GoatLabels GoatLabels
One file in. Every label out.

Bulk shipping labels from a CSV


Mapped once. Checked before you pay.

Upload a CSV, map your columns to shipping fields once and save the mapping, then validate every row before any money moves. Rows with a bad address are flagged, the rest are quoted across USPS, UPS and FedEx (DHL on international rows), and the file is purchased row by row from one prepaid wallet.

Every row rate-shopped, not the file as a lump

USPS, UPS and FedEx quote each domestic row's own parcel, DHL joins on international rows, so a heavy row and a light row in the same upload can land on different carriers.

UPS FedEx DHL USPS DHL: international
Per-row quotes Not one carrier for the file.
Validated first Before any money moves.
All-in price Nothing added at checkout.

One prepaid wallet for the whole file

Rows are bought one at a time against a single balance, so a half-finished file leaves you with exactly the labels you paid for and nothing in between.

VisaMastercardAmerican ExpressApple PayGoogle PayBitcoinEthereumTether (USDT)
Debited per row Card, Apple Pay, Google Pay, ACH, crypto.
Failed rows retry Individually, not the whole file.
Re-run is safe Bought rows are skipped, not doubled.

Updated 2026-10-16

What columns does a shipping CSV need?

Less than most people assume, and in a stricter form than most people expect. Eight fields have to resolve before a row can be bought: recipient name, address line 1, city, a two-letter ISO country code, weight, length, width, and height. That is the whole required set. Everything else in the catalog is optional — order number, company, email, phone, address line 2, state or province, postal code, package type, a pinned carrier, a pinned service, and the three customs columns of declared value, item description, and HS code.

Two of those deserve calling out because they are where clean-looking files break. Country has to be ISO-2 — US, GB, HK — not "United States" and not "USA", because that code is what selects which carrier services are even eligible for the row. And the three dimensions are required, not the nice-to-have they are on a single manual shipment, because a file is quoted without a human looking at each box. The one exception is a USPS flat-rate container: map the package type column instead and the dimensions stop mattering, since the container defines them.

Your file almost certainly does not use those names, and it does not have to. Headers are matched after lower-casing and stripping punctuation, so "Shipping Postal Code", "shipping_zip" and "Zip Code" all land on the same field, and the usual Shopify, Etsy, Amazon and eBay export headers are recognised on sight. One deliberate exception: any column starting with "From" is never auto-mapped, because bulk import always ships from your account's saved sender address and marketplace exports habitually put junk in their From columns. If the reason you are exporting at all is that Shopify has paused label buying, skip the file: shipping Shopify orders while label buying is on hold covers syncing the store instead.

Download the CSV template

If you are building the file by hand rather than exporting it, start from the template. Its 21 headers are spellings the importer recognises on sight, so every column auto-maps on the mapping step with nothing left to pick, and the three example rows cover the three shapes a file usually mixes: a domestic parcel with dimensions, a USPS flat-rate box with no dimensions, and an international row with the customs columns filled. Delete the examples, keep the header row, add your shipments.

Download goatlabels-bulk-labels-template.csv 21 columns, 3 example rows, 1 KB. Weight in pounds, dimensions in inches.

The dashboard's Upload step also offers Domestic, International and Multi-box template buttons, so you never have to come back here for a copy.

Column mapping: every field, every accepted header

This is the complete field catalog the mapping step offers, with the header spellings auto-detect recognises for each. Matching ignores case, spaces and punctuation, so "Shipping Postal Code", "shipping_postal_code" and "SHIPPINGPOSTALCODE" are the same header. Any header that starts with "From" is skipped on purpose; the file never sets the sender.

GoatLabels field Required Accepted header aliases Example
Order number optional Order Number, Order ID, Order, Order Name, Order Num, Ref, Reference 1001
Recipient name required Recipient Name, Name, Ship To Name, To Name, Buyer Name, Customer Name, Shipping Name, Full Name Tino Martinez
Company optional Company, Company Name, Business Name, Shipping Company Bennett & Co
Email optional * Email, Buyer Email, Customer Email, Shipping Email, Recipient Email tino@example.com
Phone optional * Phone, Phone Number, Shipping Phone, Buyer Phone, Recipient Phone, Tel, To Phone Number +1 609 555 0134
Address line 1 required Address 1, Address Line 1, Line1, Street, Street Address, Shipping Address1, Address, To Address1 1528 Riverside Dr
Address line 2 optional Address 2, Address Line 2, Line2, Apt, Suite, Shipping Address2, To Address2 Apt 2
City required City, Town, Shipping City, To City Trenton
State / Province optional State, Province, Region, Shipping State, Shipping Province, To State/Province NJ
Postal code optional Postal Code, Postcode, Zip, Zip Code, Shipping Zip, Shipping Postal Code, To Zip/Postal Code 08618
Country (ISO-2) required Country, Country Code, Shipping Country, Shipping Country Code, ISO2, To Country US
Weight required Weight, Weight (kg), Weight (lb), Weight (lbs), Parcel Weight, Ship Weight 2.5
Length required Length, Length (cm), Length (in), Box Length 12
Width required Width, Width (cm), Width (in), Box Width 9
Height required Height, Height (cm), Height (in), Box Height 4
Package type optional Package Type, Packaging, Box Type, Parcel Type, Package Medium Flat Rate Box
Boxes (multi-box) optional Boxes, Parcels, Packages, Multibox, Box List 3 x 24x18x18 @ 32lb
Carrier optional Carrier, Courier, Shipping Carrier, Preferred Carrier USPS
Service optional Service, Service Level, Shipping Service, Service Type, Shipping Method Priority
Declared value (USD) optional Declared Value, Declared Value USD, Value, Item Value, Customs Value, Total 60
Item description optional Description, Item Description, Items, Item Name, Title, Product Name Leather wallet
HS code international HS Code, Harmonized Code, Tariff Code, HTS 4202.31

* Email and phone are optional columns, but the carrier contact rules checked at the validate step want a recipient phone and email on most rows (USPS and every international service), so a file without them fails validation with "Recipient phone required" rather than at purchase. Weight and dimensions are read in the unit you set on the mapping step, kg or lb and cm or in; a header ending in "(lbs)" switches the weight unit to pounds for you. Boxes is read where multi-box shipments are enabled on your account; elsewhere the row asks you to split it into one row per box.

How to import the file, step by step

The Bulk import page is a four-step wizard and the step names below are the ones on screen. The whole first pass, including saving the preset, takes about fifteen minutes; every file of the same shape after it takes the upload.

  1. Upload. In the dashboard open Shipments and choose Bulk import. On the Upload CSV card drop your file on "Drop your CSV here" or click Choose file. The first row must be your column headers; the file must be .csv, UTF-8, under 2 MiB and at most 500 rows. If you do not have an export yet, start from the template above.
  2. Map columns. On Map your columns, each GoatLabels field shows the header the auto-detect picked; fix the blanks with one dropdown per field. Set the weight unit (kg or lb) and the dimension unit (cm or in) for the whole file, and optionally a default country, weight or box size for rows that leave the cell empty. Type a name such as "Etsy export" and click Save preset so the next file of the same shape is one click. Then click Validate rows.
  3. Validate & quote. Validation results lists every row with its problems named on the row: a missing required field, a country that is not ISO-2, a phone or email the carrier will reject, an undeliverable address. Fix the file or go Back to mapping, re-run, then click Get rates to quote every valid row: USPS, UPS and FedEx on domestic rows, DHL joining on international rows. Each row takes the cheapest all-in option for its own parcel unless its Carrier and Service columns pin it.
  4. Purchase. Click Buy labels. Rows are bought one at a time from your prepaid wallet; the summary counts purchased, skipped and failed rows, and a failed row has its own Retry. Re-running a file never buys a row that already has a label. Print the stack from Shipments.

Mapping columns once and saving it: the second file takes minutes

Auto-detection gets most of the way and then stops, because no heuristic knows whether your "Total" column is the order total or the declared customs value. The mapping step is one dropdown per field, grouped by recipient, address, package, customs, and service, with the required ones marked — you finish what auto-detection started, set whether weights are pounds or kilos and dimensions inches or centimetres, and you are done.

Then save it under a name. "Etsy export", "backer survey", "wholesale PO". The next file of the same shape applies that preset in one click, and the presets list is yours to manage — apply, rename by saving again, delete. This is the difference between a one-off import and a repeatable process: the first file costs you ten minutes of mapping, and every file after it costs you the upload. If you are fulfilling a crowdfunding campaign, the late-pledge file and the replacement-parts file are the same shape as the original survey export, which is exactly the case presets are for — shipping labels for Kickstarter covers the rest of that job. Wholesale sellers get the same benefit from the opposite direction: a Faire purchase order has the same columns every month, and shipping labels for Faire explains why each carton in a multi-carton order needs its own row. A Big Cartel shop has no connector at all, so its order export is the integration, and batch-shipping a Big Cartel drop is one saved preset plus one upload.

Validating before you pay, not after the boxes come back

The validate step is the reason to do this in a wizard rather than a script that buys as it reads. Every row is checked before any money moves: required fields present, address accepted by the carrier network, country code valid, weights and dimensions in range, phone and email well-formed where they are supplied, and a restricted-goods keyword scan that mirrors the one a single shipment gets — so a row that would be refused at purchase is refused now, at the point where fixing it is free.

Rows come back with their problems named on the row rather than as a count at the top. A missing secondary unit, a postal code that does not match the city, an ISO code that is actually a country name — you edit, re-check, and move on. Good rows do not wait for bad ones; they proceed to quoting while you repair the rest. This is the single highest-value step in the whole flow, because the alternative version of catching these is a pallet of returns three weeks later, and what happens to a parcel that comes back costs the label twice plus the packaging. Most of those defects repeat from file to file, and why a real address fails validation covers each one and its fix.

Once rows are valid they are quoted in batch against USPS, UPS and FedEx, with DHL on international rows, and each row takes the cheapest all-in option for its own parcel, not one carrier chosen for the whole file. Rows that have to go a specific way keep their pinned carrier or service from the mapped columns. International rows use the customs columns you mapped; duties default to the recipient unless you explicitly choose to prepay them, and what to write on the form is on customs forms for small parcels.

What happens when a row fails mid-file?

Purchasing runs sequentially, one row at a time, and that is a deliberate design decision rather than a performance limitation. A parallel fan-out would let two rows clear the same wallet-balance check against the same starting balance and over-debit you; serialising the purchases makes the balance arithmetic exact. It also means a failure is contained to its own row instead of poisoning the batch.

So when a row fails — the carrier declines it, the address turns out to be undeliverable at purchase time, the balance will not stretch — that row reports its own error and the file carries on or stops with the reason visible. You get a summary of how many purchased, how many were skipped, and how many failed, and you can retry a single failed row without touching the ones that worked. Re-running a file you have already partly bought is safe: rows with a label already attached are recognised and skipped rather than purchased a second time.

One thing to know before a very large run: on the Free plan the monthly shipment allowance is enforced per row as the batch executes, so a file that starts under the cap stops exactly at it rather than silently overshooting, and the remaining rows report why. A single file is capped at 500 rows, so larger exports get split — which is a reasonable review checkpoint anyway. The plan detail is on pricing.

How a whole shipping day is sequenced around the file, from merging channels to packing against the printed stack, is on the batch fulfillment day workflow. Files exported from a warehouse system follow the same path; the warehouse angle is on shipping labels for warehouses. Print-on-demand shops that ship the stickers, prints, and bundles their provider does not handle use the same file path, and self-fulfilled print-on-demand orders covers which orders to keep in-house.

Four steps, in this order

Upload, map, validate, then buy.

The order matters more than the steps do. Mapping happens before validation so the checker knows which column is the postal code; validation happens before quoting so a broken row never reaches a carrier; quoting happens before purchase so you approve the price. Money moves last, one row at a time.

1
One file in
However your platform exports it
orders-export.csv

Ship To Name, Ship To Address 1, Ship To City, Ship To Zip, Weight (lbs) — whatever your platform decided to call them.

Shopify export
Order CSV, unedited
TikTok Shop export
Different headers, same mapping
Parsed preview
Required fields
8
Optional fields
13
Country format
ISO-2
Row cap per file
500
Drop a .csv — headers auto-detected

Marketplace exports, warehouse extracts, backer surveys, wholesale POs — anything that saves as a .csv.

2 Billy Map & validate

Mapped once, then checked row by row.

Billy AI
  • One dropdown per field, grouped by recipient, address, package, customs, service
  • Saved as a named preset — the next file of the same shape is one click
  • Every row validated before any money moves, with the reason on the row
  • Good rows carry on to quoting while you repair the bad ones
Mapped. Validated. Quoted.
3
Bought row by row
Cheapest carrier, per parcel
One prepaid wallet
Debited per row, never in parallel
per row
USPS
Labels purchased
Failed rows retry individually
resumable

Purchased, skipped, and failed are counted separately — and re-running a file never buys a row twice.

Every export. One mapping step.

Whatever exported the file, the columns still map.

Shopify, Amazon, eBay, Etsy, Walmart and the rest of the 13 connected stores can sync orders straight into the To Ship queue with no file at all — but their CSV exports import just as happily, and their header names are recognised on sight. Anything that saves as a .csv works: a warehouse extract, a backer survey, a wholesale PO, a spreadsheet somebody keeps by hand.

Shopify logo Shopify
Etsy logo Etsy
WooCommerce logo WooCommerce
TikTok Shop logo TikTok Shop
Amazon logo Amazon
eBay logo eBay
Squarespace logo Squarespace
Wix logo Wix
Walmart logo Walmart
Shopify Plus logo Shopify Plus Soon
Square logo Square
BigCommerce logo BigCommerce
Magento logo Magento
Zapier logo Zapier Soon
NetSuite logo NetSuite Soon
Ecwid logo Ecwid Soon
Temu logo Temu
Shein logo Shein Soon
ChannelAdvisor logo ChannelAdvisor Soon
SkuVault logo SkuVault Soon
Zoho Inventory logo Zoho Inventory Soon
Patreon logo Patreon
Four things that make a batch survivable

The hard part of bulk is not printing.
It is everything before it.

Anyone can loop over a file and call an API. What decides whether a 400-row import is a good afternoon or a bad month is what happens to the rows that are wrong, and whether the money moved before or after you found out.

One wallet,
debited row by row

Rows are purchased sequentially against a single prepaid balance, so two rows can never clear the same balance check and over-debit you. Fund it with a card, Apple Pay, Google Pay, ACH, or crypto. Stop halfway and you own exactly the labels you paid for.

Wallet balance
$1,247.36 USD
AI

Saved mapping presets,
named by you

Headers are auto-detected from the common marketplace exports, you finish the mapping by hand, and then you save it. Apply it to the next file in one click. The first import costs ten minutes; every import after it costs the upload.

Billy Billy LIVE
Where's the package to Maya?
It's in transit via UPS. Expected Friday, Aug 7.
UPS
1Z8923A6B05G4123456
In transit
Austin, TX → Dallas, TX
Ask Billy anything...

Per-row validation
before any money moves

Required fields, carrier address validation, ISO-2 country codes, weight and dimension ranges, phone and email format, and a restricted-goods scan — all at the validate step, all with the failure reason on the offending row. Fixing is free; printing a bad row is not.

Shipment summary
UPS Ground $12.49
Insurance $0.75
Fuel surcharge $0.32
Total $13.56

Every row quoted
across the file

USPS, UPS and FedEx price each domestic row's own parcel, DHL joins on international rows, and the cheapest all-in option wins per row, so the file does not get flattened onto one carrier. Rows that must go a specific way keep a pinned carrier or service from their mapped columns.

Compare rates
UPS UPS $12.48
FedEx FedEx $13.22
DHL DHL $14.10
USPS USPS $11.79
Duties inside the quote where DDP applies

Or skip the wizard
and call the API

If the file is really a database query, the REST API does the same job programmatically with signed webhooks, real idempotency keys so a retried row never buys two labels, and unlimited calls on every plan.

POST /v1/shipments
{
"to": { "name": "Maya" },
"from": { "name": "Alex" },
"service": "ups_ground",
"label_format": "pdf"
}
Webhook delivered
GoatLabels mobile shipments queue with all-in carrier prices
Billy drafting a label from a pasted order on mobile

Label ready

CL-1038 · Seattle, US

The rows the file did not have

The stragglers, without a second file.

Every batch has a tail: the late pledge, the address correction that arrived by DM, the one carton nobody counted. Re-exporting and re-mapping a file for three rows is absurd, so those go the other way: straight from the phone, into the same queue, against the same carriers and the same wallet.

Paste or snap the corrected address — Billy pulls the name, address, and item and validates it.
USPS, UPS and FedEx come back with all-in prices side by side on one screen, DHL on international lanes.
Buy it from the same prepaid balance the batch was bought from — one ledger, not two.
One-tap print to your phone's share sheet or a thermal printer over Wi-Fi.
Hands full of tape? Hold the mic, speak the address, and Billy quotes it and queues the label.
Billy is included, not a paid tier

Ask what the file did without reopening it.

A 400-row import turns into 400 questions later, and the answers are not in the spreadsheet you uploaded. Ask out loud — "where's Maya's package?" — and Billy pulls the tracking history and reads it back. The same assistant drafts and validates the one-off rows the batch missed, on every plan, at no extra cost. This is the real product, not a render.

goatlabels.io/dashboard/shipments — Billy
Billy reading back a parcel's tracking history over the purchased labels list

Listening

"Where's Maya's package?"

Out for delivery

CL-1039 · Austin, TX · by 6 PM

Speaks plain English · answers for labels bought in a batch or one at a time · remembers customers and saved boxes · included on every plan.

All-in quotes, per row

Each row gets its own all-in prices.

A file is not one shipment, and flattening it onto one carrier is how a batch quietly overpays. Every valid row is priced against its own parcel by the carriers that serve its lane, DHL among them on international rows, each column a single all-in number locked at quote time, so a heavy row and a light row in the same upload can end up on different carriers.

US → DE 2.6 lbs 12×8×4 in
Cheapest for this row
USPS

USPS

Priority Mail Intl

10–15 days

$7.40

$1.90 of duties & taxes prepaid on the rows that carry customs columns

all-in · no surprises

FedEx

FedEx

Intl Connect Plus

3–5 days

$8.90

$2.20 of duties & taxes prepaid on the rows that carry customs columns

all-in · no surprises

DHL

DHL

Express Worldwide

1–2 days

$9.80

$2.50 of duties & taxes prepaid on the rows that carry customs columns

all-in · no surprises

Pinned rows keep their mapped carrier Accepted void → credit back to your wallet Multi-currency display
Public API v1

If the file is really a database query.

Plenty of batches start life as a SELECT and only become a CSV because something downstream wanted one. Skip the export: REST, JSON, one Bearer header, and real idempotency keys so a retried row never buys two labels — with unlimited calls on every plan, which is what makes looping over ten thousand rows a non-event.

Quote and buy per row from your own loop — no per-request pricing, ever
Real idempotency keys — a retried row never buys a second label
Signed webhooks instead of polling for tracking events
OpenAPI 3.1 spec, no SDK lock-in, and no 500-row file cap to work around
Read the API docs Get a free API key $0 on every plan
curl https://api.goatlabels.io/api/v1/shipments
POST /api/v1/shipments
Authorization: Bearer sk_live_…
Idempotency-Key: ord_8421

{
  "to": { "name": "Joyce", "city": "Berlin", "country": "DE" },
  "parcel": { "weight": 2.6, "weight_unit": "lb" },
  "service": "fedex_intl_priority"
}
What a big file actually costs

No per-file fee. No per-row fee.

Importing is not a paid feature and neither is the wizard. Free covers 50 shipments a month — and because the plan allowance is enforced per row as the batch executes, a file that starts under the cap stops exactly at it rather than silently overshooting. Pro lifts the cap entirely.

Pro

Most popular
$40 / month
Unlimited shipments — the per-row plan check stops stopping you
Unlimited address validation
Billy AI on Telegram Telegram logo — chase a failed row without opening the dashboard
API access still free and unlimited

Rate by plan

illustrative
Free Pro

Pro: one flat monthly plan, unlimited shipments

Free

$0 / forever

Import, map, validate, and save presets on the free plan — the labels are the only cost.

50 shipments a month, no monthly fee
CSV import with saved mapping presets and per-row validation
Every valid row rate-shopped: USPS, UPS and FedEx domestic, DHL international
Billy AI in the web app, unlimited — for the rows the file missed
REST API with unlimited calls; fund by card, Apple Pay, Google Pay, ACH, or crypto

Billy is not an upsell

The assistant that turns a pasted order or a screenshot into a validated draft runs unlimited in the web app on Free. It is what you use for the late pledge and the corrected address — the rows that were never going to be worth a second file. Pro adds Billy on Telegram.

Web, every plan Telegram logo Telegram, Pro

API free on every plan

GET /api/v1/shipments

200 OK · plan: free

Unlimited calls on Free — still unlimited on Pro, which is what makes a scripted import cheaper than a metered one.

Bring what you pay today

On Pro we will work with you to beat the label rates you are already getting from

ShippoPirate ShipShipStation
No per-file fee No monthly fee Presets saved on Free
USPS UPS FedEx DHL

Every row's price is quoted live from USPS, UPS and FedEx (DHL on international rows) as one all-in number, and that exact amount leaves your prepaid wallet as the row is bought. Nothing is added at checkout and nothing is billed per file. Full pricing details

Whose orders arrive as a file

Four jobs that are a spreadsheet first.

These are the shapes where orders never arrive one at a time: they arrive as an export, a survey, a purchase order, or a migration — and the label work is a batch from the moment it starts.

Crowdfunding creators

One survey export, hundreds of identical boxes

Highest volume, once

A backer survey is the purest bulk case there is: one file, one parcel spec, and addresses that have been sitting in a form for a year. Map it once, validate every row before you print, and the late-pledge file reuses the same preset.

500 rows per file saved preset per-row validation
goatlabels.io/dashboard/shipments
GoatLabels shipments queue with purchased labels

Wholesale and B2B brands

Shopify logoWooCommerce logo Purchase orders, not shopping carts

Wholesale orders arrive as a PO or a buyer's spreadsheet, often with several cartons per account and a column layout that never changes from month to month. That stability is exactly what a saved mapping preset is for.

Pinned where it matters

Map the carrier column to hold one account's rows to one carrier

Etsy logo

Sellers migrating a backlog

Etsy logoShopify logo Moving off another platform mid-queue

exported 240 unshipped orders from the old tool
Mapped, validated, and bought in one pass

Anyone whose orders start as a query

Warehouse extracts and internal systems

8

required columns — the rest of the catalog is optional

Bulk CSV labels, answered

Can I upload a CSV to print shipping labels in bulk?
Yes. Upload a .csv, map its columns to shipping fields, validate every row, and purchase the file row by row. It is a four-step wizard — upload, map columns, validate and quote, purchase — and a single file can carry up to 500 rows. Larger exports are split into several files, which is also how you keep a very large batch reviewable.
What columns does the file need?
Eight fields have to resolve for a row to validate: recipient name, address line 1, city, a two-letter ISO country code, weight, and the three box dimensions. Everything else is optional — order number, company, email, phone, address line 2, state, postal code, package type, a pinned carrier or service, and the customs columns of declared value, item description, and HS code. If you use a USPS flat-rate container you map the package type instead of supplying dimensions.
What happens to rows with a bad address?
They are flagged at the validate step, before any money moves, with the reason on the row — a missing required field, an address the carrier rejects, a country code that is not valid ISO-2, a phone or email that is malformed. You fix the row and re-run the check. Nothing about a failed row blocks the good rows; they carry on to quoting while you repair the rest.
Can I rate-shop the whole file, or do I pick a carrier first?
Rate-shop the whole file. Every valid row is quoted against the carriers that serve its lane, USPS, UPS and FedEx on domestic rows and DHL as well on international rows, and the cheapest option for that specific parcel is selected per row, so a heavy row and a light row in the same upload can end up on different carriers. If a row has to go on a particular carrier or service, map the optional carrier and service columns and that row is pinned while the rest keep rate-shopping.
What happens if my wallet runs out halfway through the file?
Purchasing runs one row at a time on purpose, so the balance arithmetic can never be raced by two rows at once. When the balance will not cover the next row, that row fails with the reason and purchasing stops there — the labels already bought are bought and printable, and nothing partial or duplicated is left behind. Top the wallet up and re-run the file: rows that already purchased are recognised and skipped rather than bought twice.
Do I have to remap the columns every time?
No. Save the mapping under a name once — "Etsy export", "backer survey", "wholesale PO" — and apply it to the next file of the same shape in one click. Headers are auto-detected first anyway, because the common marketplace exports use predictable names, so the saved preset mostly exists to nail the columns that auto-detection cannot guess.

Common import errors and what fixes them

The messages below are the ones the validate, quote and purchase steps actually print on a row, in roughly the order a first import meets them.

"Only .csv files are supported" or "CSV had no header row"
The importer reads .csv only, so export or Save As CSV from Excel, Numbers or Google Sheets before uploading; .xlsx and .numbers files are refused at the file picker. "CSV had no header row" and "CSV had no data rows" mean the first line was empty or the file held headers and nothing else. Row one must be the column names and row two the first shipment.
"CSV exceeds the 500-row cap" or "CSV payload exceeds 2 MiB"
A single upload is capped at 500 data rows and 2 MiB. The message tells you how many rows were found; split the export into files of 500 or fewer and import them one after another with the same saved preset. Rows that already purchased in an earlier run are recognised and skipped, so overlapping files are safe.
"Missing recipient name", "Missing address line 1", "Missing city"
A required field is mapped to no column, or that cell is blank on this row. Check Map your columns first: if the dropdown for that field is empty, auto-detect did not recognise your header, so pick it by hand (or rename the header to one of the aliases in the table above). If the mapping is right, the row itself is missing the value and needs editing in the file.
"Unrecognized country" or "Missing or invalid ISO-2 country code"
Country must be a two-letter ISO code: US, GB, CA, HK. Full names such as "United States" and three-letter codes such as "USA" are refused rather than guessed, because that code decides which carrier services are eligible for the row. One repair is built in: "UK" is accepted and becomes GB. If every row ships to the same country, leave the column out and set a default country on the mapping step.
"Missing or invalid weight" (or length, width, height)
The cell is blank, zero or not a number after stripping units and symbols; "2.5 lb" is read as 2.5, but "two pounds" is not. All four are required for a parcel row because the file is quoted without a human looking at each box. Two ways out: set a default weight or default box size on the mapping step for rows that leave the cell empty, or put a USPS flat-rate container in Package type, in which case the container supplies the dimensions and a blank weight defaults to 1 lb.
"Unrecognized package type"
A warning, not an error: the row still validates and quotes by its dimensions. The Package type column is only read for USPS flat-rate containers, and it accepts their display names with or without the USPS or Priority Mail prefix: Flat Rate Envelope, Padded Flat Rate Envelope, Legal Flat Rate Envelope, Small Flat Rate Box, Medium Flat Rate Box, Large Flat Rate Box, Large Flat Rate Board Game Box. Anything else, including "parcel" or "box", produces this warning and is otherwise ignored.
"Recipient phone required" or "The recipient email address doesn't look valid"
The carrier contact rules are checked at the validate step, before quoting, so you fix them in the file instead of hitting a per-row rejection at purchase. Unpinned domestic rows are checked against the USPS rules and international rows against the international rules, both of which want a recipient phone and email; a row pinned to a carrier uses that carrier's rules. A value that is present but malformed fails the format check: phone numbers need digits and an optional country code, emails need a real local part and domain. The sender side comes from your saved default address, so "Sender phone required" is fixed in the Address Book, not the file.
"Address is undeliverable" or "The recipient address was rejected"
The first comes from address validation at the validate step, the second from the carrier at quote time. Both mean the street, city, state and postal code do not resolve to a deliverable point: a transposed house number, a city that does not match the postal code, a missing apartment on a multi-unit building, or a US zip whose leading zero a spreadsheet removed (three- and four-digit US zips are padded back automatically, so 8618 becomes 08618). Fix the row and re-validate; the good rows do not wait for it.
"Set a default sender address before quoting"
Bulk import always ships from your account's default sender in the Address Book, and any "From ..." columns in the file are deliberately ignored. Add a sender address, mark it as the default, and run the quote step again. Nothing in the file needs to change.
"Restricted item" or "Item customs details rejected"
The item description is scanned against the restricted-goods list the single-shipment flow uses; a blocked category fails the row and a review category only warns. "Item customs details rejected" comes back on international rows whose HS code, declared value or country of origin the carrier would not accept, with the field named in the message. Use a six- to ten-digit HS code and a declared value above zero; see customs forms for small parcels for what belongs in each column.
"Row was not validated; re-run the validate step" or "Upgrade to Pro for unlimited shipments"
The first appears when a file was edited or remapped after validation, so the row's checked state is stale: click Validate rows again, then Get rates. The second is the Free plan's monthly shipment allowance, enforced per row as the batch executes, so a file that starts under the cap stops exactly at it and the remaining rows report why. Either wait for the month to roll or move to Pro; the labels already bought are bought.
Real sellers, real words

Sellers whose orders arrive by the hundred.

A video took off and I had 80 TikTok Shop orders by morning. I printed every label from my phone on the bus to the post office.
E

Early customer · TikTok

TikTok Shop seller

TikTok logo TikTok Shop
I run my Etsy shop from the kitchen. The AI reads the order, picks the carrier, the label prints. That's the whole workflow now.
E

Early customer · Etsy

Etsy maker

Etsy logo Etsy
The API is what every shipping API pretends to be. Idempotency that actually works.
S

Sasha R.

Staff engineer, marketplace

API user
Free up to 50 shipments a month. No per-file fee.

Stop pasting addresses
one row at a time.

Upload the export, map the columns once, let every row be validated before a cent moves, then buy the file against USPS, UPS and FedEx (DHL on international rows) from one prepaid wallet.

No card required. Save the mapping and the next file is a one-click job.

Updated