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 option sets using local workspace file synchronization.

Workflow Sequence for Pricing Models

When constructing pricing models and wiring up a purchaser, developers and AI coding agents should author local workspace files managed via CLI DevServer synchronization (aircada dev). See Dataset File Format (.airpds) and Pricing Model Manifest Format (.airpm) for detailed JSON specifications:

1. Author Datasets (datasets/*.airpds): Write .airpds JSON files defining schema columns (STRING, FLOAT, INTEGER, COLOR, MEDIA_ITEM) and dataset row items.

2. Author Option & Pricing Models (option-models/*.airpm): Write stripped .airpm manifests specifying typeVersion: 1.02, basePrice, optionSets, and syncingSettings.

3. Run CLI DevServer (aircada dev): Synchronize local workspace files live with Aircada Studio and Engine using atomic disk write protections (.tmp -> fs.rename).

4. Runtime Inspection: Use MCP inspection tools (inspect_studio_structure) to query the live session and verify that option models and datasets are registered.

1. File Synchronization & Local Editing

Local .airpds and .airpm files serve as the authoritative single source of truth for datasets and pricing rules. The CLI DevServer automatically detects file edits, validates schemas, and broadcasts updates over WebSockets to Studio in real time.

2. Synchronization and CLI Codegen

After dataset and pricing model files are synchronized with Engine, the Aircada CLI automatically updates the options.generated.ts file in the project folder structure. At this stage, your newly created pricing models and Option Registries become completely visible and accessible in code.