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/orderssaves an order with every field, and can link it to a booking in the same call.POST /api/v5/orders/create-simplesaves a minimal order from flat fields.
Both require your API key in the api-key header. See Authentication.
Create an order
Section titled “Create an order”POST /api/v5/ordersSend JSON. The body is strict: a field that is not in this table is rejected with 400.
| Field | Type | Required | Description |
|---|---|---|---|
order_id | string | Yes, unless transdirect_order_id is sent | Your order number. |
imported_from | string | No | Where the order came from, for example csv or the name of your system. Used with order_id to find an existing order. |
transdirect_order_id | integer | No | The id of a Transdirect booking to link. It must be one of your bookings. Send selected_courier with it. |
selected_courier | string | No | Courier 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_price | number | No | Shipping 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. |
delivery | object | No | Recipient name, email, phone and address (all strings). |
delivery_client_name, delivery_client_email, delivery_client_phone, delivery_client_address | string | No | Flat alternatives to the delivery fields. A non-empty flat field wins; an empty one falls back to the matching delivery field. |
buyer_name, buyer_email | string | No | The buyer. |
goods_summary | string | No | Short description of the goods. |
goods_dump | string | No | Raw line-item data from your platform, stored as text. |
sale_price | number | No | Order total in AUD. |
purchased_time, paid_time | string | No | When 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.
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 oneResponse
Section titled “Response”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"}Link an order to a booking
Section titled “Link an order to a booking”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:
- on a new order, in the
POST /api/v5/ordersbody above, or - on an existing order, with
PUT /api/v5/orders/{id}.
{ "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."}.
Create a simple order
Section titled “Create a simple order”POST /api/v5/orders/create-simpleSaves 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.
| Field | Type | Required | Description |
|---|---|---|---|
order_id | string | Yes | Your 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_address | string | No | The recipient. |
buyer_name, buyer_email | string | No | The buyer. |
goods_summary | string | No | Short description of the goods. |
imported_from | string | No | Source of the order. Defaults to csv. |
sale_price | number | No | Order total in AUD. Defaults to 0. |
courier_price | number | No | Shipping charged to the buyer in AUD. Defaults to 0. |
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.
Errors
Section titled “Errors”| Status | Body | Cause |
|---|---|---|
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.
Try it
Section titled “Try it”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}.