OTR Quote
Endpoint: POST /v1/otr/quote
Submit shipment details to receive carrier rates for LTL and/or Truckload transportation. The response includes a quoteNumber and a list of carrierQuotes, each with its own rateNumber.
Authentication required. All requests to this endpoint require a valid bearer token. See Authentication.
Request Body
Core Fields
These fields are required to submit a complete OTR quote request.
| Field | Type | Required | Description |
|---|---|---|---|
customerBsn | string | Yes | Branch identifier for your organization. Retrieve from GET /v1/customers |
origin | object | Yes | Shipment origin location |
destination | object | Yes | Shipment destination location |
UOM | string | Yes | Unit of measure: "US" or "METRIC" |
items | array | Yes | List of shipment items |
accessorials | array | Yes (may be empty) | Additional services requested for the shipment (liftgate, appointment, etc.). This field must always be included in the request body, even when no accessorials are provided. In those cases, send an empty array: []. |
modes | array | Yes | Transportation modes: ["LTL"], ["Truckload"], or both |
requestingUser | string | Yes | Email address of the user submitting the quote request |
Origin / Destination Object
{
"country": "US",
"state": "CA",
"city": "Los Angeles",
"postalCode": "90001"
}
Field Reference
Modes
"modes": ["LTL"]
"modes": ["LTL", "Truckload"]
Accessorials
Retrieve valid values from GET /v1/tools/otr/accessorials.
| Field in response | Use as |
|---|---|
accessorialType | accessorialType in quote request |
accessorial | accessorial in quote request |
displayName | Informational only — do not send in request |
"accessorials": [
{
"accessorial": "Liftgate",
"accessorialType": "Pickup"
}
]
LTL vs Truckload accessorial rules
- LTL:
accessorialTypemust be"Pickup","Delivery", or"Shipment" - Truckload:
accessorialTypecan benull
This endpoint supports multiple transportation modes, PRIMO strongly recommends submitting requests with a single mode whenever possible to ensure more accurate accessorial validation.
Items
Each item in the items array represents a commodity in the shipment.
| Field | Type | Required | Description |
|---|---|---|---|
itemName | string | Yes | Item description |
packageType | integer | Yes | Package type ID from GET /v1/tools/otr/packages |
quantity | integer | Yes | Number of identical units |
weight | number | Yes | Weight per unit |
length | number | Conditional | Required for booking; optional if volume is provided |
width | number | Conditional | Required for booking; optional if volume is provided |
height | number | Conditional | Required for booking; optional if volume is provided |
volume | number | Conditional | Required when dimensions are omitted |
freightClass | string | Yes | Freight class (e.g., "50", "92.5") |
levels | integer | Yes | Stack levels (1 if not stackable; 2 or more if stackable) |
isHazardous | boolean | Yes | Mark true for hazardous materials |
isStackable | boolean | Yes | Whether other items can be stacked on top |
Quoting without dimensions:
You can quote using volume + weight instead of explicit dimensions. However, dimensions are mandatory for booking. Plan accordingly.
Use POST /v1/density to derive freightClass and volume from dimensions.
Stacking rules:
isStackable | levels |
|---|---|
false | Must be 1 |
true | Must be 2 or greater |
Insurance (optional)
"insurance": {
"cargoValue": "1000",
"goodsValue": "NEW",
"isNewGoods": true,
"addFreightCost": false,
"addExtraCoverage": false,
"insuredName": "Insurance1",
"insuredCountry": "UNITED STATES"
}
| Field | Description |
|---|---|
cargoValue | Total declared cargo value |
goodsValue | "NEW", "USED", or "PERISHABLE" |
isNewGoods | true when goodsValue = "NEW", otherwise, send false |
addFreightCost | Include freight cost in insured value |
addExtraCoverage | Add 10% extra coverage for lost profits |
Equipments
For Truckload (FTL) quotes the quote results will include the equipment types available for the selected rate. Please take this into account when requesting and reviewing Truckload (FTL) quotes.
Request Examples
- Minimum Request
- Without Dimensions
- Full Request
{
"customerBsn": "YOUR_CUSTOMER_BSN",
"origin": {
"country": "US",
"state": "CA",
"city": "Los Angeles",
"postalCode": "90001"
},
"destination": {
"country": "US",
"state": "CA",
"city": "Los Angeles",
"postalCode": "90001"
},
"UOM": "US",
"items": [
{
"itemName": "Test Pallet",
"packageType": 100,
"quantity": 1,
"length": 24,
"width": 29,
"height": 24,
"weight": 1000,
"freightClass": "92.5",
"levels": 1,
"isHazardous": false,
"isStackable": false
}
],
"accessorials": [
{
"accessorial": "Liftgate",
"accessorialType": "Pickup"
}
],
"modes": ["LTL"],
"requestingUser": "joe@example.com"
}
{
"customerBsn": "YOUR_CUSTOMER_BSN",
"origin": {
"country": "US",
"state": "CA",
"city": "Los Angeles",
"postalCode": "90001"
},
"destination": {
"country": "US",
"state": "CA",
"city": "Los Angeles",
"postalCode": "90001"
},
"UOM": "US",
"items": [
{
"itemName": "Test Pallet",
"packageType": 100,
"quantity": 1,
"weight": 2000,
"volume": 4.63,
"freightClass": "50",
"levels": 1,
"isHazardous": false,
"isStackable": false
}
],
"accessorials": [
{
"accessorial": "Liftgate",
"accessorialType": "Pickup"
}
],
"modes": ["LTL"],
"requestingUser": "joe@example.com"
}
{
"customerBsn": "YOUR_CUSTOMER_BSN",
"origin": {
"country": "US",
"state": "CA",
"city": "Los Angeles",
"postalCode": "90001"
},
"destination": {
"country": "US",
"state": "DC",
"city": "WASHINGTON",
"postalCode": "20001"
},
"UOM": "US",
"items": [
{
"itemName": "Chemical Product 1",
"packageType": 100,
"quantity": 1,
"length": 24,
"width": 29,
"height": 24,
"weight": 1000,
"freightClass": "50",
"levels": 1,
"isHazardous": true,
"isStackable": false
},
{
"itemName": "Pallet",
"packageType": 100,
"quantity": 1,
"length": 24,
"width": 29,
"height": 24,
"weight": 1000,
"freightClass": "50",
"levels": 2,
"isHazardous": false,
"isStackable": true
}
],
"accessorials": [
{
"accessorial": "Liftgate",
"accessorialType": "Pickup"
},
{
"accessorial": "Liftgate",
"accessorialType": "Delivery"
}
],
"insurance": {
"cargoValue": "1000",
"goodsValue": "NEW",
"isNewGoods": true,
"addFreightCost": false,
"addExtraCoverage": false,
"insuredName": "Insurance1",
"insuredCountry": "UNITED STATES"
},
"modes": ["LTL", "Truckload"],
"requestingUser": "joe@example.com"
}
Response
{
"data": {
"quoteNumber": 89169865,
"mileage": 1,
"referenceQuoteNumber": "QUOTE_REF_NUMBER",
"carrierQuotes": [
{
"rateNumber": 1525,
"carrierNumber": 5863632,
"carrierName": "Carrier Name",
"transitDays": 1,
"mode": "LTL",
"service": "Standard",
"serviceDescription": "Less than Truckload",
"totalAmount": 222.30,
"suggestedRate": 255.65,
"quoteExpirationDate": "2026-05-18T12:14:13.86-05:00",
"accessorials": [
{
"accessorial": "Liftgate",
"accessorialType": "Pickup",
"quantity": 1
}
],
"charges": [
{
"displayName": "Base",
"chargeCode": 1000,
"amount": 222.30,
"isWaived": false
}
]
}
]
},
"errors": null
}
Key Response Fields
| Field | Description |
|---|---|
quoteNumber | Unique quote ID — save this for booking |
carrierQuotes[].rateNumber | Carrier-specific rate ID — save this for booking |
totalAmount | Buy rate (actual carrier cost) |
suggestedRate | Suggested sell price |
transitDays | Estimated transit time in days |
quoteExpirationDate | When the rate expires |
Empty carrier quotes
If carrierQuotes is empty on a 200 OK response, no carrier matched the lane. Contact PRIMO customer service to review coverage for your origin/destination.
Next Steps
- OTR Book → — Use your
quoteNumberandrateNumberto create a booking