Skip to content

Create an order

Save a sale from your store as a Transdirect order, so it appears in the members area under Orders and can be linked to a booking. There are two endpoints:

  • POST /api/v5/orders saves an order with every field, and can link it to a booking in the same call.
  • POST /api/v5/orders/create-simple saves a minimal order from flat fields.

Both require your API key in the api-key header. See Authentication.

POST /api/v5/orders

Send JSON. The body is strict: a field that is not in this table is rejected with 400.

FieldTypeRequiredDescription
order_idstringYes, unless transdirect_order_id is sentYour order number.
imported_fromstringNoWhere the order came from, for example csv or the name of your system. Used with order_id to find an existing order.
transdirect_order_idintegerNoThe id of a Transdirect booking to link. It must be one of your bookings. Send selected_courier with it.
selected_courierstringNoCourier key of the quote you chose on the linked booking, for example couriers_please. If the booking has no quote for that courier, or you leave it out, the order is still saved with selected_courier empty and courier_price 0, so you can choose a courier later.
courier_pricenumberNoShipping price in AUD. Stored as sent on an order with no booking linked. When you link a booking, Transdirect replaces it with the booking’s quoted price for selected_courier, or 0 if there is none.
deliveryobjectNoRecipient name, email, phone and address (all strings).
delivery_client_name, delivery_client_email, delivery_client_phone, delivery_client_addressstringNoFlat alternatives to the delivery fields. A non-empty flat field wins; an empty one falls back to the matching delivery field.
buyer_name, buyer_emailstringNoThe buyer.
goods_summarystringNoShort description of the goods.
goods_dumpstringNoRaw line-item data from your platform, stored as text.
sale_pricenumberNoOrder total in AUD.
purchased_time, paid_timestringNoWhen the order was placed and paid. ISO 8601 recommended.

Transdirect looks for an existing order with the same order_id and imported_from (with imported_from: "Woocommerce", any order on your account with that order_id matches). If it finds one, it does not change that order’s fields: it returns it with 200, after linking the booking if you sent transdirect_order_id and selected_courier. Otherwise it saves a new order with status pending and returns 201.

Terminal window
curl -X POST "https://api.transdirect.com.au/api/v5/orders" \
-H "api-key: $TD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"order_id": "WEB-1042",
"imported_from": "csv",
"buyer_name": "Jane Citizen",
"buyer_email": "jane@example.com.au",
"delivery": {
"name": "Jane Citizen",
"email": "jane@example.com.au",
"phone": "0412345678",
"address": "1 Collins Street, MELBOURNE VIC 3000"
},
"goods_summary": "2 x Ceramic planter",
"sale_price": 89.90,
"purchased_time": "2026-10-16T10:28:00+11:00"
}'
import { client, postApiV5Orders } from '@transdirect/api-sdk';
client.setConfig({ headers: { 'api-key': process.env.TD_API_KEY! } });
const { data, error, response } = await postApiV5Orders({
body: {
order_id: 'WEB-1042',
imported_from: 'csv',
buyer_name: 'Jane Citizen',
buyer_email: 'jane@example.com.au',
delivery: {
name: 'Jane Citizen',
email: 'jane@example.com.au',
phone: '0412345678',
address: '1 Collins Street, MELBOURNE VIC 3000',
},
goods_summary: '2 x Ceramic planter',
sale_price: 89.9,
purchased_time: '2026-10-16T10:28:00+11:00',
},
});
// response.status is 201 for a new order, 200 for an existing one

201 Created with the new order, or 200 OK with the existing one. The fields are described on List orders.

{
"id": 88,
"transdirect_order_id": null,
"transdirect_member_id": 12345,
"transdirect_order_status": "pending",
"order_id": "WEB-1042",
"goods_summary": "2 x Ceramic planter",
"goods_dump": "",
"imported_from": "csv",
"imported_time": "2026-10-15T23:30:00.000Z",
"purchased_time": "2026-10-16T10:28:00+11:00",
"sale_price": 89.9,
"selected_courier": "",
"courier_price": 0,
"paid_time": "",
"buyer_name": "Jane Citizen",
"buyer_email": "jane@example.com.au",
"delivery": {
"name": "Jane Citizen",
"email": "jane@example.com.au",
"phone": "0412345678",
"address": "1 Collins Street, MELBOURNE VIC 3000"
},
"last_updated": "2026-10-15T23:30:00.000Z"
}

Quote the order’s goods with Create a quote. The quote response’s id is the booking id, and each key of quotes is a courier key. Send both to the order:

{
"order_id": "WEB-1042",
"imported_from": "csv",
"transdirect_order_id": 34500123,
"selected_courier": "couriers_please"
}

Transdirect stores the booking id, the courier key and that courier’s quoted price (courier_price) on the order. Linking does not confirm the booking: confirm it with POST /api/v5/bookings/{id}/confirm and the same courier.

Confirming through the API does not change the order’s status. If you track status, set it yourself with PUT /api/v5/orders/{id}, for example to booked. Once a linked order’s status is anything other than pending, ready_to_book or quoted, confirming its booking returns 409 with {"message":"This order can no longer be booked. Refresh your orders and try again."}.

POST /api/v5/orders/create-simple

Saves an order from flat fields only. If you already have an order with this order_id (from any source), that order is returned unchanged with 200. Otherwise a new pending order is saved and returned with 201. The body is strict.

FieldTypeRequiredDescription
order_idstringYesYour non-empty order number. Missing, null or blank values return 400. Numeric references are accepted and stored as strings.
delivery_client_name, delivery_client_email, delivery_client_phone, delivery_client_addressstringNoThe recipient.
buyer_name, buyer_emailstringNoThe buyer.
goods_summarystringNoShort description of the goods.
imported_fromstringNoSource of the order. Defaults to csv.
sale_pricenumberNoOrder total in AUD. Defaults to 0.
courier_pricenumberNoShipping charged to the buyer in AUD. Defaults to 0.
Terminal window
curl -X POST "https://api.transdirect.com.au/api/v5/orders/create-simple" \
-H "api-key: $TD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"order_id": "WEB-1043",
"delivery_client_name": "Sam Lee",
"delivery_client_phone": "0298765432",
"delivery_client_address": "100 George Street, SYDNEY NSW 2000",
"goods_summary": "1 x Desk lamp",
"sale_price": 59.00
}'
import { client, postApiV5OrdersCreateSimple } from '@transdirect/api-sdk';
client.setConfig({ headers: { 'api-key': process.env.TD_API_KEY! } });
const { data, error } = await postApiV5OrdersCreateSimple({
body: {
order_id: 'WEB-1043',
delivery_client_name: 'Sam Lee',
delivery_client_phone: '0298765432',
delivery_client_address: '100 George Street, SYDNEY NSW 2000',
goods_summary: '1 x Desk lamp',
sale_price: 59,
},
});

The response is the same order shape as above, with imported_from set to csv unless you sent another value.

StatusBodyCause
400{"success":false,"error":{"name":"ZodError","message":"..."}}The body has a field that is not listed, or a value of the wrong type. message is a JSON-encoded list of the problems.
400{"error":"order_id is required"}POST /api/v5/orders with neither order_id nor transdirect_order_id.
401{"error":"missing_api_key"} or {"error":"invalid_api_key"}No key, or the key is unknown or deactivated.
403{"error":"No access to booking."}transdirect_order_id is not one of your bookings, or you sent selected_courier without transdirect_order_id on an order that has no linked booking.
429{"error":"rate_limited"}More than 600 requests in a minute on this key. Wait for the number of seconds in retry-after.
500{"error":"Failed to save order"} or {"error":"internal_error","requestId":"..."}The order could not be saved. Check List orders before retrying, so you do not save it twice.

Booking ownership is checked before saving. A rejected booking link (403) leaves the order unchanged and does not create a new order.

Open Create or update a saved order or Create a simple saved order in the API Explorer, paste your API key into the authentication box and send the request. These calls save real orders on your account; delete test orders afterwards with DELETE /api/v5/orders/{id}.