Fare Freight Get started

Fare Freight Public API

Reference for the Fare Freight Public API: live carrier rate quotes, plus consignment booking, manifesting and document downloads for orders already in Fare Freight. This page is the authoritative field-by-field reference.

Rate base URLffspaurate.farefreight.com.au
Shipment base URLany.farefreight.com.au
Auth headerX-FF-Secret-Key
FormatJSON, snake_case
Doc refFF-PUBRATE-API-v1
Effective13 Sep 2026
No sandbox environment

The base URL is live production. A request may call real carrier rate APIs and is logged against the live account. Talk to your account manager before load-testing or running automated test suites.

Getting started

Receive credentialsFare Freight provisions your accountId and X-FF-Secret-Key.
Confirm your catalog is loadedEvery variant_id you plan to quote needs weight, dimensions and freight class on file with Fare Freight — check this with your account manager before testing.
Send a real test quoteThere’s no sandbox, so use a genuine variant/address pair from your catalog against production.
Handle the responseRender rates[] to the customer; treat an empty array as “nothing available,” not an error.
Handle failuresRetry 500 once with backoff, honour Retry-After on 429, and treat 400 / 401 as integration bugs to fix rather than to retry unchanged.
Go live

Authentication

Every request carries a per-account secret key in the X-FF-Secret-Key header. Fare Freight provisions one key per accountId when your integration is set up.

HeaderValue
X-FF-Secret-KeyYour account’s secret key, issued by Fare Freight. Treat it like a password — don’t expose it in client-side/browser code.

A missing or incorrect key returns 401 with no response body. If you believe your key is compromised, contact Fare Freight to have it rotated — there is currently no self-service rotation.

Conventions

ConventionDetail
MoneyWhole cents, as an integer or integral number (e.g. 4999 = $49.99).
Weight & dimensionsManaged entirely server-side from your product catalog — not something you send or compute.
DatesISO 8601 with a UTC offset, e.g. 2026-09-16T00:00:00+10:00.
State/territoryStandard AU abbreviations: NSW, VIC, QLD, WA, SA, TAS, ACT, NT.
Field casingsnake_case in every request and response body.

Endpoint index

MethodPathHostDescription
POST/api/public/rate/{accountId}ffspaurate.farefreight.com.auReturns quotes for one cart/shipment.
POST/api/public/consignment/{accountId}any.farefreight.com.auBook a consignment with the chosen carrier.
POST/api/public/consignment-manifest/{accountId}any.farefreight.com.auBook a consignment and manifest it in one call.
POST/api/public/manifest/{accountId}any.farefreight.com.auManifest already-booked orders.
POST/api/public/download/connote/{accountId}any.farefreight.com.auDownload connotes as one merged PDF.
POST/api/public/download/manifest/{accountId}any.farefreight.com.auDownload manifests as one merged PDF.
POST/api/public/download/label/{accountId}any.farefreight.com.auDownload labels as one merged PDF.

Rate endpoint

POST/api/public/rate/{accountId}

Returns quotes for one cart/shipment. {accountId} is the integer account ID Fare Freight assigned you.

Request headers

HeaderNotes
Content-TyperequiredAlways application/json.
X-FF-Secret-KeyrequiredSee Authentication.
X-FF-Event-TypeoptionalFree-text label for your own logs on our side. Defaults to FRESH_ORDER.
X-FF-Order-IdoptionalYour internal order ID (integer), attached to our request log for tracing.
X-FF-Order-NumberoptionalYour internal order number (string), same purpose as above.

Request body schema

The body is a single rate object. Every field below is either enforced (you’ll get a 400 without it) or genuinely used in rating — nothing decorative is required.

Don’t bother computing weight or dimensions. items[].variant_id is matched against the product catalog configured on your Fare Freight account — weight, dimensions and freight class are always looked up from there and override anything you send, box path or not.

rate.origin & rate.destination

FieldTypeNotes
postal_coderequiredstringAustralian postcode. Destination is capped at 20 characters.
cityrequiredstringSuburb / locality.
provincerequiredstringState/territory code — NSW, VIC, QLD, WA, SA, TAS, ACT or NT. Sent straight to almost every connected carrier for zone rating; there’s no fallback if it’s missing, so the quote is either wrong or rejected.
emailrequired on destinationstringNeeded if your account has any customer-specific pricing rule configured. Not required on origin.
countryoptionalstringAssumed AU.
address1 / address2optionalstringStreet address. Used by some carriers (BigPost, MachShip, Allied Express, Mothership) for consignment details; others rate on postcode/suburb/state alone.
name / company_nameoptionalstringPassed through to carrier consignment labels where applicable.
address_typeoptionalstringResidential or Business — overrides your account’s default delivery-type assumption.

rate.items[]

FieldTypeNotes
variant_idrequiredintegerMust match a variant configured in your Fare Freight product catalog.
quantityrequiredinteger>= 1.
pricerequirednumberLine unit price, in cents. Drives free-shipping/margin/discount rule thresholds — a missing price is treated as $0 and silently skews any configured rule, so don’t omit it even though nothing forces the correct value.
product_idoptionalintegerNot used for rating.
name / skuoptionalstringLogging only.
properties._address_typeoptionalstringPer-item override: Residential / Business.
properties._liftgate_deliveryoptionalstringPer-item override: Y / N.

rate.order_totals

FieldTypeNotes
subtotal_pricerequirednumberSum of price × quantity across items[], in cents. Used to detect a split-shipment request (one of several parcels for the same order) — get it wrong and the wrong rate bucket gets returned.
total_priceoptionalnumberAccepted, not currently used in rating.
discount_amountoptionalnumberAccepted, not currently used in rating.

rate.currency and rate.locale are both optional and currently unused — the currency returned in the response comes from your account’s own configuration, not the request.

Sample request

# request curl -X POST “https://ffspaurate.farefreight.com.au/api/public/rate/482” \ -H “Content-Type: application/json” \ -H “X-FF-Secret-Key: <your-secret-key>” \ -d @request.json
// request.json { “rate”: { “origin”: { “postal_code”: “2015”, “city”: “Alexandria”, “province”: “NSW”, “address1”: “12 Bourke Road” }, “destination”: { “postal_code”: “3121”, “city”: “Richmond”, “province”: “VIC”, “email”: “jane.citizen@example.com”, “address1”: “48 Swan Street” }, “items”: [ { “variant_id”: 40213897, “quantity”: 2, “price”: 4999, “sku”: “TBL-OAK-120” }, { “variant_id”: 40213912, “quantity”: 1, “price”: 12500 } ], “order_totals”: { “subtotal_price”: 22498 } } }

200 response

A successful call always returns 200 — including when rates comes back empty. An empty array means no configured carrier could quote this address/cart, not an error; don’t treat it as a failure in your integration.

// 200 { “rates”: [ { “service_name”: “Business Delivery”, “service_code”: “B-FF-NFM-SYD-STD(N,N,N)”, “total_price”: 8420, “currency”: “AUD”, “description”: “Delivered to a business address with a loading dock or forklift.”, “min_delivery_date”: “2026-09-16T00:00:00+10:00”, “max_delivery_date”: “2026-09-19T00:00:00+10:00” }, { “service_name”: “Residential Delivery”, “service_code”: “R-FF-NFM-SYD-STD(Y,N,N)”, “total_price”: 9650, “currency”: “AUD”, “description”: “Delivered to a residential address.”, “min_delivery_date”: null, “max_delivery_date”: null } ] }
FieldTypeNotes
service_namestringDisplay name for the quoted service.
service_codestringStable identifier for the quoted service — keep it on your order record if you need to reference which quote was chosen.
total_priceintegerTotal price in cents.
currencystringAlways your account’s configured currency (typically AUD).
descriptionstringHuman-readable delivery description, where configured.
min_delivery_date / max_delivery_datestring or nullISO 8601 with offset. Only populated for carriers with delivery-date estimation enabled on your account; null otherwise.

Rates are sorted cheapest first.

Error responses

StatusMeaningBody
400A required field is missing or invalid. See errors[] for exactly which.{“errors”: […]}
401Missing or incorrect X-FF-Secret-Key for that accountId.empty
429Rate limit exceeded. Response carries a Retry-After header.empty
500Unexpected server-side error. Safe to retry once with backoff; contact us if it persists.Spring default error JSON
// 400 example { “errors”: [ “rate.origin.province: must not be blank”, “rate.destination.email: must not be blank”, “rate.items[0].variantId: must not be null”, “rate.orderTotals.subtotalPrice: must not be null” ] }

Field names in errors[] follow the request’s Java structure (camelCase, e.g. variantId), not the snake_case spelling you send in JSON (variant_id). Match on the trailing field name if you’re parsing these programmatically.

Shipment endpoints

These endpoints book, manifest and download documents for orders that already exist in Fare Freight (the orders synced from your Shopify store), identified by their fulfilment_order_id. They live on any.farefreight.com.au — a different host from the rate endpoint above — and use the same credentials: your accountId in the path and the X-FF-Secret-Key header. A missing or wrong key returns a bodyless 401.

MethodPathDescription
POST/api/public/consignment/{accountId}Book a consignment with the chosen carrier.
POST/api/public/consignment-manifest/{accountId}Book a consignment and manifest it in one call.
POST/api/public/manifest/{accountId}Manifest already-booked orders.
POST/api/public/download/connote/{accountId}Download connotes as one merged PDF.
POST/api/public/download/manifest/{accountId}Download manifests as one merged PDF.
POST/api/public/download/label/{accountId}Download labels as one merged PDF.

Response envelope

// response envelope { “status”: “SUCCESS”, “message”: “Consignment and manifest created successfully”, “orders”: [ { “fulfilment_order_id”: 1042, “carrier”: “MACHSHIP”, “fulfilment_status”: “Manifested”, “consignment_id”: “5518203”, “connote_number”: “FFR000123456” } ] }
statusHTTPMeaning
SUCCESS200Done.
ERROR422The carrier or Fare Freight rejected the request (e.g. already booked, already manifested). message says why.

Other errors

StatusMeaningBody
400Invalid payload, or an unknown fulfillment_type.{“errors”: […]} / {“error”: “…”}
401Missing/incorrect secret key, or the account isn’t active.empty
404A fulfilment_order_id doesn’t exist on your account, or (downloads) no document is available yet.{“error”: “…”}
409(Manifest) an order that hasn’t been booked yet.—
422Carrier/Fare Freight rejected it.—
502The carrier rejected or returned an unreadable document. Retry shortly.{“error”: “…”}

POST/api/public/consignment/{accountId} · POST/api/public/consignment-manifest/{accountId}

Same body for both. Books the order with the carrier connection you select. Supported carriers: NFM, MachShip, BigPost, KIS, Direct Freight, Allied Express and Australia Post. The body mirrors what the Fare Freight app sends when you book from the Orders screen.

Where the quote and carrier ID come from. quote is the service you selected from a Fare Freight consignment quote, and quote.ff_carrier_id is the ID of the carrier connection (Carrier Connections in the app) that should book it. The other quote fields are carrier-specific and passed through unchanged — send the quote exactly as it was returned.

Body

FieldTypeNotes
fulfilment_order_idrequiredintegerThe Fare Freight fulfilment order to book.
quoterequiredobjectSee above.
pickup_daterequiredstringYYYY-MM-DD.
from_time / to_timerequiredstringPickup window, 24-hour HH:mm.
pickup_addressrequiredobjectlocation_id (integer), city, zip, province_code required; name, address1, address2, province, country optional.
delivery_addressrequiredobjectaddress1, city, zip, province_code, customer_name required; address2, country, phone, email, company optional.
items[]requiredarrayAt least one.

Example

# request curl -X POST “https://any.farefreight.com.au/api/public/consignment-manifest/482” \ -H “Content-Type: application/json” \ -H “X-FF-Secret-Key: <your-secret-key>” \ -d @consignment.json
// consignment.json { “fulfilment_order_id”: 1042, “quote”: { “ff_carrier_id”: 5, “service”: “Business Delivery”, “service_code”: “B-FF-NFM-SYD-STD(N,N,N)”, “shipping_charge”: 84.20 }, “pickup_date”: “2026-09-21”, “from_time”: “09:00”, “to_time”: “17:00”, “items”: [ { “variant_id”: 40213897, “quantity”: 2, “height”: 30, “width”: 40, “length”: 60, “weight”: 12.5, “package_type”: “Carton” } ] }

Once an order has a connote number, booking it again as New Label is refused with 422 (“already been booked with consignment …”), so retrying after a timeout won’t double-book it — only a deliberate Reship/Return with confirm_duplicate_label creates a second booking.

consignment-manifest is not available for BigPost (BigPost has no manifest step): it returns 422 before booking anything — use consignment on its own for BigPost orders.

POST/api/public/manifest/{accountId}

Supported carriers: NFM, MachShip, KIS, Direct Freight, Allied Express (no separate manifest step — the order is simply marked manifested) and Australia Post.

Up to 100 orders per call. If any carrier group fails you get 422 with each failure in message (for example MACHSHIP: This order has already been manifested with manifest ID …), and orders shows which orders did get manifested. An order that hasn’t been booked yet returns 409.

POST/api/public/download/connote/{accountId} · POST/download/manifest/{accountId} · POST/download/label/{accountId}

Same body as the manifest call. The response is a single merged application/pdf (as a file attachment) covering every requested order; on failure you get a JSON error instead.

# request curl -X POST “https://any.farefreight.com.au/api/public/download/label/482” \ -H “Content-Type: application/json” \ -H “X-FF-Secret-Key: <your-secret-key>” \ -d ‘{“fulfilment_order_ids”: [1042, 1043]}’ \ -o labels.pdf
DocumentAvailable for
labelNFM, MachShip, Direct Freight, KIS, Allied Express, Australia Post
connoteNFM, MachShip, Allied Express, Australia Post
manifestNFM, MachShip, KIS

Requesting a document a carrier doesn’t produce returns 422. A 404 means the carrier has nothing yet — for a manifest, the order usually hasn’t been manifested. Orders on different carriers are merged into the one PDF in request order, grouped by carrier.

Rate limits

Each account is limited to a burst of 30 requests, refilling at a sustained 60 requests per minute (~1/second). Once exhausted, further calls get 429 with a Retry-After: 60 header until the bucket refills.

These defaults are set for typical integration volume. If your expected call volume is significantly higher (e.g. a live storefront checkout rather than backend/batch calls), let your account manager know so we can size your account’s limit accordingly — this is a per-account setting, not a fixed platform ceiling.

The shipment endpoints have their own per-account allowance with the same limits (burst of 30, sustained 60 per minute) — calls to one don’t use up the other’s.

Support

For credentials, catalog setup, rate-limit adjustments, or anything behaving unexpectedly, contact your Fare Freight account manager.

Fare Freight · Public API · v1 · Doc ref FF-PUBRATE-API-v1 · Effective 13 Sep 2026