Best Technology Services
BestConnect Travel API · Demo
Demo environment

BestConnect Travel API

BestCare travel units for Australian field service sites, priced by the same calculator that runs inside BestConnect Quote. Send a list of sites, get back the dispatching Point of Presence, the travel zone and the billable units for each, plus a summary.

Getting started

Three calls cover the whole service. GET /health needs no key and tells you the service is up and which calculator version it is running. GET /v1/openapi.json is the machine-readable specification. POST /v1/travel does the work.

curl -s https://api-demo.best-ts.com.au/v1/travel \
  -H "Authorization: Bearer $TRAVEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sites":[{"reference":"SITE-001","suburb":"North Sydney","postcode":"2060"}]}'

Replace the key with the one Best Technology Services issued to you. Keys are environment-specific: a demo key does not work in production.

The calculator is deterministic and holds no state between calls. Send the same sites twice and you get the same answer, so it is safe to retry a failed call.

Authentication

Every call to /v1/travel carries an API key, in either header form:

HeaderValue
AuthorizationBearer <key> (preferred)
X-Api-Key<key>

Call the API from your server, never from a browser, so the key stays out of client code. Keys can be rotated on request: a new key is issued, both work for an agreed period, then the old one is retired. A missing or unknown key returns 401.

Cost travel for a list of sites

POSThttps://api-demo.best-ts.com.au/v1/travel

The body is a JSON object with exactly one of sites or text, and an optional unitRate.

FieldTypeMeaning
sitesarray, 1 to 500Structured sites. Each needs suburb and postcode; state is optional but resolves suburbs that exist in more than one state; reference (up to 100 characters) is your own id, echoed back on the matching result.
textstringA pasted site list instead of sites: one site per line, suburb and postcode on each. Lines that cannot be read come back in skipped.
unitRatenumber, optionalAUD ex GST per BestCare unit the quote is priced at. Defaults to the list rate. Units do not depend on it; only the dollar figures in the summary and the drive-overnight conversion do.

Request

{
  "unitRate": 390,
  "sites": [
    { "reference": "SITE-001", "suburb": "North Sydney", "postcode": "2060", "state": "NSW" },
    { "reference": "SITE-002", "suburb": "Mudgee",       "postcode": "2850" },
    { "reference": "SITE-003", "suburb": "Coober Pedy",  "postcode": "5723", "state": "SA" }
  ]
}

Response

{
  "requestId": "6f1c0a3e-...",
  "calculator": { "api": "v1", "appVersion": "2.16.9", "ratesReviewed": "2026-08-15", "environment": "demo" },
  "unitRate": 390,
  "sites": [
    {
      "reference": "SITE-001",
      "input": { "suburb": "North Sydney", "postcode": "2060", "state": "NSW" },
      "pop": "Sydney", "zone": "METRO", "km": 0, "driveHours": 0,
      "bcUnits": 0, "zoneUpliftUnits": 0, "matchType": "exact",
      "flyIn": false, "regionalPlus": false, "review": false, "error": false,
      "notes": ""
    },
    {
      "reference": "SITE-002",
      "input": { "suburb": "Mudgee", "postcode": "2850" },
      "pop": "Dubbo", "zone": "REGIONAL+", "km": 140, "driveHours": 1.75,
      "bcUnits": 0.5, "zoneUpliftUnits": 0.25, "matchType": "exact",
      "flyIn": false, "regionalPlus": true, "review": false, "error": false,
      "notes": "Regional+ — beyond 100km of a regional PoP"
    },
    {
      "reference": "SITE-003",
      "input": { "suburb": "Coober Pedy", "postcode": "5723", "state": "SA" },
      "pop": "FLY-IN", "zone": "FLY-IN", "km": 850, "driveHours": null,
      "bcUnits": 7.75, "zoneUpliftUnits": 0, "matchType": "exact",
      "flyIn": true, "regionalPlus": false, "review": false, "error": false,
      "flyInDetail": {
        "airport": "CPD", "airportName": "Coober Pedy", "originPop": "Adelaide",
        "flightHours": 1.6, "airportKm": 10, "fareClass": "REGIONAL", "nightsClass": "REGIONAL",
        "fareAllowance": 650, "nights": 1, "travelHours": 10, "passSales": 1171.5
      },
      "notes": "Fly-in Adelaide to Coober Pedy (Regional, 1.6h), 10 km from airport, 1 night(s) at 1 unit: 10.0h travel on the day-rate ladder + $1171.50 pass-through incl. $650 fare"
    }
  ],
  "summary": {
    "totalSites": 3, "matched": 3, "notFound": 0, "mismatch": 0, "errorCount": 0,
    "flyIn": 1, "reviewCount": 0, "regionalPlus": 1,
    "byZone": { "METRO": 1, "REGIONAL": 0, "REGIONAL+": 1, "REMOTE": 0, "DRIVE-OVERNIGHT": 0, "FLY-IN": 1 },
    "totalBcUnits": 8.25, "zoneUpliftUnits": 0.25, "exGst": 3217.5, "gst": 321.75, "incGst": 3539.25
  }
}

Abridged from a real demo response. Results come back in input order, one per site; a site inside its PoP's included distance returns zero units and an empty notes. The header X-Request-Id carries the same id as the body.

Response fields

Each site

FieldMeaning
referenceYour reference, when you sent one.
inputThe site as it was read: suburb, postcode, state.
popThe dispatching Point of Presence: the Best location the engineer travels from. null when the address could not be matched.
zoneTravel zone (see below). null when unmatched.
km, driveHoursOne-way road distance and drive time from the PoP.
bcUnitsBillable BestCare travel units for one attendance by one engineer: the road distance beyond the PoP's included band, or the whole fly-in or drive-overnight itinerary. Excludes the zone uplift. null means the site needs a custom quote from Best; do not price it yourself.
zoneUpliftUnitsThe zone uplift to add per attendance on top of bcUnits: 0 metro, 0.25 regional and regional+, 1 remote, 0 for drive-overnight and fly-in (their itinerary is already in bcUnits). Travel per attendance at a site is bcUnits + zoneUpliftUnits.
matchTypeexact suburb and postcode matched · postcode suburb unknown, priced from the postcode · mismatch both real but they do not belong together · not_found neither recognised.
errorThe address cannot be trusted. Set for mismatch and not_found. Correct the address and resubmit; a quote must not be built from an error row. suggestion, wrongField and suggestedInput tell you what to fix and offer the corrected address.
reviewA person must look at this row before it is quoted. Set on every address error, and on sites the calculator could not price: a fly-in with no scheduled airport within reach, or a site missing distance data. Those come back with bcUnits: null and Best quotes the travel.
flyIn, flyInDetailThe site is reached by air, with the itinerary the units came from: arrival airport, origin PoP, flight hours, airport-to-site km, fare allowance, nights, travel hours and the pass-through amount.
regionalPlusDispatched from a regional PoP with travel beyond 100 km.
notesHow the units were arrived at, in words. Suitable to show to a person.

Summary

FieldMeaning
totalSites, matched, notFound, mismatchCounts by match outcome.
errorCountSites with error: true. If this is not zero, the quote is blocked until the addresses are corrected.
reviewCount, flyIn, regionalPlusSites flagged for review, reached by air, or regional-plus.
byZoneSite count per zone.
totalBcUnitsSum of bcUnits across priced sites, travel only. Sites with bcUnits: null are excluded.
zoneUpliftUnitsSum of zoneUpliftUnits across matched sites, for one attendance each.
exGst, gst, incGstDollar figures for totalBcUnits at the unitRate returned alongside. Uplifts are not included.

Zones

The zone follows from the dispatching PoP's class and the road drive time. Distances and zones are precomputed from real road routing and never estimated on the fly.

ZoneMeaning
METROServed from a metro PoP within its included distance band.
REGIONALServed by road from a metro or regional PoP, beyond the metro band and within a day's drive.
REGIONAL+Regional dispatch with travel beyond 100 km.
REMOTEWithin reach of a remote PoP.
DRIVE-OVERNIGHTReachable by road, but 3.5 to 5 hours one way, so the engineer stays overnight. Priced deterministically from the drive time, nights, car and fuel; notes spells out the itinerary.
FLY-INReached by air. Priced from the airport table where a scheduled service exists; otherwise bcUnits is null and the site is a custom quote.

Travel beyond the PoP's included distance (60 km from a metro PoP, 100 km regional, 20 km remote) accrues in quarter-unit steps per started 20 km. Regional and remote attendances also carry a zone uplift, returned separately as zoneUpliftUnits. The notes field on each site spells out the working.

Errors

Every error is JSON with the same shape. details appears on validation failures and names each offending field by JSON path.

{
  "error": {
    "code": "validation_failed",
    "message": "The request did not pass validation.",
    "requestId": "6f1c0a3e-...",
    "details": [
      { "path": "sites[1].postcode", "message": "postcode is required." }
    ]
  }
}
Statuserror.codeWhen
400invalid_jsonThe body could not be parsed.
400validation_failedA field is missing or malformed. See details.
401unauthorizedMissing or unknown API key.
404not_foundNo such route.
405method_not_allowedWrong HTTP method for the route.
413payload_too_largeBody over 1 MB.
429rate_limitedOver 120 requests in a minute. Wait Retry-After seconds.
500internal_errorThe calculator failed. Quote the requestId when you report it.

A 400 never means the sites were wrong, only the request. Address problems come back as 200 with error: true on the affected sites, so one bad address does not fail the whole list.

Limits and reliability

Changes and support

The path carries the major version. Additive changes (new optional fields, new zones) ship within v1 without notice; anything that would change the meaning of an existing field ships as v2 alongside v1, with at least three months before v1 is retired. The calculator version and the date the rates were last reviewed are on every response, so you can tell when the figures moved.

Questions, keys and problem reports: info@best-ts.com.au, or your Best Technology Services contact. Include the requestId.

Consider it done.