Rating

One request quotes every eligible carrier on your account at once. The rates come back as one list in one shape, so a quote from Saia and a quote from XPO can be compared field for field.

How it works

  1. Create a rating job with POST /rating/jobs . Describe the shipment once. The response is immediate: a job in PROCESSING with no rates yet.
  2. Shipwell contacts every carrier in parallel , so a slow carrier never holds up a fast one.
  3. Read rates as they arrive. Each carrier's rates are saved the moment it answers, so ?include=rates returns the fast carriers' quotes while slower ones are still working. You never wait on the slowest carrier to show the first price.
  4. Poll the job with GET /rating/jobs/{rating_job_id} until is_terminal is true .
  5. Read the full set with ?include=rates once is_terminal is true .
  6. Book one by passing its id to dispatch as rate_id . FTL rates are the exception: you book them by tendering in the Shipwell app. See Full truckload (FTL) .

A job always finishes. Carrier attempts still waiting after about 30 minutes are closed as errored, so your polling loop has a known end even when a carrier never answers.

Endpoints

Endpoint What it does
POST /rating/jobs Create a rating job. Returns 201 with the job in PROCESSING.
GET /rating/jobs/{rating_job_id} Read the job. Add ?include=rates to expand its rates.
GET /rating/jobs/{rating_job_id}/rates/{rate_id} Read one rate on its own. This is the URL in the rate's self_link.

Create a rating job

modes accepts LTL, VLTL and FTL, alone or together. equipment is required: LTL and VLTL are quoted on a dry van, so send [{"equipment_type": "DRY_VAN"}]. FTL has its own equipment rules, covered in Full truckload (FTL). Leave out capacity_providers to quote every carrier eligible for your account, or list the ones you want by provider_code.

Example request
Copy
Copied
curl --request POST 'https://sandbox-api.shipwell.com/rating/jobs' \
--header 'Authorization: Token <user-token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: 3c9e7a10-po-4417' \
--data-raw '{
  "modes": ["LTL"],
  "customer_reference_number": "PO-4417",
  "equipment": [{"equipment_type": "DRY_VAN"}],
  "stops": [
    {
      "sequence_number": 1,
      "location": {"line_1": "515 Congress Ave", "locality": "Austin", "region": "TX", "postal_code": "78701", "country": "US"},
      "contact": {"company_name": "Acme", "first_name": "Dock", "last_name": "Team", "phone": "+15125551234"},
      "requested_window": {"earliest": "2026-12-01T14:00:00Z", "latest": "2026-12-01T22:00:00Z"}
    },
    {
      "sequence_number": 2,
      "location": {"line_1": "4340 Directors Row", "locality": "Houston", "region": "TX", "postal_code": "77092", "country": "US"},
      "contact": {"company_name": "Beta Receiving", "first_name": "Receiving", "last_name": "Desk", "phone": "+17135554500"}
    }
  ],
  "handling_units": [
    {
      "description": "Palletized boxes",
      "quantity": 1,
      "freight_class": "70",
      "weight": {"value": 500, "unit": "LB", "qualifier": "PER_ITEM"},
      "dimensions": {"measurement_type": "DIMENSIONS", "unit": "IN", "length": {"value": 48, "unit": "IN"}, "width": {"value": 40, "unit": "IN"}, "height": {"value": 50, "unit": "IN"}}
    }
  ]
}'
Example response (201)
Copy
Copied
{
  "data": {
    "id": "01HZKD8QKZQ8Z7XV9MKZ5QXW3H",
    "resource_type": "rating_job",
    "self_link": "https://sandbox-api.shipwell.com/rating/jobs/01HZKD8QKZQ8Z7XV9MKZ5QXW3H",
    "status": "PROCESSING",
    "is_terminal": false,
    "created_at": "2026-08-19T15:30:32.591Z"
  }
}

What to send for usable quotes

The API only enforces what every carrier needs to accept a request. Individual carriers need more to return a price, so send a complete shipment:

Field Required by the API Needed by most carriers
modes Yes
stops (2 or more) Yes
stops[].location Yes A full address: line_1, locality, region, postal_code, country. A bare postal code is accepted, but Saia, Peninsula and Pitt Ohio reject it.
requested_window on the pickup stop Yes
stops[].contact No Not needed to rate, but booking needs a pickup contact (company_name, first_name, phone) and a delivery contact (company_name, phone). Send both now and the booking needs only rate_id; otherwise send them when you dispatch.
handling_units (1 or more), with weight Yes
equipment (1 or more) Yes LTL and VLTL: DRY_VAN, because that freight moves in the carrier's standard enclosed dry van. FTL: exactly one of DRY_VAN, FLATBED or REEFER. See Full truckload (FTL).
handling_units[].freight_class No Saia, Peninsula and Duie Pyle reject the request without it.
handling_units[].dimensions No Saia requires it.
total_linear_feet No Required when modes includes VLTL.
Tip

Send an Idempotency-Key header with a value unique to the shipment. If your request times out and you retry it with the same key and body, you get the original job back instead of quoting every carrier a second time. A retry while the first request is still being created answers 409.

Read the rates

Read the job with ?include=rates. While the job is still PROCESSING you get the rates collected so far; once is_terminal is true you get every carrier's answer. There is one entry per carrier attempt and service level.

Example request
Copy
Copied
curl --request GET 'https://sandbox-api.shipwell.com/rating/jobs/01HZKD8QKZQ8Z7XV9MKZ5QXW3H?include=rates' \
--header 'Authorization: Token <user-token>'
Example response (200, abridged)
Copy
Copied
{
  "data": {
    "id": "01HZKD8QKZQ8Z7XV9MKZ5QXW3H",
    "resource_type": "rating_job",
    "status": "COMPLETED",
    "is_terminal": true,
    "rates": [
      {
        "id": "01HZKD9M4TQ4Z8XW0NKZ6RYX4J",
        "resource_type": "rate",
        "self_link": "https://sandbox-api.shipwell.com/rating/jobs/01HZKD8QKZQ8Z7XV9MKZ5QXW3H/rates/01HZKD9M4TQ4Z8XW0NKZ6RYX4J",
        "provider_code": "ESTES",
        "carrier_name": "Estes Express Lines",
        "capacity_provider": {"account_id": "01KBZ91QKW3D9VDP5PVY4HWQ1G", "account_name": "Estes - Main"},
        "transportation_mode": "LTL",
        "charges": {
          "total_charges": {"amount": 412.37, "currency": "USD"},
          "charge_breakdown": [
            {"charge_code": "BASE", "description": "Linehaul"},
            {"charge_code": "FSC", "description": "Fuel surcharge"}
          ]
        },
        "transit_time": {"transit_days": 2},
        "expiration_date": "2026-08-26T00:00:00Z",
        "messages": []
      },
      {
        "id": "01HZKD9M4TQ4Z8XW0NKZ6RYX4K",
        "provider_code": "SAIA",
        "carrier_name": "Saia",
        "charges": null,
        "messages": [
          {"title": "Rate request failed", "detail": "Destination postal code is outside this carrier's service area."}
        ]
      }
    ]
  }
}
  • A rate with charges is bookable. Pass its id to dispatch as rate_id . An FTL rate ( transportation_mode: "FTL" ) is booked by tendering in the Shipwell app instead. See Full truckload (FTL) .
  • A rate with charges: null is a failed attempt. The carrier's reason is in messages , in the carrier's own words. There's no separate success flag, because a rate with no price can't be booked.
  • charges is the carrier's own price, with no markup applied. See Carrier Rules & Markup .

Volume LTL

For shipments too large for standard LTL but short of a full truckload, include VLTL in modes and send total_linear_feet. The carriers that support it are marked in Supported Carriers.

Full truckload (FTL)

FTL quotes come from TQL (Total Quality Logistics). TQL is the only carrier quoting FTL through this API.

Note

FTL is available in production. It isn't in sandbox yet, where a request with FTL in modes is rejected with 400.

  • Ask for it in modes. Send ["FTL"] on its own, or alongside LTL and VLTL to compare a truckload quote with LTL quotes in one job. Every rate carries the mode it was quoted for in transportation_mode .
  • Choosing carriers. Leave out capacity_providers and FTL goes to TQL. If you name carriers, ["FTL"] on its own may name only TQL , and FTL with other modes needs TQL among the names.
  • Equipment. Send exactly one entry: DRY_VAN , FLATBED or REEFER . REEFER needs a temperature with a finite minimum , maximum , or both. FLATBED and REEFER need FTL on its own in modes .
  • No price is still an answer. When TQL can't price a lane, its rate comes back with charges: null and TQL's reason in messages , like any other carrier.
Copy
Copied
"modes": ["FTL"],
"equipment": [
  {"equipment_type": "REEFER", "temperature": {"unit": "FAHRENHEIT", "minimum": 34, "maximum": 38}}
]

Booking an FTL rate

An FTL rate from this API tells you TQL's price for the load. It can't be booked through this API: sending its id to POST /dispatching/jobs returns 400 with the code unsupported_transportation_mode.

FTL is booked by tendering by email in the Shipwell app, and the tender belongs to a shipment in the app. A rating job created through this API isn't linked to any app shipment, so its FTL rate can't be tendered as it is. To book the load:

  1. Create the shipment in the Shipwell app.
  2. Get its quotes there. TQL's FTL quote appears alongside the others.
  3. Select the TQL FTL quote and send the tender. TQL accepts or rejects it, and the shipment moves to Tendered once it's accepted.

Contact your Shipwell representative to turn FTL on for your account.

Rating statuses

See Statuses for what each rating job status means.

API reference

Rating API reference: every field, with request and response examples and code samples.

Next steps

Pick a rate and dispatch it.

Copyright © Shipwell 2025. All right reserved.