API Reference

TrukTek Developer Docs

Integrate TrukTek tools directly into your dispatch software, in-cab devices, or internal workflows. All endpoints use standard HTTP — no SDK required.

Base URL: https://www.truktek.com

Overview

TrukTek exposes four REST endpoints for external use. Three require a valid Bearer token (obtained from a TrukTek account passphrase). The Bandit endpoint also requires an active Carrier Pro subscription or trial. All endpoints accept browser session cookies too, so logged-in users on your site can call them directly.

EndpointAuthBillingDescription
POST/api/auth/device
PassphraseAny accountExchange passphrase for Bearer token
GET/api/loads
NonePublicPublic load board search
POST/api/loads/search
Bearer / cookieAny verified accountAuthenticated load search with partner matching
GET/api/loads/rate-check
Bearer / cookieAny verified accountMarket rate summary for a lane (avg/min/max RPM)
POST/api/loads/chain
Bearer / cookiePro / trialHOS-aware multi-stop load chain planner
GET/api/mileage
Bearer / cookiePro / trialZip-to-zip driving mileage
GET/api/truck-stops
Bearer / cookiePro / trialFuel stops & parking/rest areas near a city
GET/api/route-weather
Bearer / cookiePro / trialNWS weather forecast at origin, midpoint, and destination
POST/api/bandit
Bearer / cookiePro / trialBandit AI freight assistant (SSE)
POST/api/tools/bol
Bearer / cookiePro / trial (10 free anonymous uses)BOL document scanner
POST/api/tools/invoice
Bearer / cookiePro / trial (10 free anonymous uses)Invoice document processor

Authentication

API access uses a device passphrase to obtain a long-lived Bearer token. The passphrase is a four-word phrase generated on your TrukTek Profile page. Exchange it once — the token lasts 365 days.

Step 1 — Get a token

POST https://www.truktek.com/api/auth/device
Content-Type: application/json

{
  "passphrase": "amber-cargo-freight-river"
}

Response 200 OK

{
  "token": "eyJhbGciOiJIUzI1NiJ9...",
  "expiresAt": "2027-07-09T00:00:00.000Z",
  "user": {
    "id": "abc123",
    "email": "dispatch@yourcompany.com",
    "companyId": "1234567",
    "dotnumber": "1234567"
  }
}

Store the token securely. You can regenerate your passphrase from Profile at any time — doing so immediately invalidates any tokens issued from the previous one.

Step 2 — Use the token

Include the token in every request as a Bearer token in the Authorization header.

Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
StatusMeaning
200Token issued — use the token field in subsequent requests
400Missing or malformed passphrase
401Passphrase not found, or account not verified
429Too many attempts — 10 per minute per IP

GET /api/loads

Public load board search. No authentication required. Returns loads with calculated metrics including gross RPM, deadhead distance, and route coordinates.

Rate limit: 30 requests per minute per IP.

Query parameters

ParamRequiredDescription
octyNoOrigin city name
ostNoOrigin state (2-letter)
dctyNoDestination city name
dstNoDestination state (2-letter)
freightNoEquipment type: Van, Reefer, Flatbed, Tanker, Intermodal, Auto
pickupDateNoPickup date (YYYY-MM-DD)
deliveryDateNoDelivery date (YYYY-MM-DD)
hoursSliderNoMax extra drive hours vs direct route (default 999 = no limit)
milesSliderNoMax deadhead miles (default 9999 = no limit)
gross_rpmNoMinimum gross rate per mile (default 0 = no minimum)

Example request

GET https://www.truktek.com/api/loads?octy=Atlanta&ost=GA&dcty=Dallas&dst=TX&freight=Reefer

Response 200 OK

{
  "loads": [
    {
      "loadId": "abc123",
      "octy": "Atlanta",    "ost": "GA",
      "dcty": "Dallas",     "dst": "TX",
      "equip": "Reefer",
      "ratePay": 2400,
      "pickupDate": "2026-07-10T00:00:00.000Z",
      "deliveryDate": "2026-07-12T00:00:00.000Z",
      "shipperNm": "Broker Name",
      "weight": 44000,
      "length": 53,
      "loadDist": 783.4,
      "grossRpm": 2.31,
      "o2oDist": 12.1,
      "coordinates": [[lon, lat], ...]
    },
    ...
  ],
  "total": 847,
  "geo": { "olat": 33.748, "olon": -84.387, "dlat": 32.779, "dlon": -96.808 }
}
StatusMeaning
200Loads returned (may be empty array if no results)
429Rate limit exceeded — 30 requests/minute
500Search failed

Authenticated load search with partner carrier matching. Returns the same load shape as the public endpoint, but excludes loads already reserved by your company and applies partner carrier visibility rules.

Auth: Bearer token or session cookie required.

Request body (JSON)

FieldRequiredDescription
octyNoOrigin city name
ostNoOrigin state (2-letter)
dctyNoDestination city name
dstNoDestination state (2-letter)
freightNoEquipment type
pickupDateNoPickup date (YYYY-MM-DD)
deliveryDateNoDelivery date (YYYY-MM-DD)
hoursSliderNoMax extra drive hours (default 10)
milesSliderNoMax deadhead miles (default 750)
gross_rpmNoMinimum gross RPM (default 0)

Example request

POST https://www.truktek.com/api/loads/search
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
Content-Type: application/json

{
  "octy": "Atlanta",
  "ost": "GA",
  "dcty": "Dallas",
  "dst": "TX",
  "freight": "Reefer",
  "milesSlider": 300,
  "gross_rpm": 2.0
}

Response shape is identical to GET /api/loads.

StatusMeaning
200Loads returned
401Not authenticated
500Search failed

GET /api/loads/rate-check

Market rate summary for a lane. Samples up to 50 available loads and returns average, min, max, and median rate per mile (RPM) along with average gross pay.

Auth: Bearer token or session cookie required.

Query parameters

ParamRequiredDescription
octyYesOrigin city name
ostYesOrigin state (2-letter)
dctyYesDestination city name
dstYesDestination state (2-letter)
freightNoEquipment type filter (omit for all equipment)
pickupDateNoPickup date (YYYY-MM-DD)

Example request

GET https://www.truktek.com/api/loads/rate-check?octy=Atlanta&ost=GA&dcty=Dallas&dst=TX&freight=Reefer
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

Response 200 OK

{
  "lane": "Atlanta, GA → Dallas, TX",
  "equipment": "Reefer",
  "sample_count": 34,
  "avg_rpm": 2.31,
  "min_rpm": 1.87,
  "max_rpm": 3.12,
  "median_rpm": 2.24,
  "avg_pay": 1810
}

If no loads are found, sample_count is 0 and a message field explains why rather than returning rate fields.

StatusMeaning
200Rate data returned (check sample_count — may be 0)
400Missing required params or city geocoding failed
401Not authenticated
404Origin or destination city not found

POST /api/loads/chain

HOS-aware multi-stop load chain planner. Given an origin, destination, and date window, it ranks back-to-back load sequences by deadhead and gross RPM across the trip. Returns the top chains sorted by overall RPM.

HOS outputs are planning estimates and are not compliance determinations.

Auth: Bearer token or session cookie required. Requires Pro subscription or trial.

Rate limit: 10 requests per minute per IP. Requests can take 5–30 seconds depending on corridor size — set your timeout accordingly.

Request body (JSON)

FieldRequiredDescription
octyYesOrigin city name
ostYesOrigin state (2-letter)
dctyYesDestination city name
dstYesDestination state (2-letter)
startDateYesEarliest pickup date (YYYY-MM-DD)
endDateYesLatest delivery date (YYYY-MM-DD)
freightNoEquipment type filter (omit for all)
maxDeadheadNoMax empty miles between legs (default 200)

Example request

POST https://www.truktek.com/api/loads/chain
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
Content-Type: application/json

{
  "octy": "Seattle",
  "ost": "WA",
  "dcty": "Boston",
  "dst": "MA",
  "startDate": "2026-07-14",
  "endDate": "2026-07-21",
  "freight": "Van",
  "maxDeadhead": 150
}

Response 200 OK

{
  "chains": [
    {
      "loads": [
        {
          "id": "abc123",
          "octy": "Seattle",   "ost": "WA",
          "dcty": "Chicago",   "dst": "IL",
          "origLat": 47.606,   "origLon": -122.332,
          "destLat": 41.878,   "destLon": -87.629,
          "rateAmount": 3200,
          "totalMiles": 2064,
          "pickupDateMs": 1752451200000,
          "deliveryDateMs": 1752624000000,
          "equip": "Van",
          "routeCoords": [[lon, lat], ...]
        },
        {
          "id": "def456",
          "octy": "Chicago",   "ost": "IL",
          "dcty": "Boston",    "dst": "MA",
          ...
        }
      ],
      "totalMiles": 4198,
      "totalGross": 5900,
      "overallRpm": 1.41
    },
    ...
  ],
  "candidateCount": 8423,
  "searchTimeMs": 4821,
  "originLat": 47.606,
  "originLon": -122.332
}

Up to 5 chains are returned, sorted by overallRpm descending. Each chain's loads array is ordered sequentially — leg 1 → leg 2 → … → final leg.candidateCount shows how many loads were evaluated in the search.

StatusMeaning
200Chains returned (chains array may be empty if no valid sequence found)
400Missing required fields or city not found
401Not authenticated
403Trial expired or subscription inactive
429Rate limit exceeded — 10 requests/minute
500Search failed

GET /api/mileage

Returns the driving mileage between two US zip codes using TomTom lane reference data. Requires an active Pro subscription or trial.

Auth: Bearer token or session cookie required.

Query parameters

ParamRequiredDescription
fromYesOrigin zip code (5 digits)
toYesDestination zip code (5 digits)

Example request

GET https://www.truktek.com/api/mileage?from=30301&to=90210
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

curl

curl "https://www.truktek.com/api/mileage?from=30301&to=90210" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..."

Response 200 OK

{
  "from": { "zip": "30301", "city": "Atlanta", "state": "GA" },
  "to":   { "zip": "90210", "city": "Beverly Hills", "state": "CA" },
  "miles": 2183,
  "matchedLane": {
    "from": "Atlanta, GA",
    "to": "Los Angeles, CA"
  }
}

matchedLane shows the TomTom reference lane that was used to produce the mileage figure. It may differ slightly from the exact zip pair when no lane originates at the precise zip location.

StatusMeaning
200Miles returned
400Missing or invalid zip code format
401Not authenticated
403Trial expired or subscription inactive
404Zip code not found, or no route available for this zip pair

GET /api/truck-stops

Find fuel stops and truck parking / rest areas near a city. Queries TrukTek's nationwide dataset of 2,600+ fuel stops and 1,900+ rest areas, sorted by distance from the requested city.

Auth: Bearer token or session cookie required. Requires Pro subscription or trial.

Query parameters

ParamRequiredDescription
cityYesCity name to search near
stateYes2-letter state code
typeNoWhat to return: fuel, parking, or both (default: both)
radiusNoSearch radius in miles (default 50, max 500)
limitNoMax stops to return (default 20, max 100)

Example request

GET https://www.truktek.com/api/truck-stops?city=Nashville&state=TN&type=both&radius=50
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

curl

curl "https://www.truktek.com/api/truck-stops?city=Nashville&state=TN&type=fuel&radius=30" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..."

Response 200 OK

{
  "city": "Nashville",
  "state": "TN",
  "type": "both",
  "radius_miles": 50,
  "fuel_stops": 5,
  "parking_stops": 4,
  "stops": [
    {
      "name": "Love's Travel Stop #123",
      "address": "1234 Interstate Dr",
      "type": "fuel",
      "miles_away": 3.2,
      "lat": 36.1627,
      "lon": -86.7816
    },
    {
      "name": "Tennessee Welcome Center",
      "address": "Nashville, TN",
      "highway": "I-40E",
      "mile_marker": "214",
      "type": "parking",
      "miles_away": 7.1,
      "lat": 36.1900,
      "lon": -86.6500
    },
    ...
  ]
}

Results are sorted by miles_away ascending. Fuel stops include name and address. Parking / rest areas include highway and mile_marker where available.

StatusMeaning
200Stops returned (stops array may be empty if none found in radius)
400Missing city/state or invalid type parameter
401Not authenticated
403Trial expired or subscription inactive
404City not found

GET /api/route-weather

Returns NWS weather forecasts sampled at three points along a route — origin, midpoint, and destination. Each point includes up to 3 forecast periods (day/night/next day) with short forecast, wind, and temperature.

Auth: Bearer token or session cookie required. Requires Pro subscription or trial.

Query parameters

ParamRequiredDescription
origin_cityYesOrigin city name
origin_stateYesOrigin state (2-letter)
dest_cityYesDestination city name
dest_stateYesDestination state (2-letter)

Example request

GET https://www.truktek.com/api/route-weather?origin_city=Memphis&origin_state=TN&dest_city=Atlanta&dest_state=GA
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

curl

curl "https://www.truktek.com/api/route-weather?origin_city=Memphis&origin_state=TN&dest_city=Atlanta&dest_state=GA" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..."

Response 200 OK

{
  "route": "Memphis, TN → Atlanta, GA",
  "points": [
    {
      "location": "Memphis, TN",
      "periods": [
        {
          "period": "This Afternoon",
          "forecast": "Mostly Sunny",
          "detail": "Mostly sunny, with a high near 91.",
          "wind": "10 mph SW",
          "temp": "91°F"
        },
        { "period": "Tonight", "forecast": "Clear", "wind": "5 mph S", "temp": "72°F", "detail": "..." },
        { "period": "Wednesday", "forecast": "Sunny", "wind": "8 mph SW", "temp": "93°F", "detail": "..." }
      ]
    },
    {
      "location": "Midpoint",
      "periods": [...]
    },
    {
      "location": "Atlanta, GA",
      "periods": [...]
    }
  ]
}

Points with no NWS coverage (e.g. offshore midpoints) return an error string instead of periods. Weather data is sourced from the US National Weather Service and is only available for the continental US.

StatusMeaning
200Forecast returned — check individual point error fields for NWS coverage gaps
400Missing required query parameters
401Not authenticated
403Trial expired or subscription inactive
404Origin or destination city not found

POST /api/bandit

Streams responses from the Bandit AI dispatcher. Bandit can search loads, find backhaul opportunities, plan multi-stop chains, check market rates, calculate net profit and break-even RPM, verify brokers via FMCSA, pull live diesel fuel prices by region, find nearby truck stops and rest areas, manage shortlists and lane needs, look up mileage, answer HOS and trucking questions, and more. Responses are delivered as Server-Sent Events (SSE).

Auth: Bearer token or session cookie required. Requires Pro subscription or trial.

Request body

FieldRequiredDescription
messageYesThe user's plain-text message
historyNoPrevious conversation turns (OpenAI message array). Pass back whatever was returned in the done event to maintain context across turns.

Example request

POST https://www.truktek.com/api/bandit
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
Content-Type: application/json

{
  "message": "Find reefer loads from Atlanta GA to Dallas TX pickup tomorrow",
  "history": []
}

Response — SSE stream

The response is Content-Type: text/event-stream. Each event is a line beginning with data: followed by a JSON object, terminated by .

data: {"type":"tool_start","tool":"search_loads","label":"Searching Atlanta GA → Dallas TX · Reefer…"}

data: {"type":"tool_result","tool":"search_loads","label":"Found 8 loads (8 total)","ok":true}

data: {"type":"text","content":"Found 8 reefer loads from Atlanta to Dallas picking up tomorrow."}

data: {"type":"text","content":" Best rate is $2.31/mi ($1,940 total). Want me to shortlist the top 3?"}

data: {"type":"done","history":[...]}

SSE event types

typeFieldsDescription
textcontentStreamed text token from the model
tool_starttool, labelA tool call is beginning
tool_resulttool, label, okTool call completed (ok=false means an error)
donehistoryTurn complete. Pass history back on the next request to maintain context.
errormessageUnrecoverable error in the agent loop

Reading the stream — JavaScript example

const res = await fetch("https://www.truktek.com/api/bandit", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9...",
  },
  body: JSON.stringify({ message: "Find reefer loads Atlanta to Dallas", history: [] }),
});

const reader = res.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
let history = [];

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });

  const parts = buffer.split("\n\n");
  buffer = parts.pop() ?? "";

  for (const part of parts) {
    if (!part.startsWith("data: ")) continue;
    const event = JSON.parse(part.slice(6));

    if (event.type === "text") process.stdout.write(event.content);
    if (event.type === "done") history = event.history; // save for next turn
  }
}
StatusMeaning
200Stream opened — SSE events follow
401Not authenticated
403Trial expired or subscription inactive

POST /api/tools/bol

Extracts structured data from a Bill of Lading image or PDF using Gemini Vision. Returns shipper, consignee, addresses, commodity, weight, reference numbers, and special handling instructions as formatted HTML.

Auth: Bearer token or session cookie. Anonymous users get 10 free lifetime uses — authenticated Pro/trial users get unlimited.

Request

Send the file as multipart/form-data with field name file. Supported formats: JPG, PNG, PDF. Max size: 4 MB (compress images before sending if needed).

POST https://www.truktek.com/api/tools/bol
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
Content-Type: multipart/form-data

file: <BOL image or PDF>

curl

curl -X POST "https://www.truktek.com/api/tools/bol" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
  -F "file=@/path/to/bol.jpg"

Response 200 OK

{
  "result": "<h3>Shipper</h3><p><strong>Name:</strong> ABC Freight Co</p>...",
  "remaining": null
}

remaining is null for authenticated users (no cap). For anonymous users it shows how many free scans remain. Processing typically takes 10–20 seconds — set your timeout to at least 60 seconds.

StatusMeaning
200Result field contains extracted HTML
400No file provided
401Not authenticated (Bearer token only — anonymous OK for free tier)
402Subscription required or anonymous quota exhausted
429Rate limit exceeded
502Processing service temporarily unavailable — retry

POST /api/tools/invoice

Extracts structured data from a carrier invoice or freight bill. Returns shipper, receiver, load number, invoice/due dates, line item charges, fuel surcharge, accessorials, and total amount due as formatted HTML.

Auth: Same as BOL Scanner — Bearer token or session cookie. 10 free anonymous uses.

Request

POST https://www.truktek.com/api/tools/invoice
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
Content-Type: multipart/form-data

file: <invoice image or PDF>

curl

curl -X POST "https://www.truktek.com/api/tools/invoice" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
  -F "file=@/path/to/invoice.pdf"

Response 200 OK

{
  "result": "<h3>Invoice</h3><p><strong>Invoice #:</strong> INV-2024-1089</p>...",
  "remaining": null
}
StatusMeaning
200Result field contains extracted HTML
400No file provided
402Subscription required or anonymous quota exhausted
429Rate limit exceeded
502Processing service temporarily unavailable — retry

Error codes

All error responses return JSON with an error field describing the issue.

// Example error response
{
  "error": "trial_expired"
}
StatusMeaning
400Bad request — missing required fields or invalid format
401Unauthenticated — missing or invalid token
402Payment required — trial expired, subscription inactive, or quota exhausted
403Forbidden — authenticated but not permitted (e.g. not admin)
404Resource not found (e.g. zip code not in database)
429Too many requests — slow down
500Internal server error
502Upstream processing service unavailable — retry after a few seconds

Rate limits

Limits are applied per IP address. Authenticated users share the same limits.

EndpointLimit
POST /api/auth/device10 requests / minute
GET /api/loads30 requests / minute per IP
POST /api/loads/searchNo hard limit — fair use expected
GET /api/loads/rate-checkNo hard limit — fair use expected
POST /api/loads/chain10 requests / minute per IP — can take 5–30s, set timeout ≥ 60s
GET /api/mileageNo hard limit — fair use expected
GET /api/truck-stopsNo hard limit — fair use expected
GET /api/route-weatherNo hard limit — NWS upstream may throttle; allow 2–5s per request
POST /api/banditNo hard limit — each request can take up to 60 seconds
POST /api/tools/bolNo hard limit — processing takes 10–20s, set timeout ≥ 60s
POST /api/tools/invoiceNo hard limit — processing takes 10–20s, set timeout ≥ 60s

Ready to integrate?

Create a TrukTek account, get approved, and generate your device passphrase from your Profile page. Need a custom integration, higher limits, or Enterprise API access? Talk to us.