Save a shipping estimate
AI agents: read /llms.txt; add .md to any page URL. This page as Markdown: /reference/shipping-rates-and-estimates/v2-shipment-estimate-create-goshippo.md. Index of every page and the rules for every call: /llms.txt. Guides and concepts in one file: /llms-full.txt. OpenAPI: /openapi.json.
POST/
Saves a Shippo rate quote on a YoPrint shipment, as a shipping estimate. Nothing is bought.
Get rates first, then send the reply's top-level object_id as goshippo_shipment_id, and the rate you picked as goshippo_selected_rate_id. YoPrint reads that Shippo shipment back and stores it with all its rates. Returns the estimate (shippo_rates, shippo_address_from, shippo_parcels, ...).
An estimate is a quote you can show or bill for. Buying the label is a separate call that takes a rate id; you can pass the estimate's id there as shipment_estimate_id, only to link the label's shipping cost line to it.
Business rules
- Works on shipments of quotes and sales orders, in any status.
- Each call adds a new estimate; sending the same ids twice saves two.
Side effects
- Reads the Shippo shipment (it buys nothing) and saves an estimate. Open Admin Portal pages refresh.
Path parameters
Your team slug, shown as Team ID next to your API key in Profile.
- Example
your-team
- Example
The shipment's hash id (
id). Hash ids only: a unique key or a document number gives 404.- Example
MQyJUnd3oty75h
- Example
Request body
application/json, required.
The top-level
object_idfrom Get shipping rates.frontend_dataobjectYour own data to keep with the estimate (the web app stores its form here).
Required with
frontend_data: your format version for it.The
rates[].object_idyou chose. Not checked against the shipment.
Response
200Successful response.
A saved shipping estimate.
Child fields (22)
created_atstring (date-time)frontend_dataobject | arrayWhat you sent as
frontend_data; an empty list[]when you sent none.What you sent, or null.
goshippo_selected_rate_idstring | nullThe rate chosen when it was saved.
goshippo_shipment_idstring | nullThe Shippo shipment.
idstringThe estimate.
order_idstringThe order.
order_object_typestring | nullorder_quotebooleanorder_scoped_idstring | nullshipment_idstringThe shipment.
shipment_scoped_idstring | nullshippo_address_fromobjectshippo_address_toobjectshippo_carrier_accountsarray of stringsshippo_extraanyThe label options, or null.
shippo_object_idstring | nullshippo_parcelsarray of objectsshippo_ratesarray of objectsEvery rate of that Shippo shipment, as saved (
amountis a decimal string).Fields of each item (19)
amountstringamount_localstringarrives_bystring | nullattributesarray of stringsShippo's tags, for example
CHEAPEST.carrier_accountstringcurrencystringcurrency_localstringduration_termsstring | nullestimated_daysinteger | nullincluded_insurance_pricestring | nullmessagesarray of objectsobject_createdstringobject_idstringThe rate id. Send it as
rate_idto buy this label.object_updatedstringproviderstringprovider_image_200stringprovider_image_75stringA URL of the carrier logo.
servicelevelobjectExactly these four keys; null when Shippo sends no service level.
Child fields (4)
extended_tokenstringnamestringtermsstringtokenstring
shipmentstringThe Shippo shipment this rate belongs to.
shippo_shipment_datestring | nullshippo_statusstring | nulltypestring
Errors
401The API key is missing or wrong (
unauthenticated).403You are not allowed to do this.
api_access_not_in_plan: your team's plan doesn't include API access (Pro and above, with an active subscription or trial), so every request answers this until the team upgrades. When your role lacks the permission the operation needs, the body is only{"message": "Insufficient Permission"}. Other refusals use the error envelope, withunauthorizedoruser_is_not_authorized.404Not found.
page_not_found: the team slug is unknown, you are not a member of the team, or an id in the path is not one of this team's.code: null, with a message that starts "No query results for": there is no record with that id.- When
- The shipment isn't your team's.
- Fix
- Check the shipment id.
422The request was refused and changed nothing.
validation_failedlists what to fix inerror.fields; other codes name a business rule, explained inerror.message. A few checks answer with only{"message": "..."}. An operation that calls another service (a payment provider, a carrier, an accounting app) can answerconnect_timeout("Please retry again") when that service does not answer in time: the change may or may not have happened there, so read the record back before you retry.- When
- Shippo rejected the shipment id (Shippo answered 400):
validation_error, "The shipping rate could not be loaded. Get shipping rates again and choose a rate before saving." Other Shippo failures, possibly including an unknown id, are a 500. - Fix
- Get rates again and send the new
object_id. - When
goshippo_shipment_idis missing, orfrontend_datais sent withoutfrontend_data_version.- Fix
- Send the required fields.
- When
- Shippo isn't connected or is disabled (
goshippo_not_enabled). - Fix
- Connect Shippo in the web app first.
500A business rule refused the request (see the operation's errors), or something failed inside YoPrint. Refusals use the error envelope with a code such as
action_not_allowed; an unexpected failure answers{"message": "Server Error"}. Repeating a refusal gets the same answer; after an unexpected failure, read the record back before you retry a change.- When
- Shippo refused the request or could not be reached. Shippo errors are not translated into 4xx replies.
- Fix
- Check the addresses, parcels and ids, then retry once. Do not loop.
Related
- POSTGet shipping rates
/v2/ api/ store/ {team_slug}/ v2/ shipment_rate/ goshippo - GETList the shipping estimates of a shipment
/v2/ api/ store/ {team_slug}/ v2/ shipment/ {hash_id}/ estimates - POSTBuy a shipping label (charges your Shippo account)
/v2/ api/ store/ {team_slug}/ v2/ shipment/ {hash_id}/ label/ goshippo
