Skip to content

API overview

The Transdirect API is a JSON REST API for quoting, booking, labelling and tracking shipments with Australian couriers. This page covers the rules every endpoint shares. New to the API? Start with the quickstart.

https://api.transdirect.com.au/api/v5

Send your key in the api-key header. Most endpoints need it; public tracking (GET /api/v5/tracking/{reference}), the location lookups (except validate-route), couriers and the public quote endpoint do not. See authentication.

Terminal window
curl https://api.transdirect.com.au/api/v5/member \
-H "api-key: $TD_API_KEY"
  • Send request bodies as JSON with content-type: application/json. Some endpoints also accept form-encoded bodies for older plugins, but JSON is the supported format.
  • Path ids such as {id} are the numeric Transdirect booking id, which you get from the quote response. Your own order or consignment number goes in customer_reference instead.
  • Weights are in kilograms and dimensions in centimetres.
  • Unknown fields in a quote body are dropped without an error. Some other bodies, such as booking updates and items, are strict and reject unknown fields with a 400. Check field names against the reference page or the spec.
  • Responses are usually JSON. Labels and other documents are application/pdf, the streamed quote endpoint is text/event-stream, a failed test_api_key_settings returns plain text, and a document that is not ready yet, requested with Accept: text/html, returns an HTML page instead of the JSON error.
  • Money is in Australian dollars, as numbers such as 12.93. Quote total includes GST, and applied_gst shows the GST part.
  • Timestamps are ISO 8601 with an offset. Quote responses use Sydney time with an offset that has no colon, such as 2026-10-16T15:32:38+1100. Booking responses use UTC, such as 2026-10-16T04:32:38.000Z. Always parse the offset rather than assuming a timezone. One exception: a booking’s pickup_window holds the pickup’s local wall-clock times even though the values end in Z, so read them as local times, not UTC.
  • Pickup dates are YYYY-MM-DD. Pickup times are HH:MM in the pickup address’s local time.
  • On a booking, status is a display label such as “Confirmed” that may be reworded. Write your code against status_code, the stable lowercase code such as confirmed. See the booking lifecycle.

Every response carries a cf-ray header that identifies the request. Some error bodies also include a requestId. Log both, and quote them when you contact support with the booking id and the request and response.

Check the HTTP status first. The body then explains the problem, but its shape depends on where the error came from, so do not assume one envelope.

StatusWhen
200, 201Success. POST /api/v5/quotes returns 201. POST /api/v5/orders returns 201 for a new order and 200 for an existing one.
204Success with no body, for example a confirm or a delete.
304GET /api/v5/bookings with an If-None-Match that matches its ETag.
400The request is invalid. The body says why (see the shapes below).
401The api-key header is missing, or the key is wrong or deactivated.
402The payment was declined or failed at confirm.
403The booking cannot be paid for (for example NO_PAYMENT_METHOD), or a batch includes another account’s booking.
404The booking, item or resource does not exist or is not yours, or the path is wrong.
409A document is not ready yet, or the booking can no longer be booked. Retry later or re-quote.
422The chosen courier cannot provide the tail lift this booking needs.
429Rate limited. Wait for the retry-after header.
500Something failed on our side, or a booking that is already paid was deleted.
502, 503A service we depend on is unavailable. Retry with backoff.

Simple error. Most endpoint errors are a single code:

{ "error": "booking_not_found" }

Switch on error. Examples are missing_api_key, invalid_api_key, booking_not_found, item_not_found, invalid_since, invalid_sort, rate_limited and label_not_ready. Document errors also include a message.

Field errors. Quote, booking and item rules report problems by field:

{ "errors": { "receiver": { "country": ["Invalid Country"] } } }

errors can be an object keyed by field, a list of messages, or a single string, for example {"errors":["Cannot update. Booking has been processed."]}. Show the messages to whoever can fix the data.

Validation errors. A body or parameter that does not match the schema returns one of two shapes. Both have error.name set to ZodError:

{
"error": {
"name": "ZodError",
"issues": [
{ "path": ["payment_method"], "code": "invalid_format", "message": "payment_method must be \"demo\", \"credit\", nab_<id>, or paypal_<id>" }
]
},
"requestId": "917e1baf-9e14-417e-b577-326ae42d1e7c"
}
{ "success": false, "error": { "name": "ZodError", "message": "[{\"code\":\"too_small\",\"path\":[\"reference\"],\"message\":\"Too small: expected string to have >=3 characters\"}]" } }

In the second shape, message is a string that contains a JSON list of issues. Parse it to get the field paths.

Payment and access errors at confirm:

{ "errors": { "payment": ["..."] }, "payment_error": { "code": "...", "user_message": "...", "log_id": "...", "method": "card" } }
{ "error": "Add a payment method or set up a credit account to make a live booking.", "access_error": { "code": "NO_PAYMENT_METHOD", "user_message": "..." } }

Read payment_error.code or access_error.code in code and show user_message to the person booking. See how payments work.

Wrong path. A path under /api/v5 that does not exist returns:

{ "error": "legacy_public_route_not_mounted", "path": "/api/v5/unknown-endpoint" }

Check the method and path against the reference. A literal placeholder such as {id} or [Number] left in the URL is a common cause.

Empty bodies. A few responses have no body: 401 on a HEAD request, 404 from GET /api/v5/bookings when you have no bookings yet, 404 from a booking’s item list when it has no items, and 400 from the sender or receiver endpoint when that address is missing.

Unexpected errors return 500 {"error":"internal_error","requestId":"..."}.

WhoLimit
Requests with an api-key (except POST /api/v5/bookings/public, where an API key does not lift the per-IP limit)600 per minute per key
POST /api/v5/bookings and POST /api/v5/bookings/stream without a key10 per hour per IP address
POST /api/v5/bookings/public30 per minute and 150 per 5 minutes per IP address
  • Over the limit, you get 429 and a retry-after header with the number of seconds to wait. There are no X-RateLimit-* headers, so count your own requests if you need to stay under the limit.
  • A keyed request returns {"error":"rate_limited"}. An anonymous quote returns {"error":"rate_limited_anonymous_quotes", ...} with limit and window_seconds. Quote with your API key (POST /api/v5/quotes) to get the keyed limit.
  • Back off and retry on 429, 502 and 503. Do not retry 4xx errors unchanged.

The API does not send webhooks. Poll for changes:

  • Labels: after a confirm, HEAD /api/v5/bookings/{id}/label returns 200 once the label is ready. Poll every few seconds, then GET it.
  • Tracking: poll GET /api/v5/tracking/{reference} for bookings that are in transit. A tracking request can fetch fresh scans from the courier, so keep to a modest interval per booking (for example every 30 minutes). Stop polling once a booking is delivered.
  • Bookings: GET /api/v5/bookings returns an ETag. Send it back in If-None-Match to get a 304 when nothing has changed.

List endpoints return a capped list, not pages with cursors:

  • GET /api/v5/bookings returns at most 100 bookings, newest first, and leaves out unconfirmed quotes. To walk through more, sort oldest first and move since forward, for example ?sort=booking_time&since=2026-10-01T00:00:00Z. If you use an offset such as +10:00, URL-encode the + as %2B. This is a capped list, not guaranteed pagination: more than 100 bookings with the same created_at cannot be stepped past.
  • GET /api/v5/orders returns at most 50 orders, newest first.
  • GET /api/v5/locations is paged with /api/v5/locations/page/{page} and a limit of up to 5000, and returns a next_page link while there are more.
AreaWhat it doesReference
QuotesPrice a shipment with every courier and create a draft bookingGet quotes, pickup availability
BookingsConfirm, read, update, list and delete bookingsCreate, confirm, get, list, update, delete, addresses, customs declaration
Booking itemsRead and change the parcels on a draft bookingList, get, create, update, delete
Labels and documentsLabels, A6 labels, manifests, invoices, shareable links and batchesGet a label, related documents
TrackingWhere a shipment isTrack a booking, tracking concepts
MembersYour account and saved payment methodsGet member, payment methods
LocationsSuburbs, postcodes, states and route checksList, search, by postcode, states, validate a route
CouriersCourier names and idsList couriers
Collection pointsParcel lockers and drop-off pointsCollection points
OrdersStore orders imported for bookingList, get, create, update
Account configurationSettings for a key, boxing and frequent ratesAPI key configuration, order boxing, frequent rates