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

# Use editors with an API key

Version 2.9 &middot; Updated 2026-10-12

This page moves your Editor API (Legacy) integration onto a WHCC API key: read products and designs, open an editor, and export what your users finish. The export gives you an order, which you then submit with the Order Submit API. [Submit orders with an API key](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/order-submit-api/index.html.md) covers that part, along with receiving order events.

> **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) instead: 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 `/products` means `https://apis-stage.whcc.com/api/v1/products`. The [Editor API](https://www.whcc.com/developer/docs/legacy/editor-api/index.html.md) pages show these same paths on the `prospector.dragdrop.design` host, which belongs to the consumer-credential flow. Send API-key requests to the host above. The paths and the bodies are otherwise the same. 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 legacy routes [below](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/editor-api/#surface): the product reads, `POST /editors` and export, plus the create and confirm routes on [Submit orders with an API key](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/order-submit-api/index.html.md).

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/editor-api/#discovery)
- **`GET /products`**: `apikey:oas` &middot; [1. Products](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/editor-api/#products)
- **`GET /products/{productId}`**: `apikey:oas` &middot; [1. Products](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/editor-api/#products)
- **`GET /products/{productId}/attributes`**: `apikey:oas` &middot; [1. Products](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/editor-api/#products)
- **`GET /designs`**: [2. Designs](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/editor-api/#designs) &middot; GZIP required &middot; scope: see step 2
- **`GET /designs/{designId}`**: [2. Designs](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/editor-api/#designs) &middot; GZIP required &middot; scope: see step 2
- **`POST /editors`**: `apikey:oas` &middot; [3. Editor](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/editor-api/#editors)
- **`PUT /oas/editors/export`**: `apikey:oas` &middot; [4. Export](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/editor-api/#export)

## Step 1: Read the products

`GET /products` returns the full list of products your credentials can order, and `GET /products/{productId}` returns one product. `GET /products/{productId}/attributes` returns that product's attribute categories and order attributes.

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

The response shape is unchanged. [Products](https://www.whcc.com/developer/docs/legacy/editor-api/products/index.html.md) documents `GET /products`, including `editorCompatibility`, which tells you which editor a product opens in. The single-product and attributes reads return the same product shape; neither has its own reference page yet.

> These are the Editor API's product routes, kept for this flow. The same key also reads the WHCC API's catalog at [`/catalog/products`](https://www.whcc.com/developer/docs/quick-start/#step-1), and you may prefer it for browsing what you can order. The two return different shapes, and the editor and ordering steps below are documented against the product fields these routes return.

## Step 2: Read designs, for designed products

Products that take a design &mdash; cards, ornaments and designer acrylic blocks &mdash; need a `designId` as well as a `productId` when you create the editor. `GET /designs` lists designs and `GET /designs/{designId}` returns one. Pass the product ids you want designs for in `productIds`: with none, the call returns 5x7 flat card designs only. [Designs](https://www.whcc.com/developer/docs/legacy/editor-api/designs/index.html.md) documents both calls.

**GZIP compression is mandatory on both routes.** Send `Accept-Encoding: gzip` on every request to `GET /designs` and `GET /designs/{designId}` (with curl, pass `--compressed`). Without it, the response is too large for some clients to receive.

```shell
curl --compressed "https://apis-stage.whcc.com/api/v1/designs?productIds=<PRODUCT_ID_1>,<PRODUCT_ID_2>" \
	-H "Authorization: Bearer <YOUR_API_KEY>" \
	-H "Accept: application/json"
```

> **Designs apply only to some products** such as cards, ornaments, and designer acrylic blocks. Other products, including prints, wall art, albums, and books, do not have designs. For products that do not have designs, you will create the editor with a `productId` alone and omit `designId` entirely. Including a `designId` with a product that does not support designs returns an error.

## Step 3: Create an editor

`POST /editors` takes your user's chosen product and returns an `editorId` and a URL that opens their editor session. [Creating an Editor](https://www.whcc.com/developer/docs/legacy/editor-api/create-editor/index.html.md) documents the payload in full, including the per-editor-type examples and the `redirects` you send your user back through.

> **Leave `userId` out.** On a consumer credential, `userId` had to match the `accountId` claim you minted the access token with. An API key resolves to one account on its own, so the field is optional and falls back to that account. If you do send it, it must be exactly the account the key resolves to &mdash; any other value is refused with `400`*API-key requests cannot specify a different userId*, and an empty string is refused too. Sending the identifier your old integration sent is the most likely cause of that refusal.

```shell
curl https://apis-stage.whcc.com/api/v1/editors \
	-H "Authorization: Bearer <YOUR_API_KEY>" \
	-H "Accept: application/json" \
	-H "Content-Type: application/json" \
	-d '{
			"productId": "uLSWZLZzEWY5KWr9z",
			"redirects": {
				"complete": { "text": "Checkout", "url": "https://yourdomain.com/return?editor=%EDITOR_ID%" },
				"cancel": { "text": "Cancel", "url": "https://yourdomain.com/cancel" }
			}
		}'
```

Redirect your user to the returned URL. They come back to your `complete` URL when they finish.

## Step 4: Export the finished editors

`PUT /oas/editors/export` turns one or more finished editors into a priced, order-shaped payload. [Export Editors for Ordering](https://www.whcc.com/developer/docs/legacy/editor-api/order-export/index.html.md) documents the request and the response in detail; [Ordering](https://www.whcc.com/developer/docs/legacy/editor-api/ordering/#export_editors) is the short version.

```shell
curl -X PUT https://apis-stage.whcc.com/api/v1/oas/editors/export \
	-H "Authorization: Bearer <YOUR_API_KEY>" \
	-H "Accept: application/json" \
	-H "Content-Type: application/json" \
	-d '{"editors": [{ "editorId": "sampleEditorId" }]}'
```

The response carries an `order` object. Fill in the fields the export left `null`, and that object is the body you submit next. [Ordering](https://www.whcc.com/developer/docs/legacy/editor-api/ordering/#create_order) shows a complete body.

Export shares the ordering routes' error contract: almost every refusal, including an editor that doesn't exist, arrives as `400`, so read the message rather than branching on the status. [What a refusal looks like](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/order-submit-api/#oas-errors) has the full list.

## Next: submit the order

Submitting the exported order is the Order Submit API's job, on the same key. [Submit orders with an API key](https://www.whcc.com/developer/docs/legacy/api-key-auth-migration/order-submit-api/index.html.md) walks through it: create the order with the `order` object from step 4, confirm it, and set up an event subscription to receive order events.