A Danish shopper fills a basket, reaches the shipping step, and sees one flat rate. Nothing about doorstep versus the pickup point down the street. So they leave. Nordic buyers expect that choice, and a checkout that hides it loses the order. Baymard puts average cart abandonment near 70%, with surprise shipping cost high on the list of reasons people bail. A flat rate that ignores the live PostNord, GLS, DAO and Bring prices Shipmondo can return is that exact surprise. Your job at checkout is to show the real price before a buyer decides to walk, and setting up Shipmondo shipping on WooCommerce properly is how you do it.
Here is the catch most Shipmondo merchants hit. The official Shipmondo for WooCommerce plugin lets a shopper pick a pickup point, but it never returns the live carrier price to the cart. You eat the difference on every order, then book the label by hand in a second tool afterward. If your current setup can’t quote a real price at checkout, no amount of configuration will make one appear there.
This guide sets up Shipmondo on WooCommerce so that:
- live carrier rates come back in the cart;
- labels print from the order screen, and tracking reaches the customer;
- you configure all of it from WP-CLI, or hand it to an AI agent that runs the same commands and stops to ask when it needs a key.
The same engine runs under every plugin in the 1TeamSoftware shipping line, and we build and support it ourselves.
Try Shipmondo Shipping Free on WordPress.org | See Shipmondo Shipping PRO Features
What the official Shipmondo integration does and doesn’t do
Know the dividing line before you start.
| Capability | Official Shipmondo for WooCommerce | 1TeamSoftware Shipmondo plugin |
|---|---|---|
| Pickup-point selection at checkout | Yes | Yes |
| Live carrier rates in the cart | No | Yes |
| Buy labels from the WooCommerce order screen | Via the Shipmondo web app | Yes (PRO) |
| Per-zone services, boxes, and origin | No | Yes |
| Multivendor origin (Dokan, WCFM, WCMP / MVX) | No | Yes |
| Run setup and fulfillment from WP-CLI | No | Yes |
| Drive it with an AI agent | No | Yes |
The official plugin is fine if all you need is a pickup-point widget and you book every label inside Shipmondo’s own dashboard. The moment you want the actual PostNord or GLS price shown live in the basket, you have outgrown it. That is the line this guide is built for.
A few Shipmondo prerequisites to line up first:
- A Shipmondo account with API access. Generate your API credentials from the API settings page inside your Shipmondo account.
- Shipmondo authenticates with an API user plus an API key, not a single token. You will set both, and you should confirm the exact field names with
wp wc-shipmondo-shipping settings listrather than assuming them. - If you came from Pakkelabels, your old login is your Shipmondo login, and the same credentials carry your carrier contracts across.
- Check Shipmondo’s own pricing page for current per-label and plan costs, since these change and are never hard-coded in the plugin.
TL;DR
- Set up Shipmondo on WooCommerce entirely from WP-CLI: credentials, origin, zones, boxes, services, and rate adjustments. Live PostNord, GLS, DAO and Bring rates then appear in the cart.
- The CLI namespace is
wc-shipmondo-shipping(the plugin slug minus-pro), the same for free and PRO. Confirm it withwp help | grep shipping. - Shipmondo uses an API user plus an API key, not one token, with a separate production pair (
api_user,api_key) and sandbox pair (test_api_user,test_api_key). Confirm the exact keys withwp wc-shipmondo-shipping settings listbefore writing anything. - Verify with
validateand a realrates quote. A quote that returns rates is the only proof the carrier is reachable. - Shipmondo creates the shipment and its label in one step, so the PRO label workflow runs through
shipments create, thenlabels pdfortrack(there is no separatelabels purchasestep for this carrier). - 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 for Shipmondo is wc-shipmondo-shipping for both the free and PRO editions. Run wp help | grep shipping first to confirm it on your install.
The command list won’t tell you the exact setting keys. Shipmondo names its credential fields api_user and api_key for production, with test_api_user and test_api_key for the sandbox. That is a user plus a key, not the single token most US carriers use, so don’t guess the rest. Read the real keys off your own install with settings list, find valid service IDs with services, and read carrier box dimensions with boxes presets.
The commands below are a curated 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 read what the plugin sees and tell you whether the config holds up.
$ wp wc-shipmondo-shipping status --format=json $ wp wc-shipmondo-shipping validate $ wp wc-shipmondo-shipping features $ wp wc-shipmondo-shipping services --format=json $ wp wc-shipmondo-shipping zones
statusprints the snapshot the plugin is working from: version, carrier, the sandbox and debug flags, whether live rates are on, your origin, and how many method instances exist. It deliberately omits any carrier-connectivity field, so treat arates quoteas your reachability check.validatewalks the full set of config checks and tags each one PASS, FAIL, WARN, INFO, or PENDING. Because a single FAIL makes it exit non-zero, you can drop it straight into a pipeline as a gate.featureslists Shipmondo’s capability flags (PascalCase, supported yes or no) such asCreateShipment,CreateManifest,ReturnLabel, andAddressValidation. Read this list on your own account before you script a label workflow, because what the carrier exposes drives which operations you get. Note that Shipmondo reportsCreateShipment, notBuyShipment: its API books the shipment and its label in a single call, so the label workflow runs throughshipments createrather than a separate buy step.serviceslists the real Shipmondo service IDs (PostNord, GLS, DAO, Bring, DHL, Posti) and their enabled status. This is the list you set, notfeatures.zonesshows which WooCommerce shipping zones the plugin is attached to, withplugin_active,instance_id, andmethod_idper zone.
A real validate run reads like this, each check tagged so you can see at a glance what still needs attention:
$ wp wc-shipmondo-shipping validate License Status PASS License is activated Ship From PASS From Address configured Product Dimensions WARN Only 27% of products have valid dimensions Cart Rates PASS Rates working: 4/4 routes, 15 rate(s) total Shipping Services PASS 7 service(s) available Shipping Zones PASS Using global shipping rates Sandbox Mode INFO Sandbox mode is active
Settings
Use these to read and write any stored setting, from credentials to origin.
$ wp wc-shipmondo-shipping settings list $ wp wc-shipmondo-shipping settings get api_user $ wp wc-shipmondo-shipping settings set origin '{"name":"Butik","address":"Vesterbrogade 1","city":"Copenhagen","postcode":"1620","country":"DK"}'
settings list is your map. It prints every setting with sensitive values shown as [REDACTED], and it is how you discover Shipmondo’s credential keys before you set them. Associative settings flatten with bracket notation (origin[city], services[...][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>. Shipmondo keeps production and sandbox credentials separate: api_user/api_key for live, test_api_user/test_api_key for the sandbox. When sandbox is yes, the plugin reads the test_* pair, so set those while you test (confirm the exact key names with settings list first):
$ wp wc-shipmondo-shipping settings set test_api_user "[email protected]" $ wp wc-shipmondo-shipping settings set test_api_key "your-sandbox-api-key" $ wp wc-shipmondo-shipping settings set sandbox yes
When you go live, set api_user and api_key from your production account and flip sandbox no.
Product readiness
DKK-per-kilo carriers price on weight and dimensions. Run these to find out whether your catalog actually carries that data.
$ wp wc-shipmondo-shipping products audit --detailed --format=json --limit=0 $ wp wc-shipmondo-shipping products stats --format=json $ wp wc-shipmondo-shipping products orders --since=2025-12-01 --format=json $ wp wc-shipmondo-shipping products fit-box --length=30 --width=20 --height=15
products auditreturns a completeness percentage and calls out three things: products with no weight, products with no dimensions, and values that look wrong. You only get the per-product breakdown in--format=json; the table view of--detailedjust repeats the summary that plainauditalready shows. Add--limit=0or a large catalog stops at the first 500 rows.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 regions, 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. Dimensions are in your store unit, so the values above assume centimeters.
Rates
Everything else exists to make this step work. These confirm Shipmondo returns live prices for a product or an order.
$ wp wc-shipmondo-shipping rates quote --products="9405:2" --destination="Strøget 1, Copenhagen, 1160, DK" $ wp wc-shipmondo-shipping rates get --order=12345
rates quoteasks Shipmondo for a live quote on an ad-hoc product and destination. It needs at minimum a 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.
A note on delivery estimates. The rate that comes back is a price, and a transit-time promise may not ride along with it. If you want to signal an ETA at checkout, fold it into your service display name rather than expecting the rate to carry one.
Fulfillment commands (PRO)
These cover fulfillment once a license is active: packing, creating shipments and their labels, and tracking. Shipmondo is a one-step carrier, so the order of operations differs from most US carriers.
$ wp wc-shipmondo-shipping boxes presets --carrier=PostNord $ wp wc-shipmondo-shipping shipments create --orders=1240,1241 $ wp wc-shipmondo-shipping labels pdf --orders=1240,1241 --output=/var/labels/today.pdf $ wp wc-shipmondo-shipping track abc123 --order=1240 --format=json $ wp wc-shipmondo-shipping manifest create --shipments=abc123,def456 --ship-date=2026-06-11 $ wp wc-shipmondo-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.- Shipmondo’s API books the shipment and its label in a single call, so
shipments createis the step that produces the label. It reportsCreateShipment, notBuyShipment, infeatures, and that is why there is no separatelabels purchasestep for this carrier. Aftershipments create, pull the PDF withlabels pdf(batch) orlabels download(single). trackreturns status plus the event timeline; it needs both the positional shipment ID and--order.manifest createbuilds a Shipmondo end-of-day document from shipment IDs you list explicitly. There is no “all pending” shortcut.- Shipmondo has no refund endpoint, so there is no
labels refundfor this carrier; cancel an unshipped booking from the Shipmondo dashboard before it leaves. 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.
The labels, tracking, manifest, and multivendor commands ship with PRO. If you fulfill from WooCommerce and want them on the same CLI, the Shipmondo Shipping PRO product page has the details.
One caveat on --format. The full table|json|csv|yaml|count range works on status, validate, features, services, zones, and rates. The products subcommands, boxes, track, and settings list are narrower, taking only table|json, and they error out plainly on anything else.
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 set of playbooks, so when you ask it to fix box coverage it reaches for the box-sizing routine instead of guessing at flags. There is no hidden layer here. It runs the same CLI you would, and it stops to ask for a key rather than inventing one. Hand it your sandbox credentials during setup, then rotate to live yourself afterward.
$ npx skills add https://github.com/1TeamSoftware/skills --skill 1teamsoftware-wc-shippingThe free plugin ships 6 skills; PRO adds 4. Once it’s installed, describe what you want with real constraints. These are the kinds of prompts it is built for:
- “Set up Shipmondo from scratch. Sandbox API user is [email protected], sandbox key is sm_test_abc123, we ship from Vesterbrogade 1, Copenhagen 1620. 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 to a Copenhagen postcode. Ask one question at a time and don’t touch my production key yet.”
- “Rotate our Shipmondo credentials to this new production API user and key. First show me which fields this carrier actually uses, set both, confirm the old secret is gone, and verify with a live quote before we trust it.”
- “I only want PostNord and GLS at checkout for Danish domestic, nothing else. List the real Shipmondo service IDs first, enable exactly those two, disable the rest, and show me the enabled list when you’re done.”
- “Customers in some regions say no shipping options appear. Make the plugin active for both my DK domestic zone and a Nordic zone, then show me the zone coverage table so I can confirm it’s attached where it needs to be.”
- “Survey live PostNord and GLS rates for my three best sellers to a few Danish and Swedish postcodes, then add a 10% handling markup, show me before and after, and apply it only after I confirm.”
- “We’re going live this week. Confirm the license is active, set our production credentials and origin, audit and fix product data, build a box set, book a test shipment on one real order in sandbox, and pull its tracking so I can see the whole pipeline before we open up.”
Real use cases
A flat rate is quietly burning your margin
The most common Nordic setup is a single flat rate on every order, and it’s wrong in both directions. Heavy parcels cost more than the flat rate, so you swallow the loss. Light parcels get overcharged, so the shopper abandons. Nobody sees the real PostNord or GLS price, because nothing is asking for it.
You’d ask the agent: “Replace my flat rate with live Shipmondo rates. Set my sandbox credentials, confirm a real quote comes back for a 2 kg parcel to a Copenhagen postcode, then enable PostNord and GLS at checkout.”
What runs:
$ wp wc-shipmondo-shipping settings set test_api_user "[email protected]" $ wp wc-shipmondo-shipping settings set test_api_key "sm_test_abc123" $ wp wc-shipmondo-shipping settings set sandbox yes $ wp wc-shipmondo-shipping rates quote --products="9405" --destination="Strøget 1, Copenhagen, 1160, DK" $ wp wc-shipmondo-shipping services --format=json $ wp wc-shipmondo-shipping settings set services '{"...":{"enabled":true}}'
The agent reads the real service IDs from services (it never invents them), enables the ones you named, and proves the carrier answers with a live rates quote. The shopper now sees the actual carrier price for their basket and their postcode.
Which boxes should I ship in
Rates look high for a dull reason: parcels get quoted in oversized boxes because the box set was never matched to what the store actually ships. Define real boxes and PostNord and GLS finally see the correct dimensions.
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, show me the coverage table before applying anything, and keep my existing custom boxes.”
What runs:
$ wp wc-shipmondo-shipping products stats --format=json $ wp wc-shipmondo-shipping products orders --since=2025-12-01 --format=json $ wp wc-shipmondo-shipping boxes presets --carrier=PostNord --format=json $ wp wc-shipmondo-shipping products fit-box --length=30 --width=20 --height=15 $ wp wc-shipmondo-shipping settings set boxes '[{"enabled":"yes","boxName":"Small","type":"parcel","length":"30","width":"20","height":"15","weight":"0.5","maxweight":"20"}]'
products stats and products orders describe the real shapes and the real carts. Here’s the catch: you can’t paste boxes presets straight into the boxes setting. The output has to be reshaped first, renaming each name to boxName, adding an enabled flag, and dropping the carrier and maxweight fields the schema doesn’t take. The agent does that translation, tries the candidates through products fit-box, shows you a coverage table, and only then writes the merged set. With no order history behind it, it works from the catalog alone and tells you so. (boxes presets is PRO; on the free plugin you populate boxes yourself.)
No rates appear for some customers: shipping zones
This one hides well. Rates come back for some shoppers and not others, so the first you hear of it is usually a buyer emailing to say checkout gave them nothing. The plugin only quotes on zones where it’s attached as a shipping method, so any Nordic zone it isn’t attached to simply goes quiet. More “no rates at checkout” reports trace back to this than to anything else.
You’d ask: “rates quote works from the CLI but checkout shows nothing for my Swedish customers. Figure out which zone those addresses fall into, check whether the plugin is attached, and add it where it’s missing.”
What runs:
$ wp wc-shipmondo-shipping zones $ wp wc shipping_zone_method create --zone_id=3 --method_id=wc-shipmondo-shipping --user=1
zones shows each zone’s plugin_active, instance_id, and method_id. Wherever it reads plugin_active: no, that’s a zone missing the method, and the agent adds it. In zone-based mode, being absent from a zone means no rates there; in global mode it doesn’t matter. Once attached, per-zone overrides through --instance let you run a different carrier mix for DK domestic versus a Nordic neighbors zone without touching your global defaults.
Tuning rates: handling fees, floors, and which services show
Three flavors of one complaint: shipping undercharges, the checkout shows too many carrier options, or a near-zero rate is slipping through. The adjustment fields all live in the free plugin and you write them with the free settings command.
You’d ask: “Survey live rates for my best sellers to a few Danish postcodes, add a 10% markup plus a flat handling fee, hide anything under 20 DKK, keep only the cheapest 3 options, and show me before and after first.”
What runs:
$ wp wc-shipmondo-shipping settings set priceAdjustmentPercent 1.10 $ wp wc-shipmondo-shipping settings set priceAdjustment 15.00 $ wp wc-shipmondo-shipping settings set minRateCost 20.00 $ wp wc-shipmondo-shipping settings set maxShippingRates 3
Watch the multiplier here: priceAdjustmentPercent is exactly that, so 1.10 adds 10%, while 10 would blow every rate up tenfold. The adjustments apply in a fixed order: carrier rate first, then the percent, then the fixed amount, then any floor and ceiling, and last the max-count cap. The fixed amount reads in store currency, so 15.00 means 15 DKK if that’s what you price in. Re-quote afterward and read the new numbers back before you sign off.
Book a test shipment before going live
You want to watch the full pipeline run once, safely, before real customers hit it. Because Shipmondo books the shipment and label together, the test is a single shipments create.
You’d ask: “In sandbox, book a test shipment for order 1240, then pull its tracking and the label PDF so I can see the whole pipeline before we go live.”
What runs:
$ wp wc-shipmondo-shipping settings set sandbox yes $ wp wc-shipmondo-shipping shipments create --orders=1240 $ wp wc-shipmondo-shipping shipments list --order=1240 $ wp wc-shipmondo-shipping track <shipment-id> --order=1240 --format=json $ wp wc-shipmondo-shipping labels pdf --orders=1240 --output=/tmp/test-label.pdf
shipments create books the shipment and its label in one call. Read the shipment ID back with shipments list, get the tracking from track, and export the printable PDF with labels pdf (or labels download for a single label). These are PRO features.
Print labels: by hand, with AI, or automated
The label commands behave the same whether a person at a keyboard runs them, an agent runs them on your behalf, or a scheduled cron does. A Shipmondo work day comes down to booking the shipments in one batch and merging their labels into one PDF:
$ wp wc-shipmondo-shipping shipments create --orders=1240,1241,1242 $ wp wc-shipmondo-shipping labels pdf --orders=1240,1241,1242 --output=/var/labels/2026-06-11.pdf
shipments create books each order’s shipment and label and skips orders that no longer exist. Because Shipmondo merges a whole batch of PostNord and GLS labels into one document, labels pdf insists on an --output path and refuses to clobber a PDF that is already there; stamp the day’s date into the filename and each batch lands in its own file.
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-shipmondo-shipping validate --format=json 2>/dev/null \
| jq -e 'all(.[]; .status != "FAIL")' >/dev/null \
|| { echo "Shipping config has failures"; wp wc-shipmondo-shipping validate; exit 1; }A WARN, like the dimension gap Shipmondo flags on a thin catalog, leaves the release alone; only a FAIL stops it. Second, a nightly run: collect the day’s processing order IDs, book their shipments in one batch, and merge the labels into a dated PDF for the morning print station. For hands-off tracking and order sync, PRO also has built-in automation cron settings (see the wp-config automation reference).
Works the same across every carrier
All 8 plugins in the line 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 the 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 |
The setting keys are where carriers differ most. Shipmondo uses api_user and api_key; a US carrier like Shippo uses testApiToken and liveApiToken. So always read settings list before writing. Carrier pricing is never hard-coded in these plugins, which is why a live rates quote is the source of truth. For real numbers, check the carrier’s own rate cards rather than any cached estimate. If you also ship outside the Nordics and want to compare the big aggregators, see ShipStation vs Shippo vs EasyPost.
Security
Nothing clever here. It comes down to a few small habits that keep a live key from ever leaking:
- Start in sandbox. Set your sandbox
test_api_userandtest_api_key, leavesandbox yes, and switch to production only after a sandbox quote succeeds. Set the productionapi_userandapi_keybefore you flipsandbox no, or no key is active and rates fail. - Hand an agent the sandbox key during setup, then rotate to the production 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. It’s 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.
That’s the whole Shipmondo setup, from credentials to a live PostNord or GLS quote in the cart. For the reasoning behind running shipping setup this way, and the same command catalog applied to the other seven carriers, see Configuring WooCommerce Shipping with AI Agents and WP-CLI.
Frequently asked questions
Install the plugin, then set your Shipmondo sandbox credentials from WP-CLI: wp wc-shipmondo-shipping settings set test_api_user "[email protected]" and settings set test_api_key "...", leaving sandbox yes while you test (switch to api_user/api_key and sandbox no for production). Set your origin, enable the carrier services you want with settings set services, attach the plugin to your shipping zones, and confirm with validate and a live rates quote. Live PostNord, GLS, DAO and Bring rates then appear in the cart.
You don’t need both. The official plugin handles pickup-point selection but never returns live carrier rates in the cart. This one does both, live rates plus a label and tracking workflow, on the same Shipmondo account.
PostNord, GLS, DAO, Bring, DHL, Posti, and the rest of Shipmondo’s Nordic and European network, depending on your agreement. Discover the exact service IDs your account exposes with wp wc-shipmondo-shipping services --format=json, then enable the ones you want with settings set services.
Not much. Shipmondo is the 2019 rebrand of Pakkelabels, so your old login is your Shipmondo login and your carrier contracts carry through. Read your credential keys with settings list, set api_user and api_key, and verify with a live rates quote.
Work down the list in order: 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, then rates quote to test Shipmondo directly. Most cases come down to a Nordic zone the plugin isn’t attached to, or products with no weight.
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 stops to ask for anything sensitive, like your API key. Same CLI a person would run, no hidden layer.
The rate that comes back is a price, and a transit-time promise may not be part of it. If you want to signal an ETA, fold it into your service display name rather than expecting it from the rate.
The free plugin covers configuration and diagnostics: status, settings, products, zones, services, rate adjustments, rate quotes, and validate, with live rates in the cart. Labels, shipments, tracking, manifests, box presets, multivendor, and license commands are PRO.
Get started
The free plugin gives you live Nordic rates at checkout. PRO adds the label, tracking, manifest, and multivendor workflow. Install the free skill, point your assistant at a staging store with your sandbox credentials, 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-shipping- Shipmondo Shipping PRO for WooCommerce
- WooCommerce shipping setup from the command line or AI (the full command catalog across all 8 carriers)
- ShipStation vs Shippo vs EasyPost
About the author: 1TeamSoftware builds and maintains the eight WooCommerce shipping plugins covered here, used by thousands of stores.

