Skip to content

Test Without Spending

Rehearse every money path for free: dry-run for previews, test-label mode for real labels that are never billed, and how to see a refusal on purpose.

Updated September 3, 20263 min readPostsale CLI

Every money path in the CLI can be rehearsed for free, and you should rehearse before the first real charge and again whenever an intent that can spend money changes. The CLI gives you two tools for that, and they do different jobs: dry-run shows what the agent would do without sending the money-moving requests, and test-label mode runs the real purchase path against the carrier's test environment so the label comes back watermarked and never billed.

In this article, we will pick the right tool for the question you are asking, turn on test-label mode and buy a label that costs nothing, trigger a refusal on purpose so you know what one looks like, and see how the two tools behave together.

Before We Begin

This article assumes that:

Which tool answers which question

You want to knowUseWhat you get
"What would the agent do with this intent?"postsale run --dry-runThe money-moving tools are simulated and listed under simulated_effects; no carrier is charged
"Does the real purchase path work, end to end?"POSTSALE_TEST_LABEL_MODE=1A real label from the carrier's test environment, watermarked, never billed, metered, or insured
"What happens when something is refused?"Test-label mode plus a non-test shipmentThe purchase is refused before any request is sent, with the offending ids named

Dry-run is a targeted intercept, not a global "nothing writes" switch: creating and updating orders, updating shipments, tagging, and filter changes still run for real under --dry-run. Details: Preview Work with Dry-Run.

Turn on test-label mode

Test-label mode is a switch in the environment, not a flag. Every process that inherits the variable is in the mode.

Here's how:

  1. Turn it on for the shell session:
bash
export POSTSALE_TEST_LABEL_MODE=1
  1. Confirm the CLI sees it:
bash
postsale doctor

checks.environment.test_label_mode reads true. Any non-empty value turns the mode on, including 0 and false, so a typo fails towards a refusal rather than towards real postage. Unset the variable to turn it off.

  1. Create a shipment as you normally would, without adding test_label yourself:
bash
postsale orders create-shipment <order_id> --input shipment.json --yes

The shipment comes back with test_label: true, and _cli_meta.applied_defaults says the CLI added it. Two things are refused rather than rewritten: an explicit test_label: false in your body (test_label_mode_conflict), and an empty body, because a shipment built by your shipping rules cannot carry the flag (test_label_mode_requires_body).

  1. Buy the label:
bash
postsale labels purchase --shipment-id <shipment_id> --label-type pdf --yes

Before the first request the CLI reads every shipment in the purchase and checks its flag. The result carries labels[0].test_label: true and _cli_meta.test_label_verified, the list of shipment ids it verified. The label is a real carrier document from the test environment: watermarked, never billed, and the package is never shipped.

  1. Void it when you are done, as you would a real label:
bash
postsale labels void --shipment-id <shipment_id> --yes

Voiding costs nothing either way; the carrier is still called, in its test environment.

Success looks like a processed shipment with test_label: true, a label you can open, and a carrier account with no charge.

See a refusal on purpose

Knowing what a refusal looks like is worth one deliberate attempt. With the mode on, try to buy a label for a shipment that is not a test shipment:

bash
postsale labels purchase --shipment-id <real_shipment_id> --label-type pdf --yes

The CLI reads the shipment, sees test_label is not true, and refuses the whole purchase with test_label_required (exit 64), naming the offending ids. Nothing is bought, and the carrier is never asked. On postsale run the same check happens before the confirmation prompt, so a batch the CLI can already see is not a test batch is refused without asking you to approve it.

The two tools together

With both --dry-run and the mode set, the pre-purchase reads still happen (dry-run never suppresses reads), so a preview of a purchase can show the same refusal a real run would give, and the simulated envelope carries test_label_verified. One caveat: the preview only shows it when the agent actually calls the purchase tool. A model that reads a non-test shipment may stop on its own and never call it. For a refusal you can count on, use the direct command above.

Good to Know

  • Every gate still applies. Test-label mode is a constraint, not an authorization. Money confirmations, batch authorization, and owner-action gates behave exactly as they do outside the mode.
  • Store automation still runs. A test label is a real event on the shipment, so anything your store integration does when a label appears, it does here too.
  • Updates are untouched. The mode stamps what the CLI creates and checks what it buys. A real shipment you update keeps test_label: false, and a purchase for it is refused.
  • unattended runs is the natural home. Set POSTSALE_TEST_LABEL_MODE=1 on a smoke-test job and the real purchase path runs at zero carrier cost, with every non-test shipment refused before a request is sent. See Batches and Unattended Runs.
  • You can always tell afterwards. Confirmed effects in traces carry a response-derived test_label, so a trace answers "was that real postage?" without guessing.

Additional Reading