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 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 instead: new integrations use the WHCC API, which is a separate flow.
Hosts
https://
Sandbox. Build and test here first. Sandbox and production keys are separate.
https://
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 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.
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.
1
Authorization: Bearer <YOUR_API_KEY>
Keep the key out of browsers, logs and source control. API Key Security covers where to store it and how to rotate it.
This flow needs a key granted both apikey and apikey:oas.
apikey
Ordinary partner access: event subscriptions, the fulfillment routes, and GET /discovery.
apikey:oas
The legacy routes below: the product reads, POST /editors and export, plus the create and confirm routes on Submit orders with an API key.
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 — check the host and the key.
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 documents the response. Call it first: the legacy routes should appear under operations.
1
2
curl https://apis-stage.whcc.com/api/v1/discovery \
-H "Authorization: Bearer <YOUR_API_KEY>"
Each row names a route, the scope it requires, and the step that calls it.
GET /discovery
apikey · Checking your key
GET /products
apikey:oas · 1. Products
GET /products/
apikey:oas · 1. Products
GET /products/
apikey:oas · 1. Products
GET /designs
2. Designs · GZIP required · scope: see step 2
GET /designs/
2. Designs · GZIP required · scope: see step 2
POST /editors
apikey:oas · 3. Editor
PUT /oas/
apikey:oas · 4. Export
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.
1
2
3
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 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, 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.
Products that take a design — cards, ornaments and designer acrylic blocks — 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 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.
1
2
3
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.
POST /editors takes your user's chosen product and returns an editorId and a URL that opens their editor session. Creating an Editor 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 — 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.
1
2
3
4
5
6
7
8
9
10
11
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.
PUT /oas/editors/export turns one or more finished editors into a priced, order-shaped payload. Export Editors for Ordering documents the request and the response in detail; Ordering is the short version.
1
2
3
4
5
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 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 has the full list.
Submitting the exported order is the Order Submit API's job, on the same key. Submit orders with an API key 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.