Datashift Freight API · v0.1.0
API Reference
Carrier-agnostic freight orchestration. Rate-shop and book shipments across all your configured carrier accounts from a single API.
https://datashift.com.au/api/freightAuth: Authorization: Bearer dsfrt_<64-hex-chars>Connectors
/connectorslistConnectorsList active connectors
Returns all active carrier connectors for the authenticated tenant. Use the `id` values as `connectorId` in rate and booking requests. Credentials are never included in the response.
Responses
200Active connectors for this tenantConnectorListResponse
401Missing or invalid API keyError
403Freight access is not active for this tenantError
Rates
/ratesgetAllRatesGet rates from all active connectors
Fans out to every active carrier connector for the authenticated tenant and returns all available services. Uses `Promise.allSettled` — one carrier being down does not fail the request; its `error` entry is included in the response instead.
Request body
RateRequest
Responses
200Rate results from all connectors. Each entry is either a successful carrier result or an error — check `success` to distinguish.AggregatedRateResponse
400Invalid request — validation failed or carrier rejected inputError
401Missing or invalid API keyError
403Freight access is not active for this tenantError
/{connectorId}/ratesgetConnectorRatesGet rates from a specific connector
Queries a single carrier connector. Set `serviceCode` to get pricing for one service only; omit it to receive all available services.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
| connectorId | path | ✓ | Database ID of the carrier connector account (from `GET /connectors`) |
Request body
RateRequest
Responses
200Available rated services for this connectorRatedService[]
400Invalid request — validation failed or carrier rejected inputError
401Missing or invalid API keyError
403Freight access is not active for this tenantError
404Connector not found or not active for this tenantError
502Carrier API returned an error or is unavailableError
Bookings
/{connectorId}/bookingscreateBookingCreate a booking
Submits a booking to the carrier. On success, returns an `orderNumber` and `consignmentNumber` (if assigned immediately by the carrier). **Collection time rules (TNT AU):** `collectionDateTime` must be 07:00–17:00 AEST, `collectionCloseTime` must be 13:00–19:00 AEST, and the window between them must be ≥ 120 minutes. Violations return 400 with a structured `errors[]` list.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
| connectorId | path | ✓ | Database ID of the carrier connector account (from `GET /connectors`) |
Request body
BookingRequest
Responses
201Booking created successfullyBookingResponse
400Invalid request — validation failed or carrier rejected inputError
401Missing or invalid API keyError
403Freight access is not active for this tenantError
404Connector not found or not active for this tenantError
502Carrier API returned an error or is unavailableError
Shipments
/shipmentslistShipmentsList shipments
Returns shipments for the authenticated tenant, most recent first. Use `limit` and `offset` to page through results. Poll this endpoint to detect when `consignmentNumber` becomes available for carriers that assign it asynchronously.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
| limit | query | — | Number of shipments to return (1–200, default 50) |
| offset | query | — | Number of shipments to skip for pagination (default 0) |
Responses
200Shipment listShipmentListResponse
401Missing or invalid API keyError
403Freight access is not active for this tenantError
/shipments/{id}getShipmentGet shipment detail
Returns full detail for a single shipment including sender, collection, and receiver addresses, item dimensions, and booking metadata.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
| id | path | ✓ | Datashift shipment ID (from booking response or `GET /shipments`) |
Responses
200Shipment detailShipmentDetailResponse
401Missing or invalid API keyError
403Freight access is not active for this tenantError
404Connector not found or not active for this tenantError
/shipments/{id}/labelgetShipmentLabelGet shipment label
Returns the PDF shipping label for a booked shipment. **Label availability:** Most carriers (including TNT AU) generate the label at booking time. If the label is not yet available, this endpoint returns 404 with `code: LABEL_NOT_AVAILABLE` — poll with exponential backoff until it becomes available. **Response format:** `application/pdf`. Save as a file or pipe directly to a label printer.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
| id | path | ✓ | Datashift shipment ID (from booking response or `GET /shipments`) |
Responses
200PDF label401Missing or invalid API keyError
403Freight access is not active for this tenantError
404Shipment not found, or label not yet available from the carrier. Check `code` — `LABEL_NOT_AVAILABLE` means retry; anything else means the shipment ID is wrong.LabelNotAvailableError
Schemas
ConnectorSummary
{
id: string // Use as `connectorId` in rate and booking requests
carrier: TNT_AU | BEX_AU
name: string // Human-readable label for this connector
}ConnectorListResponse
{
connectors: ConnectorSummary[]
}Address
{
suburb: string
postcode: string
state: string
residential: boolean // Whether this is a residential address. Triggers a residential surcharge on collection (RSP) or delivery (RSD) where applicable.
}BookingAddress
{
companyName: string
contactName: string
phoneAreaCode: string
phoneNumber: string
address1: string
address2?: string
suburb: string
state: string
postcode: string
}Package
{
count: integer
lengthCm: number
widthCm: number
heightCm: number
weightKg: number
}RateRequest
{
from: Address
to: Address
packages: Package[]
dangerousGoods: boolean
date?: string // Shipping date (YYYY-MM-DD). Defaults to today in AEST if omitted.
localDateTime?: string // Current local time in AEST (yyyy-MM-ddTHH:mm:ss, no TZ suffix). Used by TNT to determine booking cutoff eligibility. Defaults to current AEST time if omitted.
serviceCode?: string | null // If set, returns pricing for this service only. Omit (or pass null) to receive all available services.
}RatedService
{
serviceCode: string
description: string
price: number
currency: string
eta?: string | null // Estimated delivery datetime (ISO 8601, no TZ suffix)
bookingCutoff: string // Latest time to book for this service today (HH:mm:ss)
collectionCutoff: string // Latest time for courier collection today (HH:mm:ss)
}AggregatedRateResult
{
connectorId: string
carrier: string
success: boolean
rates?: RatedService[] // Present when success is true
error?: CarrierError // Present when success is false
}AggregatedRateResponse
{
results: AggregatedRateResult[]
}Items
{
count: integer
totalWeightKg: number
maxLengthCm: number
maxWidthCm: number
maxHeightCm: number
}BookingRequest
{
sender: BookingAddress
collection: BookingAddress // Collection address — often the same as sender but can differ (e.g. a warehouse pickup for an office-based account).
receiver: BookingAddress
items: Items
packagingCode: CT | BX | SA | PA | EN | CR | DR | RO | BG | PC // TNT AU packaging codes: `CT` — Carton, `BX` — Box, `SA` — Satchel, `PA` — Pallet, `EN` — Envelope
serviceCode: string // Carrier service code from a prior `getRates` call
collectionDateTime: string // Pickup ready time in AEST local time, no TZ suffix. Must be 07:00–17:00 AEST, ≥ 120 minutes before collectionCloseTime.
collectionCloseTime: string // Premises close time in AEST local time as hhmm string. Must be 13:00–19:00 AEST.
payer: Sender | Receiver | ThirdParty
payerAccountNumber?: string // Account number to charge when `payer` is `Receiver` or `ThirdParty`. Not required when `payer` is `Sender` (the connector's own account is charged).
dangerousGoods: boolean
customerReference?: string
specialInstructions?: string
}BookingResponse
{
orderNumber: string // Booking reference issued by the carrier.
consignmentNumber?: string | null // Consignment/tracking number. Present immediately for some carriers (e.g. TNT AU); null for carriers that issue it asynchronously.
connectorId: string
}ShipmentSummary
{
id: string // Datashift shipment ID
carrier: TNT_AU | BEX_AU
connectorName: string
orderNumber: string
consignmentNumber?: string | null // Null if not yet assigned by the carrier
status: BOOKED | CANCELLED
serviceCode: string
source: API | PORTAL // Whether the shipment was booked via the API or the portal UI
fromSuburb?: string | null
toSuburb?: string | null
createdAt: string
}ShipmentListResponse
{
total: integer // Total shipment count for this tenant (may exceed the current page)
limit: integer // Page size used for this response
offset: integer // Offset used for this response
shipments: ShipmentSummary[]
}ShipmentDetail
ShipmentSummary & { payer: Sender | Receiver | ThirdParty sender: BookingAddress collection: BookingAddress receiver: BookingAddress items: Items collectionDateTime: string collectionCloseTime: string customerReference?: string | null specialInstructions?: string | null }
ShipmentDetailResponse
{
shipment: ShipmentDetail
}LabelNotAvailableError
{
message: string
code: LABEL_NOT_AVAILABLE
}CarrierError
{
message: string
code?: string
}Error
{
message: string
errors?: {
message: string
field?: string // Field path for validation errors (e.g. `sender.postcode`)
code?: string // Carrier error code for carrier-returned errors
}[] // Validation errors use `{ field, message }`; carrier errors use `{ code, message }`
}