Every call to POST /v1/commerce/submissions and POST /v1/commerce/submissions/calculate needs a shipping object, and both accept the same values. The one difference is that shipping.address is optional on calculate, so you can price a basket before checkout collects an address (see Response Bodies).
shipping objectaddress
object, required on submit
Where the order ships: name, addr1, addr2, city, state, zip, country (2-letter code), and optionally attn (an attention line), email and phone. There is no company field: sending one returns 400. International destinations may also need a phone in E.164 format, for example +15551234567. Optional on calculate only.
Every address needs name, addr1 and city. Send country every time too: an address without one is read as a US address, not reported as incomplete. A US address also needs a 2-letter state and a zip of at least 5 characters. Outside the US, state and zip are optional. Submit with a field missing and you get a 400 (submission.not_submittable) with one invalidParams[] entry per field, named like shipping.address.zip. Calculate with a partial address still answers 200, with validation.isValidForSubmit: false and the same entries in validation.invalidParams[], so you can check an address before you submit. A zip under 5 characters or a 1-letter state also makes isValidForSubmit false, with an entry whose reason gives the length rule (Must be at least 5 characters., Must be 2 characters.). See what WHCC checks.
type
string, optional
dropship ships straight to your customer. studio ships to you. Leave it out and it defaults to dropship, or follows priority when you send one: studio_* means studio, dropship_* means dropship. If you send both, they must agree. If your account can't use that type for these products, the request is rejected with a 400 naming shipping.type.
Studio shipping goes to US and Canadian street addresses only: not to a PO Box, and not outside the US and Canada.
priority
string, optional
The shipping method. Which methods a basket can use depends on the type, the address and the products in it, so take the value from options.shipping[] on a calculate response for that address (see below). Leave it out and WHCC uses the least expensive method the destination offers. A priority from the other type, or one the destination doesn't offer, is rejected with a 400 (see the note at the end of this page).
returnAddress
object, optional
The return address WHCC prints on the shipping label of a drop-ship order. Leave it out and the label carries the address on your WHCC account. See Return address.
Call calculate with the basket, shipping.type and the address, and no priority. The response prices the basket with the least expensive method for that destination, and options.shipping[] lists every method the address offers, each with its price:
1
2
3
4
5
6
7
8
9
10
11
12
{
"shippingType": "dropship",
"shippingPriority": "dropship_lowest_cost",
"options": {
"shipping": [
{ "id": "dropship_lowest_cost", "type": "dropship", "priority": "dropship_lowest_cost", "label": "Economy", "price": { "value": "7.95", "code": "USD" } },
{ "id": "dropship_expedited", "type": "dropship", "priority": "dropship_expedited", "label": "Expedited", "price": { "value": "20.61", "code": "USD" } },
{ "id": "dropship_one_day_standard", "type": "dropship", "priority": "dropship_one_day_standard", "label": "Standard One-Day", "price": { "value": "31.34", "code": "USD" } },
{ "id": "dropship_one_day_priority", "type": "dropship", "priority": "dropship_one_day_priority", "label": "Priority One-Day", "price": { "value": "40.48", "code": "USD" } }
]
}
}
Show your customer the label and price of each entry. To ship with one of them, send its priority as shipping.priority on submit, with the same type. To take the cheapest, leave priority out. Either way, shippingType and shippingPriority on the response tell you what the order is using, and totalPrice.subtotals.shipping.label names it. See Response Bodies.
A few things to expect from the list:
label can name the carrier.options.shipping[], because the choices depend on where the order is going (see calculating with no address).shipping.returnAddress is optional. A drop-ship label already carries the address on your WHCC account as its return address, so send this only to print a different one on an order, such as a studio you ship for or your own warehouse. There's no setting to turn on: when the field is present, WHCC uses it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"type": "dropship",
"priority": "dropship_lowest_cost",
"address": {
"name": "Jordan Rivera",
"addr1": "100 Main Street",
"city": "Minneapolis",
"state": "MN",
"zip": "55401",
"country": "US"
},
"returnAddress": {
"name": "Example Photo Co",
"addr1": "250 Studio Lane",
"addr2": "Suite 4",
"city": "Eagan",
"state": "MN",
"zip": "55121",
"country": "US",
"phone": "5555550123"
}
}
The rules:
name, addr1, city, state, zip and country are required once you send the object. addr2 and phone are optional.country must be US. WHCC prints return addresses for US senders only. If you ship from outside the US, leave returnAddress out and the label carries your account address.phone, if sent, is exactly 10 digits, with no spaces or punctuation: 5555550123, not 555-555-0123.attn or email, returns 400 naming the key. This is stricter than shipping.address, and it is checked as soon as you send it: a bad returnAddress is a validation 400 on submit and on calculate alike, not an incomplete-address result on calculate.shipping.type set to studio, with a priority that starts with studio_, or with account shipping settings that resolve the order to studio, the request returns 400 with an invalidParams[] entry named shipping.returnAddress. Its reason reads shipping.returnAddress is not allowed with studio shipping. Return addresses apply to drop-ship orders only; remove it, or use shipping settings that resolve to drop-ship. A studio_* priority counts as studio even when type is dropship.Calculate accepts the same shipping object, so you can check a returnAddress before you submit. It returns the same 400s, and its response doesn't echo the address. The submit response and GET /v1/commerce/submissions/{submissionId} return it as returnAddress, exactly as you sent it, and leave the key out when you sent none (see Response Bodies). With no returnAddress, the label carries your account address, which GET /account returns (see Reading your account).
Coming from the Order Submit API? This is its ShipFromAddress with FromAddressValue set to 2. There is no FromAddressValue field to send here. See Order Request Schema and the shipFromAddress field of the Editor API order export.
Calculate gives you today's price for the items and address you send, but it doesn't hold that price. WHCC prices the order again when it places it, and that's the amount you're billed. For most US addresses the two match.
Some destinations price differently, and nothing in the response marks a value as provisional. Response Bodies covers how sales tax and destination fees appear.
Calculate and submit check that the required fields are present. They don't verify that the address exists, that the zip belongs to the state, or that phone and email are well formed. Validate the address in your own checkout before you send it.
country left out or empty is treated as US, with no invalidParams[] entry for it. The US rules for state and zip then apply. A code that isn't a real country is not rejected: it is priced as an international destination.country and state are accepted in either case and returned as you sent them. Send codes, not names: a name such as United States or Minnesota returns 400.name, addr1, addr2 or city and doesn't screen their characters: markup, emoji and control characters come back as sent. Labels print from the Windows-1252 character set (see Metadata & Reference), so send plain text that fits on a label.state or zip WHCC can't place leaves sales tax as "TBD". A "TBD" response doesn't carry the submission.pricing.total_excludes_tax guidance note.addr1 is offered a single dropship method, and no studio method.If you send both type and priority, make them agree. A priority belongs to the type in its name: dropship_* to dropship, studio_* to studio. A pair that disagrees is rejected with a 400 whose invalidParams[] names both shipping.type and shipping.priority. A value that isn't shaped like any priority is rejected the same way, naming shipping.priority.
A well-formed priority that the destination doesn't offer (one from a Canadian address sent with a US address, say) is also rejected once you've sent an address: 400 with code: "submission.shipping_priority_unsupported", and the reason lists the priorities of the same shipping type that are available, if there are any. The list can be missing even when other priorities are on offer. Calculate without an address never fails this check. To avoid it, ask calculate what the address offers and pick from that.
See the submission shape this produces on Response Bodies, or how to carry your own order identifiers alongside it on Metadata & Reference.