Skip to content

Save a shipping estimate

Open .md

POST/v2/api/store/{team_slug}/v2/shipment/{hash_id}/shipment_estimate/goshippo

v2Operation ID v2_public_shipment_estimate_create_goshippo

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.

Permission

Any member of the team. No sales order permission is checked. Needs a connected, enabled Shippo integration (Settings > Integrations > Shippo Shipping). Without one the reply is 422 goshippo_not_enabled with no message.

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

  • team_slugstringrequired

    Your team slug, shown as Team ID next to your API key in Profile.

    • Example your-team
  • hash_idstringrequired

    The shipment's hash id (id). Hash ids only: a unique key or a document number gives 404.

    • Example MQyJUnd3oty75h

Request body

application/json, required.

Response

200Successful response.

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, with unauthorized or user_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_failed lists what to fix in error.fields; other codes name a business rule, explained in error.message. A few checks answer with only {"message": "..."}. An operation that calls another service (a payment provider, a carrier, an accounting app) can answer connect_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_id is missing, or frontend_data is sent without frontend_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.