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

# Submit orders with an API key

Version 1.0 &middot; Updated 2026-10-12

This page moves order submission onto a WHCC API key: create the order, confirm it, and receive order events through an event subscription. Use it on its own if you build OrderImport bodies yourself, or as the second half of [Use editors with an API key](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/editor-api/index.html.md), submitting the order an editor export gives you. Your order body doesn't change. The routes you send it to and the way you authenticate do.

> **This page is for an existing integration being moved onto an API key.** If you are building something new, start at the [Quick Start](https://www.whcc.com/developer/docs/quick-start/index.html.md): new integrations use the [WHCC API](https://www.whcc.com/developer/docs/api/index.html.md), which is a separate flow.

> **Hosts**
>
> - **`https://apis-stage.whcc.com/api/v1`**: Sandbox. Build and test here first. Sandbox and production keys are separate.
> - **`https://apis.whcc.com/api/v1`**: Production. **A confirmed order here is a real, billable order.**
>
> Every path on this page is relative to that base, so `/oas/orders/create` means `https://apis-stage.whcc.com/api/v1/oas/orders/create`. Send API-key requests to the host above, not to the host your consumer-credential integration calls. The examples show the sandbox host and run as written with a sandbox key. On production, only the host and the key change.

## The credential

Send the API key as a bearer token on every request. There is no token exchange, no access-token call (`/auth/access-token` on the Editor API, `/api/AccessToken` on the Order Submit API), and no token expiry to manage.

```plaintext
Authorization: Bearer <YOUR_API_KEY>
```

Keep the key out of browsers, logs and source control. [API Key Security](https://www.whcc.com/developer/docs/api/api-key-security/index.html.md) covers where to store it and how to rotate it.

### Your key carries two scopes

This flow needs a key granted **both**`apikey` and `apikey:oas`.

- **`apikey`**: Ordinary partner access: [event subscriptions](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/order-submit-api/#webhooks), the [fulfillment routes](https://www.whcc.com/developer/docs/api/fulfillment/index.html.md), and `GET /discovery`.
- **`apikey:oas`**: The two ordering routes [below](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/order-submit-api/#surface): create and confirm.

A request whose key doesn't carry a scope the route requires is refused with `403`, with no `code` field to branch on. A one-field `{"message":"Forbidden"}` or `{"message":"Unauthorized"}` body comes from the gateway, before the request reached the service &mdash; check the host and the key.

### Checking what your key reaches

`GET /discovery` lists the operations the key you present can call, with the scope each one requires, and returns the key's own scopes in `grantedScopes`. [Discover routes for your key](https://www.whcc.com/developer/docs/api/#discovery) documents the response. Call it first: the legacy routes should appear under `operations`.

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

## What this flow calls

Each row names a route, the scope it requires, and the step that calls it.

- **`GET /discovery`**: `apikey` &middot; [Checking your key](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/order-submit-api/#discovery)
- **`POST /oas/orders/create`**: `apikey:oas` &middot; [1. Create](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/order-submit-api/#create-order)
- **`POST /oas/orders/{confirmationId}/confirm`**: `apikey:oas` &middot; [2. Confirm](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/order-submit-api/#confirm)
- **`POST /fulfillment/event-subscriptions`**: `apikey` &middot; [3. Events](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/order-submit-api/#webhooks)
- **`POST /fulfillment/event-subscriptions/{id}/test`**: `apikey` &middot; [3. Events](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/order-submit-api/#first-subscription)
- **`POST /fulfillment/event-subscriptions/{id}/enable`**: `apikey` &middot; [3. Events](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/order-submit-api/#first-subscription)

The three event-subscription rows are the ones this walkthrough calls. The resource has more &mdash; list, read, replace, disable, delete and the event-type catalogue &mdash; and all of them take `apikey`. [Event Subscriptions](https://www.whcc.com/developer/docs/api/event-subscriptions/index.html.md) is the full list.

### Replacing your current calls

The Order Submit API (Legacy) routes don't accept an API key. Replace each call you make today with its API key equivalent.

| Legacy endpoint | With an API key |
| --- | --- |
| `POST /api/OrderImport` | `POST /oas/orders/create` |
| `POST /api/OrderImport/Submit/{ConfirmationID}` | `POST /oas/orders/{confirmationId}/confirm` |
| `POST /api/callback/create` | An event subscription |
| `GET /api/AccessToken` | Not needed. Send the API key as the bearer token. |

## Step 1: Create the order

`POST /oas/orders/create` takes the OrderImport body you already build and returns a `ConfirmationID`. The schema is unchanged and documented field by field under [Order Import](https://www.whcc.com/developer/docs/legacy/order-submit-api/order-import/index.html.md). You don't call the Order Submit API's own import and submit routes on an API key.

```shell
curl https://apis-stage.whcc.com/api/v1/oas/orders/create \
	-H "Authorization: Bearer <YOUR_API_KEY>" \
	-H "Accept: application/json" \
	-H "Content-Type: application/json" \
	-d @order.json
```

`order.json` is either the OrderImport body you send today, or the `order` object from an [editor export](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/editor-api/#export) with the fields it left `null` filled in. The order is attributed to the account your key resolves to. Nothing in the body changes that.

## Step 2: Confirm the order

An order is not produced until it is confirmed. `POST /oas/orders/{confirmationId}/confirm` takes no body.

```shell
curl -X POST https://apis-stage.whcc.com/api/v1/oas/orders/a3ff9b4a-3112-4101-88ab-6ba025fd7600/confirm \
	-H "Authorization: Bearer <YOUR_API_KEY>"
```

The response fields are the Order Submit API's, documented under [Order Submit](https://www.whcc.com/developer/docs/legacy/order-submit-api/order-submit/index.html.md).

### What a refusal on these two routes looks like

The two ordering routes share an error contract that is narrower than the rest of this API:

- **`400`**: Almost everything. A malformed body, a rejected field, an editor that doesn't exist, and an upstream failure all arrive as `400`. Read the message rather than branching on the status.
- **`403`**: Either your key doesn't carry `apikey:oas`, or the request points at an account that isn't yours. These are passed through rather than flattened, so a `403` here is always one of those two.
- **`500`**: Something is wrong with the key itself rather than with your request. Retrying the same call won't help. Contact WHCC support.

## Step 3: Receive order events

With an API key, order events arrive through an **event subscription**. You create it yourself through the WHCC API, and it receives events for every order on your account.

[Event Subscriptions](https://www.whcc.com/developer/docs/api/event-subscriptions/index.html.md) documents every route and field. This section covers what you need to make the switch.

The Editor API's `POST /oas/webhooks/create` and `POST /oas/webhooks/verify` don't accept an API key. Use an event subscription instead.

### Your first subscription

```shell
curl https://apis-stage.whcc.com/api/v1/fulfillment/event-subscriptions \
	-H "Authorization: Bearer <YOUR_API_KEY>" \
	-H "Content-Type: application/json" \
	-H "Idempotency-Key: $(uuidgen)" \
	-d '{
			"destination": {
				"type": "webhook",
				"callbackUri": "https://path.to.your/webhook/endpoint"
			},
			"eventTypes": ["order.accepted", "order.rejected", "order.shipped"],
			"description": "Production endpoint"
		}'
```

Store `signingSecret` from the `201`, deploy your handler, [send a test event](https://www.whcc.com/developer/docs/api/event-subscriptions/#test), then [enable](https://www.whcc.com/developer/docs/api/event-subscriptions/#enable) the subscription. [Event Subscriptions](https://www.whcc.com/developer/docs/api/event-subscriptions/index.html.md) explains each of those, and why an `Idempotency-Key` on create is worth sending.

> **Your Order Submit callback keeps working until you remove it.** While both are live, your endpoint receives each event twice, signed with different secrets. If your callback is on V1, the two copies can also be named differently: an accepted order arrives as `order.received` on the callback and `order.accepted` on the subscription. Map the names to one vocabulary before you deduplicate on event type, or every event is processed twice; [Version 1 subscriptions](https://www.whcc.com/developer/docs/api/event-subscriptions/#version-1) lists the mapping. [If you also have an Order Submit callback](https://www.whcc.com/developer/docs/api/event-subscriptions/#duplicate-deliveries) covers deduplicating them, and [Verifying a delivery](https://www.whcc.com/developer/docs/api/event-subscriptions/#verify) covers checking signatures.

> ## What's Next
>
> [Event Subscriptions](https://www.whcc.com/developer/docs/api/event-subscriptions/index.html.md) &mdash; the full reference for step 3.
>
> [Security and Signatures](https://www.whcc.com/developer/docs/legacy/order-submit-api/webhook-security/index.html.md) &mdash; verify `WHCC-Signature` on a delivery.
>
> [Delivery, Retries & Idempotency](https://www.whcc.com/developer/docs/legacy/order-submit-api/webhook-delivery/index.html.md) &mdash; the retry schedule, the response timeout, and why your handler must deduplicate.
>
> [API Key Security](https://www.whcc.com/developer/docs/api/api-key-security/index.html.md) &mdash; where to keep the key.