TruckTabs API · v1
Send a route, a vehicle and a load. Get back the permits each state needs, what they cost, and a link your carrier can pay from. The same engine as trucktabs.com, over HTTP.
The API is for businesses whose own software handles oversize and permitted freight: brokers, carriers with a dispatch system, TMS vendors. Keys are issued by our team. Request access below and we reply by email, usually within a business day.
Every request goes to one base URL, and every body in both directions is JSON:
https://trucktabs.com/api/v1Once you have a key, call GET /me first. It proves the key works and shows what it can do.
curl https://trucktabs.com/api/v1/me \
-H "Authorization: Bearer $TRUCKTABS_API_KEY"{
"client": { "id": "3f6c2b8e-5d1a-4f7e-9c2b-8a1d4e6f7b90", "name": "Example Logistics" },
"key": {
"id": "9a4e1c7d-2b3f-4d5e-8f6a-1b2c3d4e5f60",
"name": "Production",
"prefix": "tt_live_Ab3x",
"scopes": ["read", "write"],
"expires_at": null
},
"limits": {
"read_requests_per_minute": 100,
"write_requests_per_minute": 30,
"quotes_per_minute": 30,
"quotes_per_day": 500
}
}Then read Quotes to price your first route. Places, state limits, the vehicle and trailer codes, and every error code are in the Reference.
Send your key in the Authorization header on every request. Keys start with tt_live_. Never put a key in a URL, where it ends up in logs.
Authorization: Bearer tt_live_…read key can look things up. A write key can also create quotes.A missing, unknown, revoked or expired key gets 401 UNAUTHORIZED. A suspended account gets 403 CLIENT_SUSPENDED, and a read key creating a quote gets 403 FORBIDDEN_SCOPE.
Content-Type: application/json, at most 32 KB. Unknown fields are refused rather than ignored, so a misspelled field name is an error you see, not a dimension that silently goes unpriced."currency": "USD". Times are ISO 8601 in UTC.{ "value": 13.5, "unit": "ft" } or "unit": "in".X-Request-Id header. Include it when you contact us about a request and we can find it straight away.200.PUT /quotes, gets 405 with an empty body.Every error has the same shape. Branch on code, which never changes meaning. message is a sentence you can show a person.
{
"error": {
"code": "INVALID_INPUT",
"message": "The request is missing 2 required fields.",
"details": {
"missing": [
{ "field": "vehicle.trailer_axles", "message": "Axles on the trailer." },
{ "field": "load.gross_weight_lbs", "message": "The gross weight in pounds, including the load." }
]
}
},
"request_id": "req_7Kq2mX9vB4nT1pR8sL3w"
}A quote request reports every problem at once, in details.invalid for values that are wrong and details.missing for values we need. The full list of codes is in the Reference.
| What | Limit | Counted per |
|---|---|---|
| Read requests (GET) | 100 a minute | key |
| Write requests (POST) | 30 a minute | key |
| Quotes created | 30 a minute | key |
| Place lookups | 60 a minute | key |
| Quotes created | Your daily allowance, shown by GET /me. Every quote that reaches pricing counts | account, midnight to midnight UTC |
Over a per-key limit you get 429 RATE_LIMITED with a Retry-After header in seconds, plus X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Over the daily allowance you get 429 QUOTE_LIMIT_REACHED; ask us if you need more. If quoting is briefly unavailable on our side you get 503 UNAVAILABLE, also with Retry-After.
A 429 with an HTML body instead of JSON is our firewall, not the API. It happens when a request reaches us without an Authorization header.
Creating a quote creates a real draft order. To retry after a timeout without creating a second one, send an Idempotency-Key header with a value you generate once per quote, such as a UUID: 8 to 128 letters, digits, _, ., : or -.
Idempotency-Key: 6f1d8f0e-3c2a-4b7e-9d15-2a8c4e7b9f31Idempotent-Replayed: true and Location. Nothing is priced or created again.409 IDEMPOTENCY_MISMATCH, unless the earlier request failed.409 IDEMPOTENCY_IN_PROGRESS and a Retry-After header. If it never finishes, a retry two minutes later picks up the same order: it returns the quote, or finishes pricing it.The version is in the path. Within v1 we only add things: new fields in responses, new optional fields in requests, new error codes for new situations. Build your client to ignore fields it doesn't know. Renaming or removing anything would be v2, running beside v1, and we would tell you well ahead.
Tell us who you are and what you're building. A person on our team reads every request. Use your work email address: we issue keys to businesses.