> Part of [WHCC Developer Documentation](https://www.whcc.com/developer/llms.txt)

# Submission Lifecycle

Version 1.5 &middot; Updated 2026-10-08

Submitting is asynchronous. `POST /v1/commerce/submissions` answers right away with `202 Accepted`, then WHCC places your order in the background. Look up the submission to see what happened, then follow each order's fulfillment link for production and shipping.

## What `202` means

- **`202 Accepted`**: WHCC has checked your submission and queued it. The body is the full [submission](https://www.whcc.com/developer/docs/api/responses/#submission) with `status: "submitting"` and no `orders` key yet, because nothing has reached WHCC's order system. Save the `id` so you can look the submission up later.

## The `Idempotency-Key` header

`Idempotency-Key` is required on every submit call. It is a unique value you choose for the order, and it is how WHCC recognizes a retry. If a timeout or dropped connection makes your client send the same call again, the key keeps the order from being placed twice.

Use your own order ID if you have one. Otherwise generate a UUID (v4) and **save it with the order before you send it**, so a retry reuses the same key. On this route keys don't expire, so never reuse one for a different order. Keep the key short, the length of a UUID or an order ID: a very long header is rejected before it reaches the API.

- **`missing`**: `400`, code `submission.idempotency_key_required`. Add the header and send again. A key that is empty or only whitespace counts as missing. The key is checked after the body, so a request with an invalid body and no key returns the body's `400` first, and only a clean body gets this one. The order is `415` for the wrong `Content-Type`, then `request.invalid_json` for a body that doesn't parse, then body validation, then the missing key.
- **`same key, same body`**: Your original submission comes back, still `202`, and nothing new is placed. It comes back as a snapshot that can lag the submission, so its `status` may already have moved past `submitting`. A replay can show `status: "placed"` while its `guidance[]` still says placement has not been confirmed and its order `status` is behind the one a lookup returns. Read `GET /v1/commerce/submissions/{submissionId}` for the current state and guidance, and don't act on the replay's guidance or order status. Retry this way as often as you need. Changing only `metadata`, or the order of `items[]`, still counts as the same body, and you get the original submission with its original metadata.
- **`same key, different body`**: `409`, code `submission.idempotency_conflict`. That key was already used for a different order, and your first submission stands. Changing `reference` or `instructions` is enough to make it a different body. Use a new key only if this really is a new order. See the [worked `409` example](https://www.whcc.com/developer/docs/api/errors/#example-409).

Calculate is the opposite. It creates nothing, so it takes no `Idempotency-Key`, and sending one is a `400` (`submission.idempotency_key_not_applicable`).

## Receive updates and look up a submission

Order status should come to you, not be fetched on a timer. Create an [event subscription](https://www.whcc.com/developer/docs/api/event-subscriptions/index.html.md) and WHCC posts `order.accepted`, `order.rejected`, `order.shipped` and `order.cancelled` for each order a submission produces. Match them to your checkout by `ConfirmationId`, which is each `orders[]` entry's `confirmationId`. A submission can produce several orders, so expect a set of events, not one.

Order events can't report a submission that failed before any order existed. So read the submission once after it settles, and whenever you need to reconcile, by its saved ID:

```shell
curl https://apis-stage.whcc.com/api/v1/commerce/submissions/<submissionId> \
	-H "Authorization: Bearer <YOUR_API_KEY>"
```

The lookup shows whether WHCC placed every order, some, or none. Use it for reconciliation and for investigating an event that never arrived, and the fulfillment links below when you need an order's detail.

### After placement: fulfillment order detail

The submission's `status` tells you what happened to the request you sent, not the production status of each fulfillment order. Once `orders[]` is available, follow its `actions.fulfillment.url` to `GET /v1/fulfillment/orders`. That request returns a list, because one WHCC order can become several fulfillment orders. Follow a result's `links.self` to `GET /v1/fulfillment/orders/{id}` for its `status`, `statusHistory`, and `shipments`. See [Orders & Fulfillment](https://www.whcc.com/developer/docs/api/fulfillment/index.html.md).

## The seven `status` values

`status` tells you where the submission is in the order lifecycle:

- **`staged`**: WHCC has your submission but hasn't started placing it. No `orders` key yet.
- **`submitting`**: On its way to WHCC's order system. Every fresh `202` response reads `submitting`. No `orders` key yet.
- **`placed`**: Every entry in `orders[]` was placed. Production and shipping may still be under way. If our team resolves a problem by hand, the submission can stay `placed`. Follow each order's `actions.fulfillment` link for current fulfillment details.
- **`shipped`**: Every order in `orders[]` has shipped, and each entry's `shippingInfo` carries the details.
- **`canceled`**: Every order in `orders[]` was canceled. Cancellation is done through the [Orders & Fulfillment](https://www.whcc.com/developer/docs/api/fulfillment/#cancel), or by WHCC customer service. A canceled order's entry reads `order_canceled`. When only some orders are canceled, the submission stays `placed`, so read each entry's `status`.
- **`failed`**: Nothing was placed. Either every entry in `orders[]` failed, in which case read each entry's `failure.code` (see [Errors & Rate Limits](https://www.whcc.com/developer/docs/api/errors/#submission-failure-codes)), or the submission couldn't be sent to WHCC at all and there is no `orders` key. In that case, contact WHCC support with the submission `id`.
- **`partially_failed`**: Some orders in `orders[]` were placed and at least one failed. See below.

> ### Read `partially_failed` carefully
>
> One submission can become several WHCC orders, and they don't all succeed or fail together. `partially_failed` means some of your customer's items are on their way and some aren't, under one submission ID. **Don't treat it as "mostly fine."** Walk every entry in `orders[]`, act on each one that carries a `failure`, and decide whether to resubmit just those items, contact WHCC support, or tell your customer part of their order needs attention. Never resubmit the whole submission. This is the status integrations most often forget to handle, so write your handler before you need it.

## A worked example

```shell
curl -X POST https://apis-stage.whcc.com/api/v1/commerce/submissions \
	-H "Authorization: Bearer <YOUR_API_KEY>" \
	-H "Content-Type: application/json" \
	-H "Idempotency-Key: <YOUR_ORDER_ID>" \
	-d @submission.json
```

`202 Accepted`, trimmed. See [Response Bodies](https://www.whcc.com/developer/docs/api/responses/#submission) for every field:

```json
{
	"id": "<submissionId>",
	"status": "submitting",
	"reference": "PO-90188",
	"createdAt": "2026-09-24T20:50:31.518Z",
	"items": [ { "…": "trimmed" } ],
	"totalPrice": { "value": "91.26", "code": "USD", "…": "trimmed" }
}
```

Retrieve the saved `id` later to reconcile the submission (trimmed):

```json
{
	"id": "<submissionId>",
	"status": "placed",
	"orders": [
		{
			"confirmationId": "<confirmationId>",
			"status": "order_placed",
			"actions": { "fulfillment": { "url": "https://apis-stage.whcc.com/api/v1/fulfillment/orders?sourceConfirmationId=<confirmationId>", "method": "GET" } }
		}
	],
	"…": "trimmed"
}
```

Once the order ships, `status` moves to `shipped` and the entry's `shippingInfo` fills in.

> ### What's Next
>
> See the full submission on [Response Bodies](https://www.whcc.com/developer/docs/api/responses/#submission), or every error code on [Errors & Rate Limits](https://www.whcc.com/developer/docs/api/errors/index.html.md).