Skip to content

API introduction

The Transdirect API is a standard REST API with JSON responses for instant live quoting, booking, label generation, and tracking across 30+ couriers.

There are two API generations, both live today:

  • v5 — the recommended path for new integrations. Served from https://api.transdirect.com.au with the version in the path (/api/v5/...). It ships an official typed TypeScript SDK (@transdirect/api-sdk), a published OpenAPI spec at /openapi.json, and an interactive API Explorer generated from the same spec.
  • v4 — the existing API at https://www.transdirect.com.au/api. It is fully supported: every current v4 integration keeps working, and the reference pages on this site document it in full.

New integration: use v5. You get typed request/response shapes from the SDK (generated from the OpenAPI spec, so types never drift from what the API actually accepts), a machine-readable spec, and the Explorer to try calls interactively. Existing v4 integration: stay put — v4 is fully supported, and because the v5 booking routes mirror the v4 shapes (/api/v5/bookings/v4/...), your mental model carries over whenever you choose to migrate. The full comparison lives at v4 vs v5 — which should I use?.

Detailv5v4
Base URLhttps://api.transdirect.com.auhttps://www.transdirect.com.au/api
Version in path/api/v5/.../v4 on booking routes only (e.g. /api/bookings/v4/{id})
AuthenticationApi-Key headerApi-Key header or HTTP Basic (email + password)
Typed SDK@transdirect/api-sdk
FormatJSONJSON
Content-Typeapplication/jsonapplication/json
Date formatISO 8601 (e.g. 2025-08-27T14:00:00+1000)ISO 8601
CurrencyAUDAUD

API access is open by default, on both API generations. As soon as you have an API key you can:

  • Get quotes for any route immediately — no approval step.
  • Make live bookings as long as you can pay for them (see below).

A booking becomes live when one of the following is true:

  • You supply a saved payment_method (credit card or PayPal) and it charges successfully, or
  • You have a Transdirect credit account with available credit (the default when payment_method is omitted), or
  • You explicitly mark the booking as a demo.

If none of these apply, the booking is refused with a 403 Forbidden and an actionable message asking you to add a payment method or set up a credit account. A credit-account booking that would take you past your limit is refused the same way, with CREDIT_LIMIT_REACHED. There is no longer a manual “validate your account to enable API access” step.

Note that a credit account is a separate arrangement most accounts do not have — having a card saved is not the same thing. If you have no credit account you must nominate a saved method in the request, using an id from GET /api/members/payment-methods. See how payments work.

Demo mode works the same way on v4 and v5: it is a flag on your normal API key, not a separate sandbox key. You can check whether it is on via GET /bookings/v4/api_details.

You can confirm any booking as a demo (sandbox) booking — no charge, no courier transmission — by passing payment_method: "demo" when creating/confirming. Demo bookings:

  • Are placed on the synthetic Demo courier and receive a DEMO-XXXXXXXX connote.
  • Produce a watermarked test label.
  • Incur no charge and are never sent to a real courier.

See create a booking and confirm a booking for usage.

The two generations enforce different limits and signal them differently. Both return 429 Too Many Requests with a retry header when you exceed a limit — but the numbers, headers, and error bodies below are version-specific.

  • Authenticated requests (Api-Key header): 600 requests / minute.
  • Anonymous quotes: 10 per hour. To lift this, sign up for a member account and send your API key with each request — the 429 message says the same.

When you are limited, v5 responds with a lowercase retry-after header (seconds to wait) and one of these JSON bodies:

{ "error": "rate_limited" }
{
"error": "rate_limited_anonymous_quotes",
"message": "...",
"window_seconds": 3600
}

The message on the anonymous-quotes body tells you the fix directly: sign up and send your API key.

v5 does not emit X-RateLimit-* headers — those are a v4 behaviour.

v4 enforces two complementary limits per identity. An identity is your authenticated member account (when using Basic auth or an API key) or your IP address (for unauthenticated requests).

Requests per minute:

IdentityLimit
Authenticated member60 requests / minute
Unauthenticated (per IP)30 requests / minute

Concurrent in-flight requests:

IdentityLimit
Authenticated member50 simultaneous requests
Unauthenticated (per IP)25 simultaneous requests

The concurrency limit prevents a single integration from monopolising server resources by holding many long-running requests open at once. If your application needs to issue many quote requests, run them in batches that respect this limit rather than firing all of them in parallel.

Successful v4 responses include headers so you can track your usage:

HeaderMeaning
X-RateLimit-LimitMaximum requests allowed in the current window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets

Requests that exceed either v4 limit return 429 Too Many Requests with a Retry-After header and a JSON error body:

{
"message": "Rate limit exceeded. Try again in 47 seconds.",
"code": 429
}

A 401 body carries a message that says which of the two problems you have:

  • “No credentials were supplied…” — nothing we authenticate with reached the API. If your client is setting a key, it is going out under the wrong header name; where we can tell which one you used (X-Api-Key, Apikey) the message names it. v4 reads the key from Api-Key — an Authorization: Bearer header is not a scheme it accepts and is dropped before it reaches the application, so it looks the same as sending nothing.
  • “The credentials supplied were rejected…” — the key arrived and was not accepted. Check it is active and belongs to a live account.

Each API key also has an authentication circuit breaker: 10 failed authentication attempts within 5 minutes returns 429 Too Many Requests with Retry-After: 300. If you see this, fix the credentials rather than retrying — the window resets after five minutes.

These apply on both generations:

  • Implement exponential backoff and respect the retry header on any 429
  • Cache quote results where possible rather than re-requesting
  • Poll tracking at most every 5 minutes (there is no public tracking webhook)
  • Run bulk operations sequentially or in small parallel batches rather than firing everything at once

Errors are returned as JSON with an appropriate HTTP status code:

{
"error": "Invalid postcode",
"message": "The sender postcode '0000' is not a valid Australian postcode."
}
Status codeMeaning
400Bad request — check your request body
401Unauthorised — the message distinguishes credentials that were rejected from credentials that never arrived
402Payment declined — the response includes a payment_error object
403Forbidden — no payment capability, credit limit reached, or API access disabled (access_error object)
404Not found — the booking or resource doesn’t exist
422Unprocessable entity — validation errors
429Rate limited — respect the Retry-After header
500Server error — contact support if this persists