Apps can extend certain core features of the Swell platform by hooking into native events and endpoints. A Swell App Extension is defined by its ability to respond to core events using functions, or its ability to tap into layers of the platform that serve distinct purposes such as these.

  • Payment gateways: Implement gateways using hooks to vault customer information, charge, and refund payments.
  • Shipping services: Implement shipping services with dynamic carrier-based pricing or custom logic.
  • Tax calculation: Integrate with various tax calculation services.

App extensions are configured in swell.json and referenced by functions and client-side components. This allows you to configure multiple extensions in a single app.

swell.json
{
  "id": "example_app",
  "type": "integration",
  "extensions": [
    {
      "id": "example",
      "type": "payment",
      "name": "My Payment Service"
    }
  ]
}

Extensions can be enabled when an app is installed, which causes their corresponding functions to be triggered by events. Functions can listen to any valid event, however there are specific events most relevant to extensions, as described later in this document.

New extension types and standard events may be introduced over time. The following extension types are currently available.

Each event described here is considered an event hook, which means the event is is only called synchronously during the processing of a record. By default, they are called before the event occurs. This differs from regular model events which are called asynchronously by default.

Response properties listed below follow the corresponding standard Swell models.

Payment extensions are for integrating payment gateways, either with 3rd-party services or custom logic.

Payment events:

  • payment.charge – Triggered before a payment is created. Receives a payment record.
    • Response properties:
      • success – Boolean true or false to indicate whether the payment was successful.
      • transaction_id – String typically from an external payment gateway to identify the payment transaction.
  • payment.refund – Triggered before a payment is refunded. Receives a payment record.
    • Response properties:
      • success – Boolean true or false to indicate whether the refund was successful.
      • transaction_id – String typically from an external payment gateway to identify the refund transaction.
Example
export const config: SwellConfig = {
  extension: "example",
  description: "Charge a credit card",
  model: {
    events: ["payment.charge"]
  },
};

export default async function (req: SwellRequest) {
  // ... perform charge logic

  return {
    success: true,
    transaction_id: '...',
  }
}

Shipping extensions are for integrating shipment rating and price calculation, either with 3rd-party services or custom logic.

Shipping events:

  • order.shipping
    • Response properties:
      • shipment_rating – Shipment rating object containing services and their prices, or errors if any occurred.
Example
export const config: SwellConfig = {
  extension: "example",
  description: "Calculate shipping services",
  model: {
    events: ["order.shipping"]
  },
};

export default async function (req: SwellRequest) {
  // ... perform shipping calculation

  return {
    shipment_rating: {
      services: [
        {
          id: '...',
          price: 9.99
        }
      ],
      errors: [...], // optional
    }
  }
}

Tax extensions are for integrating tax calculation, either with 3rd-party services or custom logic.

Tax events:

  • order.taxes
    • Response properties:
      • taxes – Tax array containing amounts calculated for the order.
      • items.taxes – Optional item-level tax details.
Example
export const config: SwellConfig = {
  extension: "example",
  description: "Calculate taxes",
  model: {
    events: ["order.taxes"]
  },
};

export default async function (req: SwellRequest) {
  // ... perform tax calculation

  return {
    taxes: [
      {
        id: '...',
        amount: 10
      }
    ],
    items: [ // optional
      {
        id: '...',
        taxes: [...]
      }
    ],
  }
}

In addition to server-side functions, an extension can include client-side components that render inside Swell checkout. A payment extension uses a component to display the gateway's payment UI, tokenize the customer's card, and save the result on the cart.

Components are Preact components placed at the root of the app's components/ folder as .jsx or .tsx files, and are pushed to Swell along with the rest of the app configuration. Like functions, a component declares which extension it belongs to in its config:

import { useCallback, useEffect } from "preact/hooks";

export const config: SwellConfig = {
  extension: "card",
  description: "Example gateway client side integration",
};

export default function GatewayComponent({
  settings,
  loadLib,
  registerHandlers,
  createIntent,
  getIntent,
  updateCart,
  onReady,
}: SwellData) {
  const onSubmit = useCallback(
    async (cart: Record<string, any>) => {
      // 1. Create a payment intent (calls the payment.create_intent function)
      // 2. Open the gateway's payment UI to collect and tokenize the card
      // 3. Verify the result (calls the payment.get_intent function)
      // 4. Save the tokenized card on the cart
      return updateCart({ billing: { card: { /* token details */ } } });
    },
    [settings, createIntent, getIntent, updateCart]
  );

  useEffect(() => {
    registerHandlers({ onSubmit });
    loadLib("gateway", "https://example.com/gateway-sdk.js").then(onReady);
  }, [registerHandlers, loadLib, onReady, onSubmit]);

  return null;
}

When a customer selects the extension's payment method in checkout, Swell renders the component and passes it props for interacting with the platform:

  • settings — the app's public setting values.
  • loadLib(id, url) — loads the gateway's browser SDK.
  • registerHandlers({ onSubmit }) — registers the handler called with the current cart when the customer submits payment.
  • createIntent and getIntent — invoke the extension's payment.create_intent and payment.get_intent functions.
  • updateCart(data) — updates the cart, typically saving the tokenized card to the billing details.
  • onReady — signals that the component has finished loading and checkout can proceed.

For complete working examples, see the Build a payment gateway, Build a shipping service, and Build a tax integration tutorials, each with full source code on GitHub.