Shipping labels & returns
Connect a carrier account
Labels are bought through your own EasyPost or Shippo account, at your rates.
await commerce.store.configureShipping({
provider: "easypost", // or "shippo"
api_key: process.env.EASYPOST_API_KEY!,
ship_from: { name: "Acme", line1: "1 Dock Rd", city: "Seattle", state: "WA", postal_code: "98101", country: "US" },
default_parcel: { length: 10, width: 8, height: 2 }, // inches
});Set weight_oz on variants so parcels are weighed automatically.
Rates and labels
const { data: rates } = await commerce.orders.shippingRates(1001); // cheapest first
const { data: label } = await commerce.orders.buyLabel(1001, rates.data[0].id, { max_cost: 1500 });
// label.label_url → print it. The order is now "fulfilled" and the customer has tracking.A rate can only be bought once, and max_cost is checked against the real price before buying.
Returns
// Customer asks to return one item
const { data: ret } = await commerce.returns.create(1001, {
items: [{ variant_id, quantity: 1 }],
reason: "Too small",
});
// Approve and email a prepaid return label
await commerce.returns.approve(ret.id, { return_label: "cheapest" });
// Items arrive: restock them and refund their value through Stripe
await commerce.returns.receive(ret.id); // { restock: true, refund: true } by defaultYou can't return more than was ordered, and receiving a return can't refund twice. Use returns.reject(id, { note }) to decline one.
Refunds without a return
await commerce.orders.refund(1001, { amount: 1000 }); // partial
await commerce.orders.refund(1001, { restock: true }); // full, back into stockRefunds made in the Stripe Dashboard are picked up automatically.