WooCommerce Shipping Setup Guide With WP-CLI and AI Agents
Shipping setup is where store launches stall. You click through the settings for an afternoon, fight with zones until a rate finally shows, then start over from zero on the next store. When a rate goes missing at checkout, the customer leaves. The Baymard Institute puts average cart abandonment near 70%, and high or surprise shipping cost is a leading reason people bail.
None of this is hard. It’s slow, easy to get subtly wrong, and impossible to repeat exactly through a UI. Drive it from the command line instead. You can run an entire WooCommerce shipping operation this way: API keys, origin address, shipping zones, boxes, services, live rates, product audits, labels, tracking, and manifests. Or install one skill and hand the whole job to an AI agent that runs the same commands and stops to ask when it needs a key. Either way the work is visible and repeats across stores, on the same engine behind thousands of WooCommerce stores in the 1TeamSoftware line, rated 4.8 to 5.0.
One prerequisite, said plainly: many official carrier integrations import orders and print labels but never quote a rate at checkout. If your current tool can’t return a price to the cart, no command will make one appear there. The 1TeamSoftware shipping plugins quote live rates at cart and checkout, validate addresses, pack boxes, buy labels, and track shipments, and they expose all of it through WP-CLI. What follows is the working catalog: every command, when to reach for it, and what comes back. The examples all use Shippo, but the engine is shared across all eight carrier plugins, so the same workflow applies whether you run Shippo, FedEx, ShipStation, or any of the others. Only the namespace changes.
Try Shippo Shipping Free on WordPress.org | See Shippo Shipping PRO Features
How the plugins compare to official carrier tools
Here is how the plugins stack up against the carriers’ own official tools:
| Capability | Official carrier tools | 1TeamSoftware plugins |
|---|---|---|
| Live rates at cart and checkout | Often missing | Yes |
| Buy and print labels | Yes | Yes (PRO) |
| Run setup and fulfillment from WP-CLI | No | Yes |
| Drive it with an AI agent | No | Yes |
| Multivendor (per-vendor rates) | No | Yes |
TL;DR
- Configure WooCommerce shipping settings entirely from WP-CLI: credentials, origin, zones, boxes, services, and rate adjustments.
- Audit your catalog, size your boxes, quote live rates, buy and merge labels, pull tracking, and gate deploys, all from the command line.
- Commands are identical across 8 carriers. Only the namespace changes (the plugin slug minus
-pro). Confirm yours withwp help | grep shipping. - Setting keys vary per carrier (especially credentials). Run
wp <namespace> settings listto discover the exact keys before you write anything. - Verify with
validateand a realrates quote. A quote that returns rates is the only real proof the carrier is reachable. - Install the free agent skill and an assistant like Claude Code runs the whole sequence for you.
$ npx skills add https://github.com/1TeamSoftware/skills --skill 1teamsoftware-wc-shippingWhat you can do from the command line
Every command follows one shape: wp <namespace> <command> [<subcommand>] [--flags]. The namespace is the plugin slug with -pro removed, so Shippo is wc-shippo-shipping for both the free and PRO editions. The examples below use Shippo. Swap in your carrier’s namespace, and run wp help | grep shipping first to confirm it.
One thing the command list won’t tell you: the exact setting keys. Credential fields, service IDs, and box types differ per carrier, so discover them instead of guessing. settings list shows the real setting keys with secrets redacted, services shows valid service IDs, and boxes presets shows carrier box dimensions.
The commands below are a working set, not the whole surface. For every command, flag, and output shape, see the full WP-CLI command reference.
Status, validation, and capabilities
Start here. These commands show what the plugin sees and whether the config holds up.
$ wp wc-shippo-shipping status
field value
Plugin Version 2.4.8
Carrier Shippo
Sandbox Mode Yes
Debug Mode No
Cache Yes
Live Rates Yes
Origin Country US
Origin City San Francisco
Shipping Method Instances 1
Multi-Vendor Platform NoneThen run validate to check every config item at once, from license and origin to box dimensions and cart rates:
$ wp wc-shippo-shipping validate validator status message License Status PASS License is activated API Settings INFO Ship From PASS From Address configured Box Dimensions PASS Box dimensions within carrier limits Box Optimization INFO Box configuration suggestions Product Dimensions WARN Only 27% of products have valid dimensions Boxes PASS 1 box(es) configured and enabled Cart Rates PASS Rates working: 4/4 routes, 15 rate(s) total Shipping Services PASS 7 service(s) available: 4/4 routes, 15 rate(s) total Shipment Defaults PASS Shipment defaults configured Rate Adjustments PASS No rate adjustments configured Parcel Adjustments PASS No parcel adjustments configured Shipping Zones PASS Using global shipping rates (not zone-based) Cache Settings PASS Cache settings optimized Automation Settings PASS Automation settings configured correctly Sandbox Mode INFO Sandbox mode is active Automation PASS WordPress cron looks healthy for 2 automation feature(s)
To see what the carrier itself supports, features prints the capability flags for labels, returns, tracking, address validation, and more:
$ wp wc-shippo-shipping features
feature supported
Sandbox yes
ShipmentDate no
GetRates no
CreateShipment yes
BuyShipment no
RefundShipment no
CancelShipment no
ReturnLabel yes
CreateOrder yes
GetOrder no
CreateManifest yes
AddressValidation yes
UseSellerAddress yes
Insurance yes
Signature yes
Alcohol yes
DryIce yes
COD no
SaturdayDelivery yes
HoldForPickup no
Tariff yes
CustomItems yes
GetShipments yes
GetShipment yes
LinkShipment noThen list the real service IDs you can enable, and check which WooCommerce zones the plugin is attached to:
$ wp wc-shippo-shipping services --format=json $ wp wc-shippo-shipping zones zone_id zone_name zone_locations plugin_active instance_id method_id 1 United States US no - - 3 E2E Test Zone US yes 3 wc-shippo-shipping 0 Locations not covered by your other zones Everywhere else no - -
statusreports version, carrier, sandbox and debug flags, live-rate state, origin, and method-instance count. There is no API-connectivity field here; arates quoteis the connectivity test.validateruns every config check and reports PASS, FAIL, WARN, INFO, or PENDING. It exits non-zero on any FAIL, which is what makes it a clean CI gate.featureslists carrier capability flags (labels, returns, tracking, address validation, and so on). These describe what the carrier can do; for the service IDs you actually set, useservices.serviceslists the real service IDs and their enabled status. This is the list you set when you configure which services quote.zonesshows which WooCommerce shipping zones the plugin is attached to, withplugin_active,instance_id, andmethod_idper zone.
Settings
These read and write any stored setting, from credentials to origin.
$ wp wc-shippo-shipping settings list
key value
licenseKey [REDACTED]
debug no
cache yes
cacheExpirationInSecs 86400
timeout 45
sandbox yes
displayAdvancedSettings yes
combineBoxes yes
useCubeDimensions no
enableLiveShippingRates yes
validateAddress no
requireCompanyName no
requireCountry yes
useSellerAddress no
useVendorSettings no
allowMultipleShipments yes
allowCreateShipmentFeature yes
allowReturnLabelFeature yes
allowMediaMailFeature yesTo read or write a single setting, target it by key. Here is the origin address being read, then set in one JSON blob:
$ wp wc-shippo-shipping settings get origin $ wp wc-shippo-shipping settings set origin '{"name":"Co","address":"123 Main St","city":"SF","state":"CA","postcode":"94105","country":"US"}'
settings list is your map. It prints every setting with sensitive values shown as [REDACTED], and it’s how you find a carrier’s credential keys before you set them. Associative settings flatten with bracket notation (origin[city], services[usps_priority][enabled]); list settings like boxes print as a raw JSON blob. Read one value with settings get <key> (add --raw to reveal a secret), write one with settings set <key> <value>, and target a single zone with --instance=<id>.
Product readiness
Rates depend on weight and dimension data. These commands tell you whether your catalog has it.
$ wp wc-shippo-shipping products audit
Metric Count Details
Total physical products 5980
Products with weight 4462
Products with dimensions 1671
Products missing weight 1518
Products missing dimensions 4309
Complete products 1671 27.9%From there you can pull the per-product breakdown and dig into size, order patterns, and box fit:
$ wp wc-shippo-shipping products audit --detailed --format=json --limit=0 $ wp wc-shippo-shipping products stats --format=json $ wp wc-shippo-shipping products orders --since=2025-12-01 --format=json $ wp wc-shippo-shipping products fit-box --length=12 --width=8 --height=6
products auditgives a completeness percentage and flags missing weight, missing dimensions, and suspicious values. The per-product lists only appear with--format=json; in table mode--detailedshows the same summary as plainaudit. Pass--limit=0so big catalogs aren’t capped at 500.products statsreturns weight and dimension stats, a size distribution from tiny to oversized, and the top items by volume.products ordersanalyzes completed and processing orders: items per order, top destination states, domestic versus international, and the largest multi-item orders by item count.products fit-boxtakes box dimensions (all three required) and reports what percentage of your catalog fits, with a sample of products that don’t. Rotation is handled automatically.
Rates
Rates are the point of the whole setup. These confirm the carrier returns live prices for a product or an order.
$ wp wc-shippo-shipping rates quote --products="8359:1" --destination="1600 Pennsylvania Ave NW, Washington, DC 20500, US"
Quoting rates for 1x product 8359 (0.01 lbs) to 1600 Pennsylvania Ave NW, Washington, DC 20500, US...
service cost days
USPS Ground Advantage 5.97
USPS Priority Mail 13.48
USPS Priority Mail Express 47.63To quote a real order instead of an ad-hoc product, pass its ID:
$ wp wc-shippo-shipping rates get --order=12345rates quoteasks the carrier for a live quote on an ad-hoc product and destination. It needs at minimum a ZIP or postcode plus a country; a full street address improves accuracy. This is the connectivity proof. It prints a human log line before the JSON, so when you script it, extract the JSON array from the first[to the matching]rather than relying on2>/dev/null.rates getquotes an existing order by ID.
Fulfillment commands (PRO)
Once a license is active, these handle fulfillment: packing, buying labels, and tracking shipments.
$ wp wc-shippo-shipping boxes presets --carrier=USPS $ wp wc-shippo-shipping shipments create --orders=1240,1241 $ wp wc-shippo-shipping labels purchase --orders=1240,1241 $ wp wc-shippo-shipping labels pdf --orders=1240,1241 --output=/var/labels/today.pdf $ wp wc-shippo-shipping track abc123 --order=1240 --format=json $ wp wc-shippo-shipping manifest create --shipments=abc123,def456 --ship-date=2026-06-11 $ wp wc-shippo-shipping license activate YOUR-KEY
boxesis PRO only.boxes presetsreturns carrier box dimensions already converted to your store units;boxes typesreads the carrier’s package-type catalog and needs configured credentials.shipments create/list/get/fetchgive you manual control over shipments before you spend on postage.labels purchasebuys labels in a batch and auto-creates shipments if missing.labels pdfmerges many orders into one print-ready PDF;labels downloadandlabels refundhandle single labels. Note thatlabels purchaselogs label counts, not tracking numbers.trackreturns status plus the event timeline; it needs both the positional shipment ID and--order.manifest createbuilds a carrier SCAN form from shipment IDs you list explicitly.license activatetakes the key as a positional argument, not--key=. On the PRO plugin,license,boxes, andstatusare always available; the operational commands appear once the license is active.
These commands ship with the PRO version of your carrier’s plugin. If you fulfill from WooCommerce and want labels, batch printing, tracking, and manifests on the same CLI, the carrier product pages at the end list each PRO edition.
A note on --format: status, validate, features, services, zones, and rates accept the full table|json|csv|yaml|count set. The products subcommands, boxes, track, and settings list accept only table|json; anything else fails loudly.
Hand it to an AI agent
Install the skill once and an assistant like Claude Code drives every command above from plain language. The skill is a small library of playbooks, so when you ask it to fix box coverage, it reaches for the box-sizing routine instead of guessing at flags. The agent runs the same CLI a human would, and it pauses to ask for secrets rather than inventing them.
$ npx skills add https://github.com/1TeamSoftware/skills --skill 1teamsoftware-wc-shippingThe free plugin ships 6 skills; PRO adds 4. After installing, describe what you want with real constraints. Here are the kinds of prompts the skill is built to handle:
- “Set up Shippo from scratch. Sandbox key is shippo_test_abc123, we ship from 215 Clayton St, San Francisco 94117. Before live rates, audit my catalog for missing weight or dimensions, recommend a starter box set from what I actually sell, and prove rates come back with a real quote. Ask one question at a time and don’t touch my live key yet.”
- “Rotate our Shippo credentials to this new live key. First show me which credential field this carrier actually uses, set it, confirm the old secret is gone, and verify with a live quote before we trust it.”
- “Customers in some regions say no shipping options appear. Make the plugin active for both my US domestic zone and Rest of World, then show me the zone coverage table so I can confirm it’s attached where it needs to be.”
- “Our shipping is undercharging. Survey live rates for my three best sellers to a few US zones, then add a 15% markup plus a flat $2 handling fee, show me the before and after, and apply it only after I confirm.”
- “We’re going live this week. Confirm the license is active, set our live key and origin, audit and fix product data, build a box set, confirm the carrier supports label purchase and tracking, then buy a test label and pull tracking on one real order so I can see the whole pipeline before we open up.”
- “Customers say no rates appear at checkout. Diagnose the root cause systematically, check zones, services, product data, and the carrier route, and if a complete product on a covered route still returns nothing, tell me whether it’s a real connectivity failure or just a route the carrier doesn’t serve.”
Real use cases
Thousands of products missing weight or dimensions
Take a catalog imported over years. A product has no weight, so rates silently drop, the customer sees no shipping option and leaves, and nothing in the logs tells you why. Missing product data is one of the most common reasons a carrier returns nothing at all.
You’d ask the agent something like: “Audit every physical product for missing weight and dimensions, give me the completeness percentage and the full list of what’s incomplete (don’t cap it, I have a big catalog), then research real specs from manufacturer sources, apply only high-confidence values to the parent and every variation in my store’s units, and list the rest for me to confirm by hand. Never make up a number.”
What runs:
$ wp wc-shippo-shipping products audit --detailed --format=json --limit=0The agent reads the missing_weight_products, missing_dimensions_products, and suspicious_data_products arrays, researches the real specs, converts them to your woocommerce_weight_unit and dimension_unit, and writes them with wp wc product update to the parent and each variation. It applies only high-confidence values and hands you the low-confidence and not-found ones to approve.
Edge cases it respects: virtual and downloadable products are excluded automatically; variations inherit weight and dimensions from the parent, so fixes update both; and suspicious values are flagged when a weight tops about 70 lb (32 kg) or any single dimension exceeds about 72 in (183 cm). It never fabricates a spec.
You end up with a higher completeness percentage, rates that stop dropping, and a short list of genuine unknowns to settle by hand.
What boxes should I use
Rates can look high for a dull reason: parcels get quoted in oversized boxes because nobody ever matched the box set to what the store actually ships.
You’d ask: “Analyze my last 6 months of orders and my catalog, recommend a box set that covers about 90% of what I ship, prefer USPS flat-rate boxes where they’d be cheaper for heavy items, show me the coverage table before applying anything, and keep my existing custom boxes.”
What runs:
$ wp wc-shippo-shipping products stats --format=json $ wp wc-shippo-shipping products orders --since=2025-12-01 --format=json $ wp wc-shippo-shipping boxes presets --carrier=USPS --format=json $ wp wc-shippo-shipping products fit-box --length=12 --width=8 --height=6 $ wp wc-shippo-shipping settings set boxes '[{"enabled":"yes","boxName":"Small","type":"parcel","length":"8","width":"6","height":"4","weight":"0.5","maxweight":"20"}]'
products stats and products orders describe the real shapes and carts. The agent maps the fields from boxes presets into the boxes schema (name becomes boxName, add enabled, drop carrier and maxweight); the preset output is not pasteable as-is. It tests candidate boxes with products fit-box, shows you a coverage table, then applies the merged set with settings set boxes. If there’s no order history it falls back to catalog-only and says so.
The result: a box set sized to your catalog and order patterns, with coverage you can see before committing. (boxes presets is PRO; on a free install you write the boxes setting directly.)
Rates don’t show in some regions: shipping zones
This one hides. Rates work for some customers and not others, so you only hear about it when a buyer emails to say they can’t check out. It’s the number-one cause of “no rates at checkout.” The plugin only returns rates on zones where it’s attached as a shipping method, so a missing zone is a silent dead end.
You’d ask: “rates quote works from the CLI but checkout shows nothing for some customers. Figure out which zone those addresses fall into, check whether the plugin is actually attached, and add it where it’s missing.”
What runs:
$ wp wc-shippo-shipping zones $ wp wc shipping_zone_method create --zone_id=2 --method_id=wc-shippo-shipping --user=1
zones shows each zone’s plugin_active, instance_id, and method_id. Where it reads plugin_active: no, the method gets added. In zone-based mode, being absent from a zone means no rates there; in global mode, that’s fine. Once attached, per-zone overrides are possible with --instance (different boxes or services for international versus domestic) without touching your global defaults.
Now the plugin is present on the right zones, and checkout returns rates.
Rate tuning: markup, floors, and which services show
Three versions of the same complaint: shipping is undercharging, the checkout shows too many options, or a $1.50 Media Mail rate is leaking through. The adjustment fields all live in the free plugin and are writable with the free settings command.
You’d ask: “Survey live rates for my best sellers to a few US zones, add a 15% markup plus $2 handling, hide anything under $5, keep only the cheapest 3, and show me before and after first.”
What runs:
$ wp wc-shippo-shipping settings set priceAdjustmentPercent 1.15 $ wp wc-shippo-shipping settings set priceAdjustment 2.00 $ wp wc-shippo-shipping settings set minRateCost 5.00 $ wp wc-shippo-shipping settings set maxShippingRates 3 $ wp wc-shippo-shipping services --format=json $ wp wc-shippo-shipping settings set services '{"usps_ground_advantage":{"enabled":true,"name":"USPS Ground Advantage"}}'
priceAdjustmentPercent is a multiplier, so 1.15 adds 15% (15 would multiply every rate fifteenfold). Adjustments apply in order: carrier rate, then percent, then fixed, then floor and ceiling, then the max-count cap. To control which services quote at all, discover real IDs with services and write them with settings set services; never invent IDs. A re-quote confirms the new numbers before sign-off.
The result: rates land inside a sane band, the checkout list is short, and only the services you chose appear.
Buy a test label before going live
Before real customers hit it, watch the full fulfillment pipeline run once, safely, end to end.
You’d ask: “In sandbox, buy a test label for order 1240, then pull its tracking so I can see the whole pipeline before we go live.”
What runs:
$ wp wc-shippo-shipping settings set sandbox yes $ wp wc-shippo-shipping labels purchase --orders=1240 $ wp wc-shippo-shipping track <shipment-id> --order=1240 --format=json $ wp wc-shippo-shipping labels pdf --orders=1240 --output=/tmp/test-label.pdf
labels purchase creates the shipment if needed and logs how many labels it bought; it does not print the tracking number. Get the tracking number from track or shipments get, and export the printable PDF with labels pdf (or labels download for a single label). Labels are a PRO feature.
You walk away with a confirmed label, retrievable tracking, and a printable PDF, all without spending live postage.
Print labels: by hand, with AI, or automated
The label commands work the same whether a person runs them, an agent runs them, or a cron job does. Daily fulfillment is a batch:
$ wp wc-shippo-shipping labels purchase --orders=1240,1241,1242 $ wp wc-shippo-shipping labels pdf --orders=1240,1241,1242 --output=/var/labels/2026-06-11.pdf
labels purchase skips orders that no longer exist and gives a per-order summary. labels pdf requires --output and errors if the file already exists, so dated filenames are safest.
Two automation patterns are worth setting up once. First, a deploy gate. Because validate exits non-zero on any FAIL, it blocks a release when shipping is broken:
$ wp wc-shippo-shipping validate --format=json 2>/dev/null \
| jq -e 'all(.[]; .status != "FAIL")' >/dev/null \
|| { echo "Shipping config has failures"; wp wc-shippo-shipping validate; exit 1; }WARN does not fail the build, only FAIL does. Second, a nightly label run: collect the day’s processing order IDs, buy their labels in one batch, and merge them into a dated PDF for the morning print station. For hands-off tracking and order sync, the PRO plugin also has built-in automation cron settings (see the wp-config automation reference).
Works the same across every carrier
All 8 plugins share one engine, one settings model, and one set of commands. What changes is the namespace, plus a few setting keys. Confirm the namespace with wp help | grep shipping, then discover keys with settings list.
| Plugin | Carrier | CLI namespace |
|---|---|---|
| Shippo | Shippo (100+ carriers) | wc-shippo-shipping |
| EasyPost | EasyPost (100+ carriers) | wc-easypost-shipping |
| FedEx | FedEx | wc-fedex-shipping |
| ShipStation | ShipStation | wc-shipstation-shipping-v2 |
| ShipEngine | ShipEngine | wc-shipengine-shipping |
| Shipmondo | Shipmondo | wc-shipmondo-shipping |
| ChitChats | Chit Chats | wc-chitchats-shipping |
| Stallion Express | Stallion Express | wc-stallionexpress-shipping |
One ShipStation catch: the current plugin runs on the carrier’s API v2, so its namespace is wc-shipstation-shipping-v2. The legacy v1 plugin used wc-shipstation-shipping. When in doubt, run wp help | grep shipping and use what it prints. Credential keys also differ by carrier: Shippo uses testApiToken and liveApiToken, and others name theirs differently, so always read settings list before writing.
Carrier pricing is never hard-coded in these plugins, which is why a live rates quote is always the source of truth. For real numbers, check the carrier’s own pricing pages rather than any cached estimate. If you’re choosing between the big aggregators first, see ShipStation vs Shippo vs EasyPost.
Security
Nothing exotic here. It’s the handful of habits that keep a live key from leaking:
- Start in sandbox. Switch to a live key only after a sandbox quote succeeds, and always set the live key before you flip
sandbox no, or no token is active and rates fail. - Hand an agent the sandbox key during setup, then rotate to the live key yourself. The agent never needs to see the real one.
- Store credentials in
wp-config.phpconstants instead of the database. Those constants override the DB, never get written back to it, and can hide credential fields from the admin UI. This is how agencies lock down managed-hosting fleets. - Output redacts secrets by default.
settings listprints them as[REDACTED], andsettings getkeeps them hidden unless you pass--raw.
Frequently asked questions
Yes. The 1TeamSoftware shipping plugins expose the full setup through WP-CLI: credentials, origin, zones, boxes, services, rate adjustments, product audits, and live rate quotes, plus labels, tracking, and manifests in PRO, all under a per-plugin namespace like wp wc-shippo-shipping.
Yes. Install the 1teamsoftware-wc-shipping skill, point an assistant like Claude Code at your site, and describe what you want. It runs the documented WP-CLI commands and pauses to ask for anything sensitive, like an API key. The skill is the same CLI a human would use, with no hidden layer.
Work down the list: validate to find config failures, zones to confirm the plugin is attached to the customer’s shipping zone, products audit to find missing weights and dimensions, and rates quote to test the carrier directly. Most cases are a zone the plugin isn’t on, or products with no weight.
All 8 plugins: Shippo, EasyPost, FedEx, ShipStation, ShipEngine, Shipmondo, Chit Chats, and Stallion Express. The commands are identical; only the namespace and a few setting keys change. Run wp <namespace> settings list to confirm the keys for your carrier.
Use the sandbox key during setup and switch to the live key yourself after verifying. Secrets are redacted in CLI output, and you can store credentials in wp-config.php constants instead of the database. The agent never invents keys; it asks.
The free plugins cover configuration and diagnostics: status, settings, products, zones, services, rate adjustments, rate quotes, and validate. Labels, shipments, tracking, manifests, box presets, and license commands are PRO, with matching CLI commands.
For one store you set up once, it isn’t. The CLI wins the moment shipping becomes something you operate: multiple stores, staging-to-production parity, agency work that repeats per client, audits you can re-run, and workflows an agent can drive.
Run wp help | grep shipping to see the namespace (the plugin slug minus -pro), then wp <namespace> settings list to see the exact setting keys with secrets redacted. Use services for valid service IDs and boxes presets for carrier box dimensions.
Get started
The free plugins cover configuration and live rate quotes; the PRO versions add labels, tracking, and manifests. These plugins already run on thousands of WooCommerce stores, so this is a well-worn path. Install the free skill, point your assistant at a staging store, and run a validate plus a rates quote to watch the whole loop work.
$ npx skills add https://github.com/1TeamSoftware/skills --skill 1teamsoftware-wc-shippingCarrier product pages:
- Shippo Shipping for WooCommerce
- ShipStation Shipping for WooCommerce
- EasyPost Shipping for WooCommerce
- FedEx Shipping for WooCommerce
- ShipEngine Shipping for WooCommerce
- Shipmondo Shipping for WooCommerce
- ChitChats Shipping for WooCommerce
- Stallion Express Shipping for WooCommerce
- Or compare the big three first: ShipStation vs Shippo vs EasyPost
