# OSOWloads Quote API developer reference One endpoint, POST https://osowloads.com/api/v1/quotes, prices an oversize/overweight lane: send origin, destination, and load dimensions; get back per-state permit fees, escort counts, police / superload / survey / utility flags, and lane totals. - Coverage: the lower 48 US states. Canadian lanes return unsupported_region rather than a guess. - Same numbers as the calculator: same engine, same state data, same rate logic. Rates default to the account's saved Bid Builder config (one exception, service_fee_per_state — see Rates). - Latency: typically 2-5 seconds; the lane is routed live and priced through every state it crosses. Parallel requests are fine. - OpenAPI 3.1 spec: https://osowloads.com/developers/openapi - Human docs: https://osowloads.com/developers ## Authentication Bearer API key, created from the dashboard (https://osowloads.com/dashboard, org owners, any paid plan). Keys look like osow_live_… and go in the "Authorization: Bearer" header. The full key is shown once at creation; a SHA-256 hash is stored, so a lost key is revoked and re-minted. Server-side only. Never in client code or a public repo. ## Quickstart Four required fields: idempotency_key, origin, destination, dims (length_in, width_in, height_in, weight_lbs; axles required over 80,000 lbs). Everything else is optional; defaults that affect the math are echoed back in assumptions[]. ``` curl -X POST https://osowloads.com/api/v1/quotes \ -H "Authorization: Bearer osow_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"idempotency_key":"demo-1","origin":"Charlotte, NC","destination":"Nashville, TN","dims":{"length_in":900,"width_in":106,"height_in":160,"weight_lbs":66188}}' ``` ## Request body POST /api/v1/quotes. Unknown fields are rejected (422), so typos fail loudly. Bodies over 64KB are rejected. Bounds below are enforced; the OpenAPI spec carries the same numbers. Top level: - idempotency_key (string 1-128, REQUIRED): a receipt number you make up for this request (not your API key); sending it again returns the stored result free instead of charging twice. - origin (string or {lat,lng}, REQUIRED): "City, ST", full address, or coordinates. Geocoded resolution echoed in meta.resolved. - destination (string or {lat,lng}, REQUIRED): same formats as origin. - dims (object, REQUIRED): see Dims below. - waypoints (array, max 3, optional): intermediate stops, each a string address or coordinates. - vias (array of {lat,lng}, max 5, optional): route-shaping points, coordinates only, not stops. - engine ("here" | "google", optional, default "here"): HERE applies truck restrictions; on HERE failure we fall back to Google with an engine_fallback warning. exclude_states works on HERE; route_preference on Google. - ow_inputs (object, optional): see Overweight inputs below. Only read when weight_lbs > 80,000. - options (object, optional): see Options below. All flags default to false. - rates (object, optional): see Rates below. - client_ref (string max 200, optional): your own load/RFQ id, echoed back untouched. - metadata (object, optional): free-form string/number pairs, echoed back untouched. Keys max 40 chars, string values max 200 chars, whole object max 1KB. ### Dims (dims, required) - length_in (number 0-6000, REQUIRED): overall length in inches, including overhang. - width_in (number 1-1200, REQUIRED): overall width in inches. - height_in (number 1-600, REQUIRED): overall height in inches. - weight_lbs (number 1-2,000,000, REQUIRED): gross vehicle weight in pounds. Over 80,000 lbs triggers overweight pricing and requires axles. - axles (integer 5-30, CONDITIONAL): total axle count; required when weight_lbs > 80,000 (422 without it). - overhang_front_in / overhang_rear_in (number 0-600 each, optional, default 0): flat fields, not an "overhangs" object. - trailer_length_in (number 0-6000, optional): omitted = total length minus 240 in (20 ft tractor), floor 0, echoed in assumptions[]. Some states rate on trailer length; send it when known. - kingpin_in (number 0-1200, optional, default 0 = not checked): kingpin-to-rear-axle distance in inches; when set, states whose legal KPRA limit is exceeded get a kingpin_exceeds_legal warning. ### Overweight inputs (ow_inputs, optional; only read when weight_lbs > 80,000) A handful of states price overweight on inputs beyond gross weight. Every omitted field gets a lean default, echoed in assumptions[]; send real numbers when you have them. - wa_excess_lbs (number, optional): Washington — the excess pounds over legal gross that WSDOT's overweight schedule prices on. Omitted: computed as weight_lbs - 80,000. - mt_excess_axle_lbs (number, optional): Montana — declared excess axle weight in pounds over the Federal Bridge Chart allowance. - mn_groups (array max 12 of {type, weight}, optional): Minnesota prices overweight per axle group. type is "tandem" | "tridem" | "quad"; weight 0-200,000 lbs. List each non-steer group; groups at or under legal weight cost $0 and can be left out. Omitted on 7+ axle MN lanes: lean default grouping with auto-distributed weights, echoed in assumptions[]. - mn_drive_lbs / mn_trailer_lbs (number 0-200,000 each, optional): Minnesota drive-axle and trailer-axle group weights, an alternative to mn_groups (both must be present to take effect). - mn_trailer_type (string max 50, optional): Minnesota trailer axle configuration (e.g. tandem, tridem) for the drive/trailer pair. - il_front_lbs / il_rear_lbs (number 0-100,000 each, optional): Illinois prices from a front/rear axle-weight matrix; these are those two weights. - ax_steer_kg / ax_drive_kg / ax_trailer_kg (number 0-60,000 each, optional): per-axle-group weights in kilograms for Canadian pricing. Accepted for forward compatibility; no effect today (the API prices lower-48 lanes only). ### Options (options, optional; all flags default false) - return_polyline (boolean): include the encoded route geometry (polyline) for map drawing. - return_tooltips (boolean): include per-state tooltips — the calculator's hover explanations (escort, police, superload, survey, engineering, utility, alerts, oversize, general). - alternatives (boolean): when HERE offers an alternate route, price it too and return it as "alternate". Still one call. - compare_mi (boolean): also route the lane on the other engine and report its mileage in meta.compare_mi. Not billed extra. - avoid_us (boolean): prefer a routing that stays out of the US when one exists. Built for future cross-border lanes; on a lower-48 lane every route crosses the US, so you get a us_crossing_forced warning instead. - route_preference (integer -100..100 in steps of 5, optional): route bias, negative prefers shorter, positive prefers faster. Google only; ignored on HERE with a warning. - exclude_states (array of two-letter codes, max 12, optional): hard wall — the route will not enter these states, or fails with no_route. HERE only; ignored on Google with a warning. ### Rates (rates, optional) rates is a PARTIAL OVERRIDE. Any field you omit falls back to the account's saved Bid Builder configuration — so API quotes match dashboard quotes — with ONE exception: service_fee_per_state defaults to 0, not the saved service fee. The resolved values actually used are always returned in meta.rate_card. - escort_dpm (number 0-50): escort charge in dollars per route mile, per active escort. - escort_day_base (number 0-5000): base retainer per escort per day. - escort_day_min (number 0-5000): minimum an escort earns per day; applied as a true-up when mileage pay falls short. - hotel_per_night (number 0-2000): hotel charge per escort per overnight on multi-day lanes. - miles_per_day (number 50-1500): assumed miles covered per travel day; drives how many escort days and hotel nights a lane needs. - esl_mode (0 | 1 | 2): escort smoothing across the lane. 0 = Raw (each state's escort count exactly as that state reports it). 1 = Conservative (fills interior dips — if escorts are needed before and after a state, they're carried through it). 2 = Full Carry (the peak escort count rides the whole lane). Default: 1 — always, regardless of the account's saved Bid Builder setting; only an explicit esl_mode in the request changes it. - survey_dpm (number 0-50): route-survey charge in dollars per mile, per state requiring a survey. - survey_minimum (number 0-5000): minimum survey charge per surveyed state. - survey_report_fee (number 0-5000): flat report fee per surveyed state. - service_fee_per_state (number 0-500): flat service fee multiplied by the number of states the route crosses. Does NOT inherit from the Bid Builder config; omitted = 0. ## Response Lane totals first, then one block per state in travel order. The per-state block uses the same cell vocabulary as the calculator's results table. - quote_id: unique id (q_ prefix, creation-time sortable). - idempotency_key / client_ref / metadata: echoed back. - engine: routing engine that actually ran ("here" | "google"; fallback flagged in warnings). - route_mi: total routed miles. - total_permits: sum of state permit fees (oversize + settled overweight, deduplicated). Null whenever ANY state is not status "priced" — those states are in meta.unpriced_states with a reason. NOTE: null does not mean free; see Billing. - total_escorts / total_survey / total_service: lane costs from the rate card in play (meta.rate_card). - any_super/super_qty, any_police/police_qty, any_survey/survey_qty, any_engr/engr_qty, any_util/util_qty: lane rollups: "Yes" | "CBC" (case-by-case) | "No", each with a quantity string like "2" or "1 +1 CBC". - orig_tier_flag / orig_tier_note, dest_tier_flag / dest_tier_note: road-tier check at the endpoints: "yes" when a lower road tier at pickup/delivery could make requirements WORSE than the main-route answer; the note names each delta (e.g. "escorts 0→1"). - states[]: per state: abbr, mi, permit + permit_status (priced | agency_priced | not_permittable | unavailable), permit_label, permit_reason (frozen machine code), permit_note (plain English), extras (small add-ons like bridge fees), escRequired/escRequiredQty (what the state itself requires: Yes|CBC|No + count string), escTravelingQty (integer: the count the escort dollars were priced on — ESL-smoothed under rate_card.esl_mode, so escorts carried through a gap state show here while escRequired stays No; CBC states price as 0 unless carried through), superload, police/policeQty, survey, engr/engrType (Automated | State Agency | Third-Party), util/utilType (Notify | Permission | Personnel | Bucket Truck), tooltips ({bullets, notes, legend} per topic, only with options.return_tooltips). - polyline: Google-encoded route geometry (only with options.return_polyline). - alternate: HERE's alternate route fully priced (only with options.alternatives). Same shape as the main quote minus ids, assumptions, and meta; it never nests another alternate. - assumptions[]: the defaults applied that materially affect the math — trailer length, rate fallbacks, overweight lean defaults — each as {field, applied, rule}. Schema-level defaults that don't move money (engine choice, false option flags) are not echoed. - warnings[]: coded machine-readable flags (no_state_data, kingpin_exceeds_legal, engine_fallback, us_crossing_forced, compare_mi_unavailable, …). - meta: data_version, rate_card (the resolved rates actually used), routed_at, provider, resolved geocodes, unpriced_states, compare_mi, usage ({charge: "allowance" | "lot" | "none", remaining_allowance, remaining_lot_credits}). ## Errors Shape: { error: { code, message, request_id } }. Errors are never charged. Flip side: a 200 where a state is not_permittable or agency_priced is a successful, BILLED answer — knowing a state will not permit the rig as described IS the quote. Only "unavailable" (our own data gap) makes the call free. - 401 unauthorized / key_revoked: missing, invalid, revoked, or expired key. - 402 insufficient_balance: allowance used and no live credits. - 403 org_suspended: organization access is off. - 409 idempotency_key_reused / request_in_progress: same key different body; or still running. - 422 validation_failed / unknown_field: bad input; details[] lists each offending path. - 422 geocode_failed / no_route / unsupported_region: could not resolve or route (Canada/Mexico lanes are not on the API yet). - 423 suspended_for_review: API access paused pending a manual review (unusual traffic). - 429 rate_limited_minute / rate_limited_day: honor Retry-After; daily cap resets 00:00 UTC. - 5xx provider_unavailable / metering_unavailable / internal: retry with the SAME idempotency_key: if the original was charged you get the stored result free, otherwise it runs fresh. ## Idempotency and retries - Same key, same request again: the stored answer comes back free, with an "Idempotent-Replay: true" header. - Same key, different body: 409 idempotency_key_reused, not charged. Use a new key for a changed request. - Timeout or 5xx: retry with the same key; charged at most once either way. - 429: wait the seconds in Retry-After, retry with the same key. The per-minute limit refills continuously, so short waits work. ## Billing and limits Prepaid. One successful quote = one call. NOT charged: errors of any kind, replays, and quotes where our own data or routing could not answer (a state with permit_status "unavailable"). CHARGED: everything else that returns 200, including agency_priced / not_permittable lanes. Every response reports meta.usage. - Included calls: Solo 30 / Team 100 / Enterprise 200 per month, resets the 1st (UTC). - Extra credit packs: 2 API calls per credit; never expire, spent oldest-first after the allowance. - Burst: 200/minute (rolling bucket; 429 + Retry-After when exceeded). - Daily cap: 1,000/day per org (raise via the dashboard). - Body size: max 64KB. ## Three worked lanes (real captured request/response pairs, 2026-08-24) ### Bare minimum: Charlotte, NC → Nashville, TN Four fields. Everything else falls back to a documented default, and every default we applied comes back named in assumptions[]: the trailer length we assumed, the rate card we used. Request: ```json { "idempotency_key": "devdemo-2026-08-24-l1", "origin": "Charlotte, NC", "destination": "Nashville, TN", "dims": { "length_in": 900, "width_in": 106, "height_in": 160, "weight_lbs": 66188 } } ``` Response (200 OK): ```json { "quote_id": "q_01M0TRVP17S28F9X27RXVDVM5W", "idempotency_key": "devdemo-2026-08-24-l1", "client_ref": null, "metadata": null, "engine": "here", "route_mi": 423.4, "total_permits": 32, "total_escorts": 0, "total_survey": 0, "total_service": 0, "any_super": "No", "super_qty": "", "any_police": "No", "police_qty": "", "any_survey": "No", "survey_qty": "", "any_engr": "No", "engr_qty": "", "any_util": "No", "util_qty": "", "orig_tier_flag": "no", "orig_tier_note": "", "dest_tier_flag": "no", "dest_tier_note": "", "states": [ { "abbr": "NC", "mi": 177.3, "permit": 12, "permit_status": "priced", "permit_label": null, "permit_reason": null, "permit_note": null, "extras": "", "escRequired": "No", "escRequiredQty": "", "escTravelingQty": 0, "superload": "No", "police": "No", "policeQty": "", "survey": "No", "engr": "No", "engrType": "", "util": "No", "utilType": "", "tooltips": null }, { "abbr": "TN", "mi": 245.3, "permit": 20, "permit_status": "priced", "permit_label": null, "permit_reason": null, "permit_note": null, "extras": "", "escRequired": "No", "escRequiredQty": "", "escTravelingQty": 0, "superload": "No", "police": "No", "policeQty": "", "survey": "No", "engr": "No", "engrType": "", "util": "No", "utilType": "", "tooltips": null } ], "polyline": null, "alternate": null, "assumptions": [ { "field": "dims.trailer_length_in", "applied": 660, "rule": "trailer_length_in not supplied: total length minus 240 in (20 ft), floor 0" }, { "field": "rates", "applied": { "escort_dpm": 2, "escort_day_base": 125, "escort_day_min": 550, "hotel_per_night": 125, "miles_per_day": 450, "esl_mode": 1, "survey_dpm": 2, "survey_minimum": 550, "survey_report_fee": 250, "service_fee_per_state": 0 }, "rule": "unspecified rates fall back to the account Bid Builder config (service_fee_per_state defaults to 0)" } ], "warnings": [], "meta": { "data_version": "statesv3@2026-08-15", "rate_card": { "escort_dpm": 2, "escort_day_base": 125, "escort_day_min": 550, "hotel_per_night": 125, "miles_per_day": 450, "esl_mode": 1, "survey_dpm": 2, "survey_minimum": 550, "survey_report_fee": 250, "service_fee_per_state": 0, "out_of_route_percent": 0, "escort_safety_net": 0 }, "routed_at": "2026-08-24T20:54:42.951Z", "provider": { "engine": "here", "alternatives_offered": 1 }, "resolved": { "origin": "Charlotte, NC", "destination": "Nashville, TN" }, "unpriced_states": [], "compare_mi": null, "usage": { "charge": "allowance", "remaining_allowance": 198, "remaining_lot_credits": 20 } } } ``` ### Typical: Baltimore, MD → Albany, NY Dimensions plus your rate card and a client_ref. A 171″-tall load up the Northeast: escorts, a route survey, and utility notifications show up priced. Request: ```json { "idempotency_key": "devdemo-2026-08-24-l2", "client_ref": "LOAD-4471", "origin": "Baltimore, MD", "destination": "Albany, NY", "dims": { "length_in": 900, "width_in": 108, "height_in": 171, "weight_lbs": 104660, "trailer_length_in": 636, "axles": 7 }, "rates": { "escort_dpm": 2, "escort_day_base": 125, "escort_day_min": 600, "hotel_per_night": 125, "miles_per_day": 400, "esl_mode": 1, "service_fee_per_state": 39.99 } } ``` Response (200 OK): ```json { "quote_id": "q_01M0TRVQDCE0038RVX32SNZX0Z", "idempotency_key": "devdemo-2026-08-24-l2", "client_ref": "LOAD-4471", "metadata": null, "engine": "here", "route_mi": 332.1, "total_permits": 303, "total_escorts": 600, "total_survey": 800, "total_service": 159.96, "any_super": "No", "super_qty": "", "any_police": "No", "police_qty": "", "any_survey": "Yes", "survey_qty": "1", "any_engr": "No", "engr_qty": "", "any_util": "Yes", "util_qty": "2", "orig_tier_flag": "no", "orig_tier_note": "", "dest_tier_flag": "no", "dest_tier_note": "", "states": [ { "abbr": "MD", "mi": 59.1, "permit": 95, "permit_status": "priced", "permit_label": null, "permit_reason": null, "permit_note": null, "extras": "", "escRequired": "No", "escRequiredQty": "", "escTravelingQty": 0, "superload": "No", "police": "No", "policeQty": "", "survey": "No", "engr": "No", "engrType": "", "util": "No", "utilType": "", "tooltips": null }, { "abbr": "DE", "mi": 15.9, "permit": 70, "permit_status": "priced", "permit_label": null, "permit_reason": null, "permit_note": null, "extras": "Bridge analysis (route-dep)", "escRequired": "No", "escRequiredQty": "", "escTravelingQty": 0, "superload": "No", "police": "No", "policeQty": "", "survey": "No", "engr": "No", "engrType": "", "util": "No", "utilType": "", "tooltips": null }, { "abbr": "NJ", "mi": 141.8, "permit": 98, "permit_status": "priced", "permit_label": null, "permit_reason": null, "permit_note": null, "extras": "Turnpike permit (route-dep)", "escRequired": "No", "escRequiredQty": "", "escTravelingQty": 0, "superload": "No", "police": "No", "policeQty": "", "survey": "No", "engr": "No", "engrType": "", "util": "Yes", "utilType": "Notify", "tooltips": null }, { "abbr": "NY", "mi": 115, "permit": 40, "permit_status": "priced", "permit_label": null, "permit_reason": null, "permit_note": null, "extras": "Thruway permit (route-dep)", "escRequired": "Yes", "escRequiredQty": "1", "escTravelingQty": 1, "superload": "No", "police": "No", "policeQty": "", "survey": "Yes", "engr": "No", "engrType": "", "util": "Yes", "utilType": "Permission", "tooltips": null } ], "polyline": null, "alternate": null, "assumptions": [ { "field": "rates", "applied": { "survey_dpm": 2, "survey_minimum": 550, "survey_report_fee": 250 }, "rule": "unspecified rates fall back to the account Bid Builder config (service_fee_per_state defaults to 0)" } ], "warnings": [], "meta": { "data_version": "statesv3@2026-08-15", "rate_card": { "escort_dpm": 2, "escort_day_base": 125, "escort_day_min": 600, "hotel_per_night": 125, "miles_per_day": 400, "esl_mode": 1, "survey_dpm": 2, "survey_minimum": 550, "survey_report_fee": 250, "service_fee_per_state": 39.99, "out_of_route_percent": 0, "escort_safety_net": 0 }, "routed_at": "2026-08-24T20:54:44.267Z", "provider": { "engine": "here", "alternatives_offered": 1 }, "resolved": { "origin": "Baltimore, MD", "destination": "Albany, NY" }, "unpriced_states": [], "compare_mi": null, "usage": { "charge": "allowance", "remaining_allowance": 197, "remaining_lot_credits": 20 } } } ``` ### Everything on: Dallas, TX → Denver, CO Full control: overhangs, engine choice, a hard state exclusion, compare_mi (the other engine's mileage as a cross-check), and metadata echoed back for your own system. Request: ```json { "idempotency_key": "devdemo-2026-08-24-l3", "client_ref": "RFQ-2026-118", "metadata": { "customer": "acme-crane", "sheet_row": 14 }, "origin": "Dallas, TX", "destination": "Denver, CO", "engine": "here", "dims": { "length_in": 960, "width_in": 134, "height_in": 161, "weight_lbs": 134075, "overhang_front_in": 0, "overhang_rear_in": 60, "trailer_length_in": 720, "kingpin_in": 0, "axles": 7 }, "options": { "compare_mi": true, "exclude_states": [ "NM" ] }, "rates": { "escort_dpm": 2, "escort_day_base": 125, "escort_day_min": 600, "hotel_per_night": 125, "miles_per_day": 400, "esl_mode": 1, "survey_dpm": 2, "survey_minimum": 600, "survey_report_fee": 250, "service_fee_per_state": 39.99 } } ``` Response (200 OK): ```json { "quote_id": "q_01M0TRVSCYNGVQTWT0YARWHWFG", "idempotency_key": "devdemo-2026-08-24-l3", "client_ref": "RFQ-2026-118", "metadata": { "customer": "acme-crane", "sheet_row": 14 }, "engine": "here", "route_mi": 787.6, "total_permits": 1015, "total_escorts": 0, "total_survey": 0, "total_service": 119.97, "any_super": "No", "super_qty": "", "any_police": "No", "police_qty": "", "any_survey": "No", "survey_qty": "", "any_engr": "No", "engr_qty": "", "any_util": "No", "util_qty": "", "orig_tier_flag": "no", "orig_tier_note": "", "dest_tier_flag": "yes", "dest_tier_note": "YELLOW\u00b74-LANE: escorts 0\u21921 | BLUE\u00b72-LANE: escorts 0\u21922 | RED\u00b7MTN 2-LANE: escorts 0\u21922, super No\u2192Yes, police No\u2192CBC, util up", "states": [ { "abbr": "TX", "mi": 459.6, "permit": 285, "permit_status": "priced", "permit_label": null, "permit_reason": null, "permit_note": null, "extras": "Repeat identical load (30 days) $35 (route-dep)", "escRequired": "No", "escRequiredQty": "", "escTravelingQty": 0, "superload": "No", "police": "No", "policeQty": "", "survey": "No", "engr": "No", "engrType": "", "util": "No", "utilType": "", "tooltips": null }, { "abbr": "OK", "mi": 40.9, "permit": 630, "permit_status": "priced", "permit_label": null, "permit_reason": null, "permit_note": null, "extras": "", "escRequired": "No", "escRequiredQty": "", "escTravelingQty": 0, "superload": "No", "police": "No", "policeQty": "", "survey": "No", "engr": "No", "engrType": "", "util": "No", "utilType": "", "tooltips": null }, { "abbr": "CO", "mi": 286.6, "permit": 100, "permit_status": "priced", "permit_label": null, "permit_reason": null, "permit_note": null, "extras": "", "escRequired": "No", "escRequiredQty": "", "escTravelingQty": 0, "superload": "No", "police": "No", "policeQty": "", "survey": "No", "engr": "No", "engrType": "", "util": "No", "utilType": "", "tooltips": null } ], "polyline": null, "alternate": null, "assumptions": [], "warnings": [], "meta": { "data_version": "statesv3@2026-08-15", "rate_card": { "escort_dpm": 2, "escort_day_base": 125, "escort_day_min": 600, "hotel_per_night": 125, "miles_per_day": 400, "esl_mode": 1, "survey_dpm": 2, "survey_minimum": 600, "survey_report_fee": 250, "service_fee_per_state": 39.99, "out_of_route_percent": 0, "escort_safety_net": 0 }, "routed_at": "2026-08-24T20:54:45.416Z", "provider": { "engine": "here", "alternatives_offered": 1 }, "resolved": { "origin": "Dallas, TX", "destination": "Denver, CO" }, "unpriced_states": [], "compare_mi": { "engine": "google", "route_mi": 793 }, "usage": { "charge": "allowance", "remaining_allowance": 196, "remaining_lot_credits": 20 } } } ``` ## Recipe: lane list in a spreadsheet Loop the rows, one POST per row, write back the fields you care about. Fire requests in parallel — they don't queue behind each other. Put the lane and dims in the idempotency key ("sheet-row-14-savannah-birmingham-960x134") so re-runs replay free but an edited row re-prices. A 200-row sheet fits inside one minute's burst; the daily cap paces bigger jobs.