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 defaulthttps://cfg.cutoptim.com. Always sendContent-Type: application/jsonon 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:
- reads the raw body before parsing it;
- reads the
CutOptim-Signatureheader,t=<unix seconds>,v1=<hex>(there may be twov1values while a secret rotates); - recomputes
HMAC-SHA256(secret, "<t>.<raw body>"), compares in constant time, and refuses a timestamp more than about five minutes away; - claims the event id from
CutOptim-Event-Idbefore doing any work, and ignores an id it has already handled; - 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:
- Node 18 or later: cutoptim-verify.mjs and example-server.mjs.
- PHP 7.4 or later: CutOptimVerify.php and example-webhook.php.
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.