Skip to main content
On this page▾

A custom shop or ERP is one where there is no ready plug-in, so your developer connects the Configurator to the cart. The rule behind everything here is one sentence: a price the browser sent must never become a cart price. Your server verifies it with CutOptim first.

CutOptim collects no payment and hosts no shop; the cart, checkout and payment stay yours. There is no SDK yet. The Configurator API reference lists every route, error code and limit, with an OpenAPI 3.1 document; this page, the orders page and the reference code walk through the integration step by step.

Two keys

  • The publishable key sits in your page for the embed. It can only do what a shopper does, and only from the domains you listed for it.
  • The secret key is for your server and is never put in a page. It is sent as Authorization: Bearer <key> to the service, by default https://cfg.cutoptim.com. Always send Content-Type: application/json on a POST.

Step 1: verify the quote before the cart

When the customer orders, your page receives a cutoptim:order event with a quote token. Send the token to your server, and from there:

curl -X POST https://cfg.cutoptim.com/cfg/v1/quote/verify \
  -H "Authorization: Bearer $CFG_API_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"quoteToken":"<token from the page>"}'

The answer is 200 with {"valid": true, "redeemed": false, "claims": {...}} or {"valid": false, "reason": "..."}. A refusal is still a 200, so read valid. Treat a timeout, a 401, a 500 or an unreadable body as not verified and refuse the line. Then compare the claims with your cart line: the tenant is yours, the currency is the cart’s, the expiry is in the future, and the quote hash equals the hash of the quote your page displayed. The reference code includes the function that computes that hash.

A local check of the token’s shape, tenant and expiry is cheaper but cannot prove the signature, because the signing key is not handed out. Use it as a pre-check only.

Step 2: check the order

Verifying the quote shows the price promise is genuine. It does not show which order the browser means. Before you store or fulfil by an order id, fetch it on your server with GET /cfg/v1/orders/{id} and your secret key. It returns the plan hash, quote hash, status, currency and the three totals in minor units, and no personal data. Compare them with what you verified.

Step 3: receive the webhook

Configure a webhook as described on the orders page. Your receiver:

  1. reads the raw body before parsing it;
  2. reads the CutOptim-Signature header, t=<unix seconds>,v1=<hex> (there may be two v1 values while a secret rotates);
  3. recomputes HMAC-SHA256(secret, "<t>.<raw body>"), compares in constant time, and refuses a timestamp more than about five minutes away;
  4. claims the event id from CutOptim-Event-Id before doing any work, and ignores an id it has already handled;
  5. ignores event types it does not know, and answers 2xx, so the sender does not retry for nothing.

You get the receiver secret with POST /cfg/v1/admin/webhooks/{id}/secret and your secret key. Keep secrets in your environment, never in a page, a repository or a log.

Reference code

Two small, dependency-free examples show all three steps. They are code to read and copy, not a hosted service:

Their secrets are placeholders. The in-memory duplicate store in the examples is a stand-in: in production, keep handled event ids in your database and claim an id in the same transaction that records the order.

The same steps, with the exact requests and answers, are in the reference: Custom shop or ERP.

Rotating keys

A key or webhook secret can be rotated with an overlap, so the old one keeps working for a set time while you deploy the new one. During a webhook rotation a delivery carries two v1 signatures for seven days, and accepting any one of them lets you switch without downtime. Console buttons for overlap rotation are not built yet; the console can create and revoke keys.

Other ways to receive orders

For WooCommerce use the plug-in. If you only need cutting plans inside your own software, with no embedded customer screen, that is the Engine API.

FAQ

Do I need a plug-in to use the Configurator with my own shop?
No. The Configurator is embedded with a script and an element, and your server does three things: verify the quote before the cart, check the order it belongs to, and verify the signed webhook. This page describes them and links reference code in Node and PHP. WooCommerce has a ready plug-in; no other platform does.
How does my server check a price?
It sends the quote token to POST /cfg/v1/quote/verify on the Configurator service with your secret key. The answer is valid or not, and whether it was already redeemed. It then compares the claims in the token with its own cart line: tenant, currency, expiry and the quote hash. A check done only locally cannot prove the signature, so never decide a price on it.
Does verifying a quote use it up?
No. The verification is read-only. Only placing the order consumes the quote, once. A valid quote can come back as already redeemed, so check both fields.
How do I know an order id from the browser is the order I verified?
Look it up on your server: GET /cfg/v1/orders/{id} with the secret key returns the plan hash, quote hash, status and totals of that order, never personal data. Compare them with the verified quote. Without this, a cheap verified quote could be sent next to the id of a different order.
Is there an SDK or an OpenAPI document?
There is no SDK and no hosted adapter, but there is an API reference: every route, error code and limit, with an OpenAPI 3.1 document at /configurator/openapi.json that a client generator can read. The reference files are small, dependency-free examples in Node and PHP that you read and copy. Python, Java and C# are not covered; the signature is a plain HMAC-SHA256, so any language can do it.
Which Configurator events can I receive?
order.created and order.status_changed. Other event names the configuration accepts, such as quote or project events, are never sent. Delivery is at least once, so keep a record of the event ids you have handled.

Last updated: October 19, 2026