Estes Express Lines API: LTL Rates, Bills of Lading, Pickups, Tracking and Documents
Estes Express Lines (Estes, SCAC EXLA) publishes one REST API suite on
cloudapi.estes-express.com, and the estes carrier talks to it. It quotes
LTL shipments across every Estes service level, estimates transit time,
files the electronic Bill of Lading and returns the labels and BOL as PDFs,
requests, checks and cancels pickups, tracks shipments by PRO or by
reference, and fetches shipping documents (the BOL, delivery receipt,
invoice...).
Credentials#
Every Estes call needs an API key and a MyEstes login:
| Parameter | Estes value |
|---|---|
key |
Your Estes API key, sent in the apikey header |
username |
Your MyEstes username |
password |
Your MyEstes password |
account_number |
The Estes account the shipment is priced and billed against |
The same values can come from the environment as RS_ESTES_KEY,
RS_ESTES_USERNAME, RS_ESTES_PASSWORD and RS_ESTES_ACCOUNT_NUMBER.
Getting the key takes three steps, all on Estes' side:
-
Email
[email protected]with your developer name, email, title and company. Estes sends two emails with a client id and client secret, one for the test environment and one for production. -
Generate the key once per environment with the client id and secret as Basic auth. The response carries the API key and a new client secret; keep both.
curl -X POST https://cloudapi.estes-express.com/v1/api-key -u CLIENT_ID:CLIENT_SECRET -
Sign up for a MyEstes account if you do not have one.
RocketShipIt exchanges the login and the key for a bearer token before each
request; Estes binds the token to the login that fetched it. The
authenticate action returns that token in data.access_token with
data.expires_in (about ten hours) if you want to see it. The password, the
API key and the token are redacted from meta.debug_information.
{
"carrier": "Estes",
"action": "authenticate",
"params": {
"key": "YOUR_ESTES_API_KEY",
"username": "YOUR_MYESTES_USERNAME",
"password": "YOUR_MYESTES_PASSWORD"
}
}
Transportation management systems serving several Estes customers need each customer's MyEstes login; one key covers them all.
Test and production#
Requests go to cloudapi.estes-express.com. "test": true sends them to
Estes' UAT host uat-cloudapi.estes-express.com, which takes its own API
key and client credentials. Estes lists the UAT host for the Bill of Lading
and pickup APIs; rates, transit times, tracking and documents are documented
against production only, so expect those to need a production key. The BOL
API's own isTest flag is never sent as true; the host decides.
Supported actions#
| Action | Estes endpoint |
|---|---|
authenticate |
POST /authenticate |
getallrates |
POST /v1/rate-quotes |
timeintransit |
POST /v1/route-guides |
submitshipment |
POST /v1/bol |
track |
GET /v1/shipments/history |
createpickup |
POST /v1/pickup-requests |
pickupstatus |
GET /v1/pickup-requests/{requestNumber} |
cancelpickup |
DELETE /v1/pickup-requests/{requestNumber} |
gettrackingdocuments |
GET /v1/search/images/{document-type} |
Estes has no endpoint to cancel a filed BOL, so voidshipment is not
supported; contact Estes to void a PRO. Invoices and event subscriptions are
not supported yet.
Describing the freight#
Each entry in packages is one handling unit (a skid, pallet, crate,
drum...). Set on each package:
weight- the handling unit's weight inweight_unit(LBorKG). Estes rates in pounds; kilograms are converted.freight_class- the NMFC class as a number:50,55,60,65,70,77.5,85,92.5,100,110,125,150,175,200,250,300,400or500.packaging_type- the handling unit type.SKIDwhen left out.PALLET,CRATE,DRUM,BOX,BUNDLE,CARTON,CASE,BAG,BALE,BARREL,ROLL,REEL,TOTE,PAIL,PIECEand the rest are translated to Estes' codes for whichever API the action uses (the rating and pickup APIs saySKandDR, the BOL API saysSKDandDRM).sub_packaging_type- the packaging of the pieces on the handling unit (BOX,CARTON...). Estes does not accept a skid or pallet as the pieces' packaging on the BOL, so a skid of unspecified pieces ships asPCS.pieces- how many pieces are on the handling unit (default 1).length,width,heightinlength_unit(INorCM; centimeters are converted). Required for the time critical, volume and exclusive use levels and recommended for every rate.description- the commodity, printed on the BOL.po_number- a purchase order number printed on the BOL.hazmat- a hazmat block with onechemical_recordsentry givingid_number(UN1263),proper_shipping_name,class_division_numberandpackaging_group, plusemergency_contactandemergency_phone. TheHAZaccessorial is added for you. See Hazmat.
Shipment level:
service- leave it out ofgetallratesto quote every service level. To narrow it, one or more ofLTL,LTLTC(time critical guaranteed),VTL(volume LTL and truckload),VTLTC,ERG(Estes retail guarantee) andEU(exclusive use), comma separated.TIME_CRITICAL,GUARANTEED,VOLUMEandEXCLUSIVE_USEare accepted too.accessorials(oraddons) - Estes accessorial codes. Each API has its own list; see Accessorials.lift_gate_required- a lift gate at delivery.ship_date(orpickup_date) - the day the freight ships (2026-12-15or20261215). Rates are priced for that day; the BOL prints it; the pickup books it. Today when left out.ready_time- on rates, the ship time (08:00); on pickups, the start of the pickup window.insured_value- asks for full value coverage of that amount (whole dollars or cents,100to150000) on rates and on the BOL.ship_contact,ship_phone,ship_email- the person requesting the quote. Estes requires them for the time critical, volume and exclusive use levels.special_instructions- printed on the BOL, or sent to the driver with a pickup.
Country codes can be the two letter US, CA, MX or the three letter
USA, CAN, MEX; each API gets the form it wants. Phone numbers can
carry any punctuation; Estes gets the ten digits.
Billing#
By default the account in account_number is the shipper, paying prepaid. A
billing entry of type transportation changes who pays:
"billing": [
{
"type": "transportation",
"payment_type": "third_party",
"account": "THIRD_PARTY_ESTES_ACCOUNT",
"company": "Pays For Freight LLC",
"name": "Pat Payer",
"phone": "2145550000",
"addr1": "456 Other St",
"city": "Dallas",
"state": "TX",
"postal_code": "75201",
"country_code": "US"
}
]
payment_typethird_partyprices the quote against that account and bills it as the third party, prepaid. On the BOL the entry's address is the bill-to party; on a pickup it is the third party.payment_typerecipientmakes the consignee pay collect, againstaccount(or youraccount_number).
The same billing works on getallrates, submitshipment and
createpickup. Without an address on the entry, the BOL's bill-to party is
the bill_* parameters (bill_company, bill_name, bill_addr1,
bill_city, bill_state, bill_code, bill_country, bill_phone) when
set, else the party that pays.
Rates#
{
"carrier": "Estes",
"action": "getallrates",
"params": {
"key": "YOUR_ESTES_API_KEY",
"username": "YOUR_MYESTES_USERNAME",
"password": "YOUR_MYESTES_PASSWORD",
"account_number": "YOUR_ACCOUNT_NUMBER",
"shipper": "RocketShipIt",
"ship_contact": "John Doe",
"ship_phone": "8705551234",
"ship_email": "[email protected]",
"ship_city": "Harrison",
"ship_state": "AR",
"ship_code": "72601",
"ship_country": "US",
"to_city": "Akron",
"to_state": "OH",
"to_code": "44333",
"to_country": "US",
"ship_date": "2026-12-15",
"weight_unit": "LB",
"length_unit": "IN",
"accessorials": ["LGATE"],
"packages": [
{ "weight": 200, "length": 48, "width": 40, "height": 36, "freight_class": "50", "packaging_type": "SKID", "description": "furniture" }
]
}
}
The city, state, postal code and country of both ends are required for a quote. One rate comes back per service level Estes could price:
service_code-LTL,LTLTC,VTL,VTLTC,ERGorEU, derived from Estes' service level name, which is indesc("Estes LTL Standard Transit").guaranteedistrueon the time critical and retail guarantee levels.rate- Estes' total charges in USD.rate_detail- the breakdown: one entry per line item by class (class_50), one per rated accessorial by its code (LGATE), and the other charge items by Estes' description ("Fuel Surcharge"). An accessorial Estes reports as "Included" has no amount and is left out.est_delivery_daysandest_delivery_time- Estes' transit days and the delivery date and time it expects.rate_id- Estes' quote id. Pass it back asrate_idonsubmitshipmentto price the BOL on that quote.billing_weight- the rated weight, handling units and tare included.package_type- Estes' rate type ("Customer Pricing").
A level Estes could not price is reported in errors with its name
("Volume LTL: ...") and left out of rates; when no level could be priced
Estes answers HTTP 422 and every reason lands in errors. Entries with type
Note are Estes' alerts (add dimensions...), not failures.
Transit time#
timeintransit asks Estes' route guide for the service days between
ship_code and to_code (city, state and country help). One entry comes
back with delivery_days, the origin and destination terminals in desc,
and formatted_eta as the ship date plus that many weekdays. Estes does not
count weekends; holidays are not accounted for, so treat the date as an
estimate.
Creating a label and Bill of Lading#
submitshipment files the electronic BOL (the Digital LTL Council eBOL
2.0.1) and returns:
tracking_numberandshipment_id- the PRO number Estes assigned.packages[]- one entry per handling unit, each with the PRO as itstracking_numberand Estes' shipment confirmation number underalternative_tracking_ids. The labels are one PDF holding every handling unit's label; it is on the first package'slabeland underdocumentsasshipping_labels.documents[]- the Bill of Lading (codebill_of_lading) as a PDF and the labels (codeshipping_labels).
Estes produces labels as PDF only; image_type is ignored. label_stock_type
picks the layout: left out or zebra gives one 4x6 label per page; avery
(3-1/3 x 4, six per sheet), avery2 (8.5 x 5), avery4 (3.5 x 5) or
letter a sheet of labels. One label per handling unit is requested.
Add reference_value (and reference_value2, reference_value3) for BOL
numbers and po_number on the shipment or the packages for purchase orders;
all print on the BOL. rate_id from getallrates is the quote the BOL is
priced on. tracking_number on submitshipment is a PRO you pre-assigned
(Estes' Reserve PRO program); leave it out and Estes assigns one. notify
entries with an email get Estes' shipment movement emails.
Filing the BOL does not request the pickup; call createpickup with the
PRO in shipment_id. Estes' warnings ("Invalid characters were removed")
come back in errors with type Warning; the BOL is still filed.
Pickups#
createpickup requests a pickup at the pickup_* address
(pickup_company_name, pickup_contact_name, pickup_phone,
pickup_email, pickup_addr1, pickup_city, pickup_state,
pickup_code, pickup_country), or at the ship_* address when those are
blank, for freight going to the to_* address. Give the day as
pickup_date, the window as ready_time and close_time (0800, 08:00
or 4:30 PM; Estes reads them as Eastern time; 0800 to 1700 when left
out). List the handling units in packages, or just pickup_quantity and
pickup_total_weight when you do not have them. Put the PRO from
submitshipment in shipment_id to link the BOL to the pickup;
reference_value and po_number go along as BOL and PO references.
special_instructions goes to the driver. pickup_type is Estes' request
action when the default live load (LL) is wrong: HL hook loaded, HE
hook empty, SE spot empty, AP appointment.
The response has Estes' pickup request number in pickup_id (and in
reference_numbers with code PUR). pickupstatus with that pickup_id
returns the request's status (Accepted, Scheduled, Completed...), the
shipper contact and the PROs picked up on it. cancelpickup with the
pickup_id deletes the request; special_instructions is the cancel
comment. Validation failures come back in errors with the field name as
the code (pickupDate).
Parcel pickups work the same way on other carriers; see Schedule a Pickup.
Tracking#
track takes the PRO in tracking_number. To track by another reference,
set reference_type to PO, BOL, PUR (pickup request number), LDN
(load number), EXL (EXLA id) or INTERLINE (interline PRO) and put that
value in tracking_number; a reference can match several PROs, and each
comes back as one entry in packages. Estes tracks the shipment as a
whole, so the events are in activity and repeated on the first package.
Each event has Estes' status in status_code (Picked Up, In Transit,
Out for Delivery, Delivered...), Estes' detail in description
("Arrived at destination terminal"), the terminal in location and a
coarse status_type (PICKUP, IN_TRANSIT, OUT_FOR_DELIVERY,
DELIVERED, APPOINTMENT, EXCEPTION). The shipment level fields give
estimated_delivery (Estes' window), delivered_time, pickup_date,
delivery_detail.received_by (who signed) and the reference numbers Estes
holds (BOL, PO, pickup request, interline PROs). The shipper's and
consignee's places are shown when the login is party to the shipment;
otherwise origin and destination are Estes' terminals, and the charges
are left out.
Documents#
gettrackingdocuments fetches images for the PRO in tracking_number.
document_type names the document, or several comma separated: BOL
(default), BOLSUP, DR (delivery receipt), DELIMG (delivery image),
PUIMG (pickup image), INVOICE, WR and WNR (weight and research),
LUMPER, LOA, CCI, B7512, CAMOTH, TCSUPP. Each document comes
back under documents with Estes' content type (application/pdf,
image/tiff...), the base64 data in media and the image URL and creation
time in metadata. Only the latest version is fetched. A consignee who is
not party to the account can pass to_code (the consignee ZIP) to see the
party-to documents. Invoices and some other types are only shown to the
payer.
Accessorials#
Estes' APIs use different code lists. accessorials takes the list for the
action, and the rating codes are translated for submitshipment (and the
other way round) so a rated payload ships unchanged.
| Service | getallrates, createpickup |
submitshipment |
|---|---|---|
| Lift gate at delivery / pickup | LGATE / LGATEP |
LFTD / LFTP |
| Residential delivery / pickup | HD / HPU |
RES / REP |
| Inside delivery / pickup | INS / INP |
IDL / IPU |
| Appointment at delivery | APT |
APTD |
| Notify before delivery | NCM |
MNC |
| Protect from freezing | FRZ |
PSC |
| Single shipment | SSM |
SS |
| Construction site | CONST / CONSTP |
CONST / CONSTP |
| Limited access | PRISDL, SCHLDL, FARMDL, ... |
LTDAD / LTDAP (need the access type) |
| Guaranteed service | use service LTLTC |
GTD_AM, GTD_NOON, GTD_PM, TCS |
| Full value coverage | insured_value |
FVC, added with insured_value |
| Hazardous material | HAZ, added with hazmat |
HAZ, added with hazmat |
Old Dominion's codes (HYD, RDC, IDC...) are translated too, so a
payload written for od-rest rates and ships on Estes. The full lists are
in Estes' API developer portal.
Errors#
Estes errors land in data.errors with Estes' code and message, prefixed
with the service level they apply to on rates. HTTP 401 means the login or
the key was rejected; a rejected login is reported as "Estes authentication
failed: Failed authentication: Invalid credentials". The BOL API reports
failures in its messageStatus block; they are mapped to errors with
Estes' codes (EBG0010 an invalid BOL date, and so on), one entry per
message. Pickup validation failures carry the field name as the code.