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.
| Endpoint | Auth | Billing | Description |
|---|---|---|---|
POST /api/auth/device | Passphrase | Any account | Exchange passphrase for Bearer token |
GET /api/loads | None | Public | Public load board search |
POST /api/loads/search | Bearer / cookie | Any verified account | Authenticated load search with partner matching |
GET /api/loads/rate-check | Bearer / cookie | Any verified account | Market rate summary for a lane (avg/min/max RPM) |
POST /api/loads/chain | Bearer / cookie | Pro / trial | HOS-compliant multi-stop load chain planner |
GET /api/mileage | Bearer / cookie | Pro / trial | Zip-to-zip driving mileage |
POST /api/bandit | Bearer / cookie | Pro / trial | Bandit AI freight assistant (SSE) |
POST /api/tools/bol | Bearer / cookie | Pro / trial (10 free anonymous uses) | BOL document scanner |
POST /api/tools/invoice | Bearer / cookie | Pro / 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...
| Status | Meaning |
|---|---|
| 200 | Token issued — use the token field in subsequent requests |
| 400 | Missing or malformed passphrase |
| 401 | Passphrase not found, or account not verified |
| 429 | Too 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
| Param | Required | Description |
|---|---|---|
| octy | No | Origin city name |
| ost | No | Origin state (2-letter) |
| dcty | No | Destination city name |
| dst | No | Destination state (2-letter) |
| freight | No | Equipment type: Van, Reefer, Flatbed, Tanker, Intermodal, Auto |
| pickupDate | No | Pickup date (YYYY-MM-DD) |
| deliveryDate | No | Delivery date (YYYY-MM-DD) |
| hoursSlider | No | Max extra drive hours vs direct route (default 999 = no limit) |
| milesSlider | No | Max deadhead miles (default 9999 = no limit) |
| gross_rpm | No | Minimum 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 }
}| Status | Meaning |
|---|---|
| 200 | Loads returned (may be empty array if no results) |
| 429 | Rate limit exceeded — 30 requests/minute |
| 500 | Search failed |
POST /api/loads/search
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)
| Field | Required | Description |
|---|---|---|
| octy | No | Origin city name |
| ost | No | Origin state (2-letter) |
| dcty | No | Destination city name |
| dst | No | Destination state (2-letter) |
| freight | No | Equipment type |
| pickupDate | No | Pickup date (YYYY-MM-DD) |
| deliveryDate | No | Delivery date (YYYY-MM-DD) |
| hoursSlider | No | Max extra drive hours (default 10) |
| milesSlider | No | Max deadhead miles (default 750) |
| gross_rpm | No | Minimum 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.
| Status | Meaning |
|---|---|
| 200 | Loads returned |
| 401 | Not authenticated |
| 500 | Search 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
| Param | Required | Description |
|---|---|---|
| octy | Yes | Origin city name |
| ost | Yes | Origin state (2-letter) |
| dcty | Yes | Destination city name |
| dst | Yes | Destination state (2-letter) |
| freight | No | Equipment type filter (omit for all equipment) |
| pickupDate | No | Pickup 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.
| Status | Meaning |
|---|---|
| 200 | Rate data returned (check sample_count — may be 0) |
| 400 | Missing required params or city geocoding failed |
| 401 | Not authenticated |
| 404 | Origin or destination city not found |
POST /api/loads/chain
HOS-compliant multi-stop load chain planner. Given an origin, destination, and date window, finds the best sequences of back-to-back loads that minimize deadhead and maximize gross RPM across the full trip. Returns the top chains sorted by overall RPM.
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)
| Field | Required | Description |
|---|---|---|
| octy | Yes | Origin city name |
| ost | Yes | Origin state (2-letter) |
| dcty | Yes | Destination city name |
| dst | Yes | Destination state (2-letter) |
| startDate | Yes | Earliest pickup date (YYYY-MM-DD) |
| endDate | Yes | Latest delivery date (YYYY-MM-DD) |
| freight | No | Equipment type filter (omit for all) |
| maxDeadhead | No | Max 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.
| Status | Meaning |
|---|---|
| 200 | Chains returned (chains array may be empty if no valid sequence found) |
| 400 | Missing required fields or city not found |
| 401 | Not authenticated |
| 403 | Trial expired or subscription inactive |
| 429 | Rate limit exceeded — 10 requests/minute |
| 500 | Search 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
| Param | Required | Description |
|---|---|---|
| from | Yes | Origin zip code (5 digits) |
| to | Yes | Destination 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.
| Status | Meaning |
|---|---|
| 200 | Miles returned |
| 400 | Missing or invalid zip code format |
| 401 | Not authenticated |
| 403 | Trial expired or subscription inactive |
| 404 | Zip code not found, or no route available for this zip pair |
POST /api/bandit
Streams responses from the Bandit AI freight assistant. Bandit can search loads, check market rates, plan load chains, look up mileage, answer 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
| Field | Required | Description |
|---|---|---|
| message | Yes | The user's plain-text message |
| history | No | Previous 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
| type | Fields | Description |
|---|---|---|
| text | content | Streamed text token from the model |
| tool_start | tool, label | A tool call is beginning |
| tool_result | tool, label, ok | Tool call completed (ok=false means an error) |
| done | history | Turn complete. Pass history back on the next request to maintain context. |
| error | message | Unrecoverable 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
}
}| Status | Meaning |
|---|---|
| 200 | Stream opened — SSE events follow |
| 401 | Not authenticated |
| 403 | Trial 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.
| Status | Meaning |
|---|---|
| 200 | Result field contains extracted HTML |
| 400 | No file provided |
| 401 | Not authenticated (Bearer token only — anonymous OK for free tier) |
| 402 | Subscription required or anonymous quota exhausted |
| 429 | Rate limit exceeded |
| 502 | Processing 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
}| Status | Meaning |
|---|---|
| 200 | Result field contains extracted HTML |
| 400 | No file provided |
| 402 | Subscription required or anonymous quota exhausted |
| 429 | Rate limit exceeded |
| 502 | Processing service temporarily unavailable — retry |
Error codes
All error responses return JSON with an error field describing the issue.
// Example error response
{
"error": "trial_expired"
}| Status | Meaning |
|---|---|
| 400 | Bad request — missing required fields or invalid format |
| 401 | Unauthenticated — missing or invalid token |
| 402 | Payment required — trial expired, subscription inactive, or quota exhausted |
| 403 | Forbidden — authenticated but not permitted (e.g. not admin) |
| 404 | Resource not found (e.g. zip code not in database) |
| 429 | Too many requests — slow down |
| 500 | Internal server error |
| 502 | Upstream processing service unavailable — retry after a few seconds |
Rate limits
Limits are applied per IP address. Authenticated users share the same limits.
| Endpoint | Limit |
|---|---|
| POST /api/auth/device | 10 requests / minute |
| GET /api/loads | 30 requests / minute per IP |
| POST /api/loads/search | No hard limit — fair use expected |
| GET /api/loads/rate-check | No hard limit — fair use expected |
| POST /api/loads/chain | 10 requests / minute per IP — can take 5–30s, set timeout ≥ 60s |
| GET /api/mileage | No hard limit — fair use expected |
| POST /api/bandit | No hard limit — each request can take up to 60 seconds |
| POST /api/tools/bol | No hard limit — processing takes 10–20s, set timeout ≥ 60s |
| POST /api/tools/invoice | No 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.