Developer documentation

Engine SDK

Drop @aeonzap/engine into your existing Node or PHP stack. Reuse the catalog, cart, checkout, and event bus.

When to use the engine SDK

Use the engine SDK when you have an existing app — a custom storefront, an ERP, an in-store POS — and want Aeonzap to handle catalog, inventory, cart math, taxes, and order persistence without sending the customer to a hosted storefront.

Node integration

import { createEngine } from '@aeonzap/engine';

const engine = createEngine({
  storeId: process.env.AEONZAP_STORE_ID!,
  token: process.env.AEONZAP_TOKEN!,
  cache: 'memory',
});

const cart = await engine.cart.create({ currency: 'INR' });
await engine.cart.addLine(cart.id, { variantId: 'var_19', quantity: 2 });
const totals = await engine.cart.totals(cart.id);

engine.events.on('order.paid', async (evt) => {
  await syncToErp(evt.order);
});

PHP integration

<?php
use Aeonzap\Engine\Engine;

$engine = new Engine([
  'store_id' => getenv('AEONZAP_STORE_ID'),
  'token' => getenv('AEONZAP_TOKEN'),
]);

$cart = $engine->cart->create(['currency' => 'INR']);
$engine->cart->addLine($cart['id'], ['variant_id' => 'var_19', 'quantity' => 2]);
$totals = $engine->cart->totals($cart['id']);

$engine->events->on('order.paid', function ($evt) {
  // sync to ERP
});

Event bus

The engine exposes the same events as the webhook stream, but in-process. Handlers run synchronously inside your worker and can mutate the outgoing response. Throw an EngineHaltError to short-circuit the pipeline.

  • cart.line_added — fires on every addLine; mutate to apply discounts
  • cart.totals_computed — last hook before we return totals to the client
  • order.creating — fires inside the transaction; reject to block the order
  • order.paid — fires after payment; safe place to call out to other systems

Custom adapters

Adapters let you replace a single subsystem — payments, shipping, taxes, inventory — without forking the engine. Implement the adapter interface and register it.

engine.adapters.register('payments', {
  async authorize(order) {
    const res = await myGateway.charge({ amount: order.total, ref: order.id });
    return { ok: res.ok, transactionId: res.id };
  },
  async refund(transactionId, amount) {
    await myGateway.refund(transactionId, amount);
  },
});

Caching

cache: "memory" is fine for a single-process app. For multi-node deployments use cache: { kind: "redis", url } so cart state and price lookups stay consistent. The SDK never caches order or customer data — those always go to the API.

Local development

Run npx @aeonzap/engine dev to start a local proxy that mirrors your store data. Calls hit the proxy first, fall through to the real API, and are cached for 60 seconds. This lets you iterate offline without burning rate limit.