Skip to content

Intent-Shaped Create and Rate Tools

How the agent fills in order and shipment bodies for you, which defaults it applies, and the two rules it will not override.

Updated September 3, 20263 min readPostsale CLI

Some agent tools accept commercial intent instead of a full raw API body. The CLI fills safe defaults, validates locally, then calls Postsale. This article explains the rules that protect you from silent unit mistakes and fabricated billing addresses.

In this article, we will see which tools use builders, apply the hard weight and billing rules, read applied_defaults, and use dimension estimates only for quotes.

Before We Begin

This article assumes that:

  • You are comfortable with postsale run or agent tooling
  • Use test-label mode for shipments you do not mean to ship (Test Without Spending)

Which tools fill in bodies for you

Builder-backed tools:

  • create_order
  • create_shipment
  • get_rates

Inspect schemas with get_tool_schema (agent) or postsale schema <slug> when a slug exists.

Example: create_order intent

json
{
    "buyer": { "name": "Jane Doe", "email": "jane@example.com" },
    "ship_to": {
        "street_line_1": "123 Main St",
        "city": "Springfield",
        "state_province": "IL",
        "postal_code": "62701",
        "country_code": "US"
    },
    "same_as_shipping": true,
    "items": [
        {
            "sku": "WIDGET-1",
            "name": "Widget",
            "quantity": 1,
            "price": 9.99,
            "weight": 0.5,
            "weight_unit": "lbs"
        }
    ]
}

Example: create_shipment intent

json
{
    "order_id": "550e8400-e29b-41d4-a716-446655440000",
    "carrier": "usps",
    "service": "usps_priority_mail",
    "test_label": true,
    "packages": [
        {
            "weight": 1,
            "weight_unit": "lbs",
            "length": 8,
            "width": 6,
            "height": 4,
            "dim_unit": "in"
        }
    ]
}

carrier and service are the backend's own field names and values (fedex | ups | usps, and a service code from get_carriersenabled_services). A carrier account cannot be pinned by id on this endpoint; the carrier type resolves to your default account of that type, or to the built-in USPS account when you have none. test_label buys watermarked, never-billed carrier test labels (USPS and UPS only). Omit every optional field to let your shipping rules decide the shipment; give any field and the rules are bypassed entirely, with the shipment shipping from the carrier account's address unless advanced.from_address_type and advanced.origin_address_id say otherwise.

Two rules you cannot override

  1. If weight is present, weight_unit is required. Wrong units can change rates dramatically.
  2. bill_address only comes from same_as_shipping: true or advanced.bill_address. The CLI will not invent a billing address.

Advanced overrides

Keys under advanced merge after builder defaults. Top-level keys replace entirely (no deep merge). Arrays replace rather than append. AJV validates the final merged body before the network call, so validation failures surface locally instead of as an API error.

What the CLI filled in for you

Responses include _cli_meta.applied_defaults as { field, value, reason } entries. We recommend repeating those in summaries so nobody is surprised by auto-filled fields.

With POSTSALE_TEST_LABEL_MODE set, every create_shipment body the builder authors is stamped test_label: true, and the real create response discloses the stamp here. Under --dry-run the simulated envelope shows the stamped body as input_received and carries no applied_defaults. An explicit test_label: false is refused before any request (test_label_mode_conflict), and so is an empty body, because a shipment built by your shipping rules cannot carry the flag (test_label_mode_requires_body). See Test-label mode.

Rate quotes and dimensions

If weight is set without length, width, and height, get_rates may apply a documented small-parcel estimate (6×6×6 in, or 15×15×15 cm when dim_unit is cm). That is for quoting only.

Partial dimensions fail with package_dimensions_incomplete.

Try a safe rates question

Here's how:

bash
postsale run "What are the cheapest rates for a 2lb package to New York?"

Or dry-run paths that only need quotes. Remember create_order is not dry-run intercepted; test orders can still be created under dry-run.

Good to Know

SymptomLikely causeWhat to do
Validation on weightMissing unitAlways send weight_unit
Bill address errorsFabrication attemptedUse same_as_shipping or advanced
Cheap quote, different purchaseEstimated dimsMeasure for real shipment

Additional Reading