Aller au contenu principal
← Référence de l’API

Démarrage rapide

Trois étapes mènent une boutique de zéro à une commande sûre : intégrer le configurateur, vérifier le devis sur votre serveur avant le panier, et accepter le webhook signé. L’intégration effectue pour vous les appels côté page de boutique ; votre code ne gère que le côté serveur.

URL de base https://cfg.cutoptim.com · Version du contrat v1 · Document OpenAPI 3.1

Accès anticipé : l’API marchand est développée et peut être essayée dans une boutique bac à sable ; les plug-ins pour les plateformes de boutique sont encore en développement. CutOptim n’encaisse aucun paiement : le panier, la commande et le paiement restent dans votre boutique.

Les chemins, noms de champs, codes d’erreur, noms d’en-têtes et exemples de code restent en anglais : ils font partie du contrat.

1. Intégrer le configurateur

Ajoutez le script et l’élément à la page produit, avec votre clé publique (pk_live_…, ou une clé de test pk_test_… pendant le développement). L’origine de la page doit figurer parmi les origines autorisées de la clé. L’intégration appelle ensuite elle-même GET /cfg/v1/config/public, POST /cfg/v1/preview, POST /cfg/v1/quote et POST /cfg/v1/order.

Quand le client commande, le service enregistre la commande signée et l’élément déclenche l’événement navigateur cutoptim:order avec { orderId, order, idempotencyKey }. Considérez cet événement comme une indication pour votre page, jamais comme la preuve d’un prix.

<script type="module" src="https://cfg.cutoptim.com/embed/assets/cutoptim-configurator.js"></script>

<button data-cutoptim-open="#cut">…</button>
<cutoptim-configurator id="cut" mode="modal" key="pk_live_your_publishable_key" lang="fr">
</cutoptim-configurator>

<script>
  document.getElementById('cut').addEventListener('cutoptim:order', (e) => {
    // e.detail = { orderId, order, idempotencyKey } - send it to YOUR server, which verifies it
  });
</script>

2. Vérifier sur votre serveur avant le panier

Votre serveur envoie le jeton de devis à POST /cfg/v1/quote/verify avec la clé secrète. La réponse contient valid et redeemed ; un refus reste un 200 avec valid: false et un reason. Il retrouve ensuite la commande désignée par le navigateur avec GET /cfg/v1/orders/{id} et compare le hash du plan, le hash du devis, la devise et les totaux avec le jeton vérifié. C’est seulement alors qu’il crée la ligne de panier, au prix vérifié.

curl -X POST https://cfg.cutoptim.com/cfg/v1/quote/verify \
  -H "Authorization: Bearer $CUTOPTIM_API_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"quoteToken":"<order.quote.quoteToken>"}'
# {"valid":true,"redeemed":true,"claims":{…},"test":false}

curl https://cfg.cutoptim.com/cfg/v1/orders/<orderId> \
  -H "Authorization: Bearer $CUTOPTIM_API_SECRET"
# {"orderId":"…","status":"received","priced":true,"planHash":"…","quoteHash":"…","totals":{…}}

3. Recevoir le webhook signé

Publiez un endpoint de webhook dans la configuration de votre boutique. Chaque commande réelle envoie order.created, chaque changement de statut order.status_changed. Lisez le corps brut, vérifiez l’en-tête CutOptim-Signature, puis enregistrez la commande une seule fois par CutOptim-Event-Id. Le récepteur ci-dessous est l’exemple de référence, tel quel.

// example-server.mjs - a webhook endpoint on node:http, to read and adapt.   CUTOPTIM_WEBHOOK_SIGNING=whsec_... node example-server.mjs
// (whsec_REPLACE_ME is a placeholder: the real secret comes from the CutOptim admin route.)
import { createServer } from 'node:http';
import { createWebhookReceiver } from './cutoptim-verify.mjs';

const secret = process.env.CUTOPTIM_WEBHOOK_SIGNING;
if (!secret) { console.error('set CUTOPTIM_WEBHOOK_SIGNING (whsec_REPLACE_ME is a placeholder)'); process.exit(1); }

const receive = createWebhookReceiver({
  secrets: [secret],
  async onEvent(event) {
    // event.type === 'order.created'; event.data.order is the signed order document. Store it in YOUR order table here,
    // keyed by event.data.orderId, in the same transaction that records the event id as seen.
    console.log('order.created', event.data.orderId);
  },
});

createServer(async (req, res) => {
  if (req.method !== 'POST') { res.writeHead(405).end(); return; }
  const chunks = []; let size = 0;
  for await (const c of req) { size += c.length; if (size > 2_000_000) { res.writeHead(413).end(); return; } chunks.push(c); }
  const out = await receive({ rawBody: Buffer.concat(chunks), headers: req.headers });   // the RAW bytes, not parsed JSON
  res.writeHead(out.status, { 'Content-Type': 'application/json' }).end(JSON.stringify({ result: out.reason }));
}).listen(Number(process.env.PORT ?? 8787));

Suite

Clés, clés de test et origines : Clés et authentification. Le récepteur complet, la version PHP et le calendrier des nouvelles tentatives : Webhooks. Une version pas à pas pour votre propre plateforme : Boutique sur mesure ou ERP.

Il n’y a volontairement pas de bouton « essayer » ici : la clé secrète appartient à votre serveur, jamais à un navigateur. La boutique de démonstration montre l’intégration et la transmission de la commande de bout en bout.

Mentions légalesConditions du configurateur (EN) ·Accord de traitement des données (EN) ·Notice de confidentialité pour les acheteurs ·Licences tierces (EN)