Skip to content

Create a quote

Price a shipment with every courier available to your key. The response is a draft booking with one quote per courier.

POST /api/v5/quotes

Requires your API key in the api-key header. Send the body as JSON with Content-Type: application/json.

Each call creates a new draft booking with status new. Nothing is charged or sent to a courier until you confirm it. Read How quoting works for the concepts behind this page.

FieldTypeRequiredDescription
senderobjectYesPickup address. See Address fields.
receiverobjectYesDelivery address. See Address fields.
itemsarrayYesAt least one item. See Item fields.
goods_descriptionstringNoWhat is inside the parcels, for example "Books". description is accepted as the same field.
declared_valuenumberNoValue of the goods in AUD, which sets the transit warranty cover. Defaults to 0, no cover. Must not be negative.
include_warrantybooleanNoDefaults to true, so a non-zero declared_value adds the warranty fee. false quotes without warranty and sets declared_value to 0. See transit warranty.
tailgate_pickupbooleanNoAsk for a tail lift truck at pickup. Only applies when an item is over 25 kg.
tailgate_deliverybooleanNoAsk for a tail lift truck at delivery. Only applies when an item is over 25 kg.
pickup_datestringNoPreferred pickup date, YYYY-MM-DD. Must not be before today in Sydney.
instructionsobjectNo{"pickup": "...", "delivery": "..."}, free-text notes for the drivers. Any delivery text is saved as authority to leave at the front door followed by your text, for example "Authority to leave at front door;Leave at reception".
customer_referencestringNoYour own reference, such as an order number. Up to 80 characters, trimmed. Saved on the booking and returned in the response.
referrer, requesting_sitestringNoFree text saved on the booking to record where the request came from, for example your app name and your site address.
FieldTypeRequiredDescription
postcodestringYesFor Australia, a 4-digit postcode that exists. Send it as a string to keep leading zeros ("0800").
suburbstringYesMust belong to the postcode. Use Search locations to find valid pairs.
statestringYes, unless it can be filled inFor Australia one of NSW, VIC, QLD, WA, SA, TAS, ACT, NT. Filled in from the suburb and postcode if you leave it out.
countrystringYesTwo-letter country code, for example AU.
typestringYesbusiness or residential.
namestringTo confirmContact name, up to 255 characters.
company_namestringTo confirm a business addressUp to 255 characters.
addressstringTo confirmStreet address, up to 255 characters.
address2stringNoSecond street address line, up to 255 characters.
emailstringTo confirmMust be a valid email address when not empty.
phonestringTo confirmUp to 50 characters.

Fields marked “To confirm” are not needed for a quote, but confirm fails without them. Send them in the quote, or add them later with Update a booking.

FieldTypeRequiredDescription
descriptionstringYesThe package type, for example Carton, Satchel or Pallet. See the package types.
weightnumberRecommendedWeight of one package in kilograms. Up to 2000.
length, width, heightnumberRecommendedDimensions of one package in centimetres. Up to 500 each.
quantityintegerYesNumber of identical packages. Up to 999.
skustringNoYour product SKU.

If you leave out a weight or dimension, your key’s default package size is used, so send real measurements. See Items and packaging.

Terminal window
curl -X POST https://api.transdirect.com.au/api/v5/quotes \
-H "api-key: $TD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sender": {
"name": "Sam Taylor",
"company_name": "Example Books Pty Ltd",
"email": "dispatch@example.com",
"phone": "0291234567",
"address": "1 Martin Place",
"suburb": "SYDNEY",
"postcode": "2000",
"state": "NSW",
"country": "AU",
"type": "business"
},
"receiver": {
"name": "Jordan Lee",
"email": "jordan@example.com",
"phone": "0398765432",
"address": "200 Collins Street",
"suburb": "MELBOURNE",
"postcode": "3000",
"state": "VIC",
"country": "AU",
"type": "residential"
},
"items": [
{ "description": "Carton", "weight": 5, "length": 40, "width": 30, "height": 20, "quantity": 1 }
],
"goods_description": "Books",
"declared_value": 0,
"customer_reference": "ORDER-1042"
}'

With the TypeScript SDK, using the same body:

import { client, postApiV5Quotes } from '@transdirect/api-sdk';
client.setConfig({ headers: { 'api-key': process.env.TD_API_KEY! } });
const { data: quote, error } = await postApiV5Quotes({
body: {
sender: {
name: 'Sam Taylor', company_name: 'Example Books Pty Ltd', email: 'dispatch@example.com', phone: '0291234567',
address: '1 Martin Place', suburb: 'SYDNEY', postcode: '2000', state: 'NSW', country: 'AU', type: 'business',
},
receiver: {
name: 'Jordan Lee', email: 'jordan@example.com', phone: '0398765432',
address: '200 Collins Street', suburb: 'MELBOURNE', postcode: '3000', state: 'VIC', country: 'AU', type: 'residential',
},
items: [{ description: 'Carton', weight: 5, length: 40, width: 30, height: 20, quantity: 1 }],
goods_description: 'Books',
declared_value: 0,
customer_reference: 'ORDER-1042',
},
});
if (error) throw new Error(JSON.stringify(error));
// quotes is an object keyed by courier id. Sort it yourself.
const cheapest = Object.entries(quote.quotes).sort(([, a], [, b]) => a.total - b.total)[0];
console.log(`Booking ${quote.id}: ${cheapest?.[0]} at $${cheapest?.[1].total}`);

201 Created. The draft booking, with a quote from each courier that priced the shipment. This example is shortened to two quotes and two quote errors; a real response usually has more of each.

{
"id": 623630,
"booked_at": "2026-10-16T15:13:34+1100",
"booked_by": "sender",
"created_at": "2026-10-16T15:13:34+1100",
"updated_at": "2026-10-16T15:13:34+1100",
"status": "new",
"status_code": "new",
"declared_value": 0,
"insured_value": 0,
"description": "Books",
"customer_reference": "ORDER-1042",
"items": [
{ "id": 46885332, "description": "Carton", "weight": 5, "length": 40, "width": 30, "height": 20, "quantity": 1, "sku": false }
],
"sender": {
"id": 69194889,
"name": "Sam Taylor",
"company_name": "Example Books Pty Ltd",
"email": "dispatch@example.com",
"phone": "0291234567",
"address": "1 Martin Place",
"address2": "",
"suburb": "SYDNEY",
"postcode": "2000",
"state": "NSW",
"country": "AU",
"type": "business"
},
"receiver": {
"id": 69194890,
"name": "Jordan Lee",
"company_name": "",
"email": "jordan@example.com",
"phone": "0398765432",
"address": "200 Collins Street",
"address2": "",
"suburb": "MELBOURNE",
"postcode": "3000",
"state": "VIC",
"country": "AU",
"type": "residential"
},
"quotes": {
"aramex": {
"total": 12.93,
"price_insurance_ex": 12.93,
"fee": 0,
"applied_gst": 1.18,
"insured_amount": 0,
"service": "road",
"transit_time": "2 Business Days",
"transit": { "text": "2 Business Days", "type": "business_days", "min_days": 2, "max_days": 2 },
"pickup_dates": ["2026-10-19", "2026-10-20", "2026-10-21", "2026-10-22", "2026-10-23", "2026-10-26", "2026-10-27", "2026-10-28", "2026-10-29", "2026-10-30"],
"pickup_time": { "from": "09:00", "to": "16:00" },
"pickupAvailability": {
"dates": ["2026-10-19", "2026-10-20", "2026-10-21", "2026-10-22", "2026-10-23", "2026-10-26", "2026-10-27", "2026-10-28", "2026-10-29", "2026-10-30"],
"dateLabels": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"times": [{ "from": "09:00", "to": "16:00" }],
"earliest": {
"day": "Monday",
"date": "2026-10-19",
"time": { "from": "09:00", "to": "16:00" },
"times": [{ "from": "09:00", "to": "16:00" }],
"readyFromTimes": ["09:00"],
"lastAvailableTimes": ["16:00"]
},
"pickupWindow": {
"operatingStart": "09:00",
"operatingEnd": "16:00",
"displayStart": "09:00",
"displayEnd": "16:00",
"sameDayCutoff": "14:00",
"minWindowMinutes": 0,
"incrementMinutes": 30,
"fixed": true,
"currentTimeInPickupTz": "15:13",
"senderUtcOffsetMinutes": 660
},
"readyFromTimes": ["09:00"],
"lastAvailableTimes": ["16:00"],
"todayReadyFromTimes": [],
"fixedPickupTime": true
},
"pickup_window": {
"operatingStart": "09:00",
"operatingEnd": "16:00",
"displayStart": "09:00",
"displayEnd": "16:00",
"sameDayCutoff": "14:00",
"minWindowMinutes": 0,
"incrementMinutes": 30,
"fixed": true,
"currentTimeInPickupTz": "15:13",
"senderUtcOffsetMinutes": 660
},
"pickup_ready_from_times": ["09:00"],
"pickup_last_available_times": ["16:00"],
"rate_card_code": "",
"tiers": [
{
"identifier": 2,
"description": "Multipickup 3 Price (Minimum 3 consignments per collection)",
"total": 10.18,
"price_insurance_ex": 10.18,
"fee": 0,
"applied_gst": 0.93,
"insured_amount": 0
}
]
},
"tnt_road_express": {
"total": 51.58,
"price_insurance_ex": 51.58,
"fee": 0,
"applied_gst": 4.69,
"insured_amount": 0,
"service": "road",
"transit_time": "1 Business Day",
"transit": { "text": "1 Business Day", "type": "business_days", "min_days": 1, "max_days": 1 },
"pickup_dates": ["2026-10-19", "2026-10-20", "2026-10-21", "2026-10-22", "2026-10-23", "2026-10-26", "2026-10-27", "2026-10-28", "2026-10-29", "2026-10-30"],
"pickup_time": { "from": "07:00", "to": "19:00" },
"pickup_cutoff": "15:00",
"pickup_window": {
"operatingStart": "07:00",
"operatingEnd": "19:00",
"displayStart": "07:00",
"displayEnd": "19:00",
"sameDayCutoff": "16:00",
"minWindowMinutes": 120,
"incrementMinutes": 30,
"fixed": false,
"currentTimeInPickupTz": "15:13",
"senderUtcOffsetMinutes": 660
},
"pickup_ready_from_times": ["07:00", "07:30", "08:00", "08:30", "09:00", "09:30", "10:00", "10:30", "11:00", "11:30", "12:00", "12:30", "13:00", "13:30", "14:00", "14:30"],
"pickup_last_available_times": ["09:00", "09:30", "10:00", "10:30", "11:00", "11:30", "12:00", "12:30", "13:00", "13:30", "14:00", "14:30", "15:00", "15:30", "16:00", "16:30", "17:00", "17:30", "18:00", "18:30", "19:00"],
"rate_card_code": "76"
}
},
"quote_errors": [
{ "courier": "allied_pallet", "code": "no_service", "serviceability": "route.no_residential", "retryable": false },
{ "courier": "team_global_express", "code": "no_service", "serviceability": "service.unavailable", "retryable": false }
],
"label": "https://www.transdirect.com.au/api/bookings/623630/label",
"notifications": { "email": false, "sms": false },
"pickup_window": ["2026-10-16T09:00:00+1100", "2026-10-16T17:00:00+1100"],
"connote": null,
"charged_weight": 0,
"scanned_weight": 0,
"special_instructions": "",
"pickup_instructions": null,
"tailgate_pickup": false,
"tailgate_delivery": false,
"meta": {
"api_version": "v5",
"cache": { "status": "BYPASS" },
"timing": { "duration_ms": 2371, "boxing_duration_ms": 0 },
"anonymous": false,
"quote_count": 2
}
}

TNT’s quote in a real response also carries a pickupAvailability object, left out here for length. This quote was made at 15:13 on a Friday. Aramex’s same-day cutoff is 14:00, and this TNT depot’s cutoff is 15:00 (pickup_cutoff), so both start on Monday. pickup_cutoff is the per-quote collection cutoff where a courier gives one, and it can be earlier than pickup_window.sameDayCutoff.

FieldDescription
idThe draft booking id. Use it to confirm, update or delete the booking. A failed draft save returns 500 booking_persist_failed instead of a successful response with id: null.
status, status_codeBoth "new" on a fresh quote.
quotesOne entry per courier that priced the shipment, keyed by the courier id you send as courier when you confirm. Sort by total yourself. Field meanings are in How quoting works.
quote_errorsOne entry per courier that did not price it. Check this before you call a price the cheapest. See quote errors.
service_noticesOptional. Couriers that are temporarily unavailable, as {courier, kind, message}.
customer_referenceThe reference you sent, or null if it could not be saved. Present only when you sent one. Set it again with Update a booking if it is null.
sender, receiver, itemsWhat was saved on the draft.
description, declared_valueThe goods description and declared value saved on the draft.
special_instructions, pickup_instructionsThe delivery and pickup instructions saved on the draft.
labelDo not use. Fetch labels with GET /api/v5/bookings/{id}/label after you confirm.
pickup_window, connote, charged_weight, scanned_weightPlaceholders on a draft. Read them from Get a booking once the booking is confirmed.
metaDiagnostics, such as timing. Do not build logic on it.
StatusBodyCause
400{"success":false,"error":{"name":"ZodError","message":"..."}}The body does not match the schema, for example sender is not an object, pickup_date is in the past or customer_reference is over 80 characters. message is a JSON string listing each problem.
400{"error":{"name":"ZodError","issues":[...]},"requestId":"..."}The same kind of problem when the request is sent without Content-Type: application/json.
400{"errors":{"receiver":{"suburb":["Invalid Suburb"]}}}An address failed a check: a missing field, a postcode that does not exist, a suburb that is not in the postcode, or a bad type, country or email. May also include substituted_fields when a value came from your key’s settings rather than your request.
400{"errors":{"items":[{"weight":["Weight must be 2000 kg or less."]}]}}An item is missing a value, is over a limit, or has an unknown package type. A request with no items returns {"errors":{"items":["Required"]}}.
400{"status":"error","message":"Please submit separate orders as these products ship from different Warehouses"}Your key uses multiple warehouses and the items’ SKUs belong to more than one warehouse. Quote each warehouse’s items separately.
401{"error":"missing_api_key"} or {"error":"invalid_api_key"}No key, or a key that is not active.
404{"error":"unknown_member","member_id":123}The account behind the key could not be loaded.
429{"error":"rate_limited"}More than 600 requests a minute on this key. Wait for the retry-after seconds.
500{"error":"booking_persist_failed"}The quote was priced but the draft could not be saved. No booking id exists; retry the quote request.
503{"error":"reference_data_unavailable","message":"Quote reference data is temporarily unavailable. Please try again."}A temporary problem on Transdirect’s side. Try again.

A courier that cannot quote is not an error: the request still returns 201, and the courier appears in quote_errors.

Open the API Explorer, paste your API key into the authentication box, and find Create a standard API quote. Each request creates a real draft booking on your account. Use demo mode to test confirming without charges.