Saltar al contenido principal
← Referencia de la API

Inicio rápido

Tres pasos llevan a una tienda de cero a un pedido seguro: incrustar el configurador, verificar el presupuesto en tu servidor antes del carrito y aceptar el webhook firmado. La incrustación hace por ti las llamadas desde la página de la tienda; tu código solo se ocupa del lado del servidor.

URL base https://cfg.cutoptim.com · Versión del contrato v1 · Documento OpenAPI 3.1

Acceso anticipado: la API para comercios está construida y se puede probar en una tienda sandbox; los plugins para plataformas de tienda siguen en desarrollo. CutOptim no cobra ningún pago: el carrito, la caja y el pago se quedan en tu tienda.

Las rutas, los nombres de campo, los códigos de error, los nombres de cabecera y los ejemplos de código se quedan en inglés: son el contrato.

1. Incrusta el configurador

Añade el script y el elemento a la página de producto, con tu clave pública (pk_live_…, o una clave de prueba pk_test_… mientras desarrollas). El origen de la página debe estar entre los orígenes permitidos de la clave. La incrustación llama entonces ella misma a GET /cfg/v1/config/public, POST /cfg/v1/preview, POST /cfg/v1/quote y POST /cfg/v1/order.

Cuando el cliente hace el pedido, el servicio guarda el pedido firmado y el elemento lanza el evento de navegador cutoptim:order con { orderId, order, idempotencyKey }. Trata ese evento como una pista para tu página, nunca como prueba de un precio.

<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="es">
</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. Verifica en tu servidor antes del carrito

Tu servidor envía el token del presupuesto a POST /cfg/v1/quote/verify con la clave secreta. La respuesta es valid más redeemed; un rechazo sigue siendo un 200 con valid: false y un reason. Después busca el pedido que nombró el navegador con GET /cfg/v1/orders/{id} y compara el hash del plan, el hash del presupuesto, la moneda y los totales con el token verificado. Solo entonces crea la línea de carrito, al precio verificado.

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. Recibe el webhook firmado

Publica un endpoint de webhook en la configuración de tu tienda. Cada pedido real envía order.created y cada cambio de estado order.status_changed. Lee el cuerpo en bruto, comprueba la cabecera CutOptim-Signature y guarda el pedido una sola vez por CutOptim-Event-Id. El receptor de abajo es el ejemplo de referencia, sin cambios.

// 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));

Siguiente

Claves, claves de prueba y orígenes: Claves y autenticación. El receptor completo, la versión en PHP y el calendario de reintentos: Webhooks. Una versión paso a paso para tu propia plataforma: Tienda propia o ERP.

Aquí no hay un botón «probar» a propósito: la clave secreta pertenece a tu servidor, nunca a un navegador. La tienda demo muestra la incrustación y el traspaso del pedido funcionando de principio a fin.

Información legalCondiciones del configurador (EN) ·Contrato de encargo de tratamiento (EN) ·Aviso de privacidad para compradores ·Licencias de terceros (EN)