Purchaser Plugins Integration

Complete developer guidance on integrating Purchaser Plugins, mapping pricing models via the APEX protocol, and using CLI-generated operators.
Published: 7/10/2026

The Purchaser Plugin operator is designed to coordinate merchant APIs across different platforms like Shopify and WooCommerce.

To function correctly, the purchaser plugin must be configured in the merchant's admin panel on the specific hosting docs.

While details of those platform-specific merchant configurations are explained in separate documentation, this section focuses on aspects involving the SDK and the APEX protocol, guiding developers and agents in working with the systems.

Use the links below to explore the setup workflow and runtime integration templates.

CLI Codegen & Purchaser Operator Usage#

Understanding generated helper files and using PurchaserPluginOperators in runtime custom Operator scripts.

1. Code Generation Details

The Aircada CLI generates helper functions for instantiating PurchaserPluginOperators directly from 'Product Configs'. These configurations are automatically created either from external merchant product configurations or via the backend system for testing pricing models in a sandboxed testing mode.

2. Example: options.generated.ts

Below is an example of the auto-generated registry code mapping Option Models, Product Configs, and Initial states:

typescript
// 🟢 AUTO-GENERATED BY AIRCADA CLI
// This file synchronizes Studio Option Models with the SDK Store.

import { PurchaserPluginOperator } from "@aircada/spec";

export const OptionsRegistry = {
  WATERBOTTLE: {
    id: "EDSXd7zWKx3w4odv",
    storeRoot: "options.waterBottle",
    sets: {
      COLOR: {
        id: "L3GHmSwZamxJasGp",
        storeKey: "color",
        storePath: "options.waterBottle.color",
        datasetId: "oyi9wys72xe",
        rowType: "WaterBottleColorsRow",
        semantics: { price: "price", label: "name" }
      }
}
  }
} as const;

export const ProductConfigs = {
  WATERBOTTLE_TEST: {
    id: "TEST_EDSXd7zWKx3w4odv",
    name: "WaterBottle (TEST)",
    configUrl: "TEST_EDSXd7zWKx3w4odv",
    optionModelId: "EDSXd7zWKx3w4odv"
  }
} as const;

/**
 * Initial state for the AirStore namespaced by Option Model.
 */
export const InitialOptionState = {
  "waterBottle": {
    "color": {
      "id": "row_red",
      "color": "#ff0000",
      "label": "Red",
      "price": 10
    }
  }
} as const;

export type AppOptionStore = typeof InitialOptionState;

export const ProductPurchasers = {
  WATERBOTTLE_TEST: async (air: any) => {
    return air.ecommerce.createPurchaserPlugin(
      ProductConfigs.WATERBOTTLE_TEST.configUrl,
      OptionsRegistry.WATERBOTTLE.storeRoot,
      InitialOptionState.waterBottle
    ) as PurchaserPluginOperator;
  }
} as const;

3. Using the Purchaser Plugin in a Custom Operator

Once generated, you can instantiate the purchaser inside a custom Operator's @Setup() lifecycle step, subscribe to dynamic price calculations, and trigger transaction submissions on input events. Here is a complete usage script:

typescript
import {
    Context, Setup, Input,
    PurchaserPluginOperator,
    AircadaContext,
    System
} from "@aircada/spec";
import { ProductPurchasers } from "../registry/options.generated";

@System({
    name: "Pricing Manager",
    type: "pricing_manager"
})
export class PricingManagerOperator {

    @Context()
    air!: AircadaContext;

    private purchaser!: PurchaserPluginOperator;

    @Setup()
    async setup() {
        console.log("[PricingManager] Creating and initializing runtime Purchaser...");
        this.purchaser = await ProductPurchasers.WATERBOTTLE_TEST(this.air);

        if (!this.purchaser) {
            console.error("[PricingManager] Failed to create runtime Purchaser operator.");
            return;
        }

        this.purchaser.price.addListener((newPrice: string) => {
            console.log(`[PricingManager] Purchaser computed new price: ${newPrice}`);
            const numericPrice = Number(newPrice);
            if (!isNaN(numericPrice)) {
                this.air.store.patchByPath("currentPrice", numericPrice);
            }
        });
    }

    @Input({ onEvent: "SUBMIT_PURCHASE" })
    onSubmitPurchase() {
        console.log("[PricingManager] Received SUBMIT_PURCHASE event. Forwarding to PurchaserPluginOperator.");
        this.purchaser.submit();
    }
}

Pricing Models and Purchaser Setup Workflow#

A step-by-step workflow sequence for configuring option models, datasets, and sets to synchronize pricing.

Workflow Sequence for Pricing Models

When constructing pricing models and wiring up a purchaser, it is recommended (though not strictly enforced by the compiler) to perform the following actions in the specified order. You can refer to Basic APEX Transaction Examples or Option Model & Set APEX Payloads for examples of these request payloads:

1. Create Datasets: Define the layout schema for option variants (e.g. colors, materials, dimensions).

2. Create Dataset Rows: Populate the dataset with specific choices, identifying cost offsets and details.

3. Create Option Models: Set up the top-level option model configuration wrapper in the Studio context.

4. Create Option Sets: Wire up and link the datasets/rows to the respective option models.

1. Using the APEX Protocol & Sensing

To establish these structures programmatically, the agent should dispatch transactions via the APEX Transactions domain. Throughout this sequence, you should use the APEX Inspection Tools (such as the inspect_studio_structure tool) to query the live 3D session, validate that datasets or models are correctly registered, and check that transaction results were successfully applied.

2. Synchronization and CLI Codegen

After the APEX protocol configuration transactions have finished executing, the Aircada CLI will automatically synchronize the state. The developer or agent can expect the CLI to auto-update the options.generated.ts file in the project folder structure. At this stage, your newly created pricing models and Option Registries will be completely visible and accessible in code.