Shipper · September 30, 2026
Sending an ERP transport request into Cargobase as a quote-request draft
An ERP posts a transport request as a system draft, keeps its own id on the draft, and converts it into a quote request only after the payload validates.
Shippers already raise transport requests in an ERP such as Dynamics. Cargobase is where that request is quoted. This write-up is the path we use for that handoff: create a system draft, keep the ERP id, then convert it into a live quote request.
The problem
Someone retypes the ERP request into Cargobase: payment location, pickup and delivery, cargo, and incoterms. The new quote-request form then shows an empty handling unit, or cargo on the wrong row, when the payload uses a value the form does not recognize.
The integration should create the draft from the ERP, leave it editable in Cargobase, and only invite providers once the draft is valid.
What we use
A Shipper token on Sandbox, then a separate Production token. See Get API access.
This is the system-draft flow in the Shipper API reference, not the legacy one-shot order create.
| Step | Call |
|---|---|
| Create the draft | POST /api/1/requests/draft/ |
| Add a file after the draft exists | POST /api/1/requests/draft/{draft_id}/attachments/ |
| Check the draft without inviting anyone | POST /api/1/requests/draft/{draft_id}/create/ with dry_run: true |
| Turn it into a quote request | same path with dry_run: false |
POST /api/1/order/create/ is the older quick-request order path. Use the draft endpoints when the request must show up in the v4 quote-request form before it is sent out.
How it plugs into the ERP
Store two ids on the ERP transport request: the ERP number you send as external_id (for example 604-TR0000130), and the draft_reference_number Cargobase returns (SD…). After convert, also store shipment_reference (S…).
Send the objects the form is built from:
| ERP data | Payload |
|---|---|
| Transport request number | external_id |
| Payment location and cost center | organizational |
| Pickup and delivery | schedule.stops[] (stop_type 1 pickup, 2 delivery) |
| Packages | packing_list[] |
| What is inside the packages | packing_list[].good_customs_information[] |
| Incoterms and door-to-door | service |
| Modes to invite | invited_modes |
Do not send stop_key on the stops at create time. The server assigns those keys. Do not send other_attachments on create; upload files after you have the draft id.
handling_unit must be a recognized value, lowercase: bag, box, carton, case, crate, container, pallet, or tube. BOX does not match box, so the handling-unit dropdown stays empty while the commodity row still prints the raw text. handling_unit_value is for containers (LCL or FCL). Quantity of boxes is units. The HS code belongs on good_customs_information.hs_code, not on good_item_id.
POST https://sandbox.cargobase.com/api/1/requests/draft/
Authorization: Token <access_token>
Content-Type: application/json
A 201 returns the full draft. Save draft_reference_number and use it as {draft_id} on later calls.
Validate before convert:
{
"dry_run": true,
"auto_select_all_providers": true
}
200 with { "valid": true } means the draft is still there and can be converted. Convert with dry_run: false. 201 returns shipment_reference. The draft row is removed on success. A 400 leaves the draft in place so the ERP can fix the fields and try again.
What this achieves
The ERP transport request opens in Cargobase as a quote-request draft with the same location, stops, handling unit, and customs lines. Providers are invited only after a successful convert, and the ERP keeps both its own number and the Cargobase S… id.