# Extensions

Source: https://developers.swell.is/apps/extensions

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.

### Use cases

- **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.

### Structure

App extensions are configured in [swell.json](https://developers.swell.is/apps/swell-json) and referenced by [functions](https://developers.swell.is/apps/functions) and client-side components. This allows you to configure **multiple extensions in a single app**.

**swell.json**

```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.

### Extension types

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](https://developers.swell.is/apps/events), 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](https://developers.swell.is/backend-api/events/event-types) which are called **asynchronously** by default.

Response properties listed below follow the corresponding standard Swell models.

#### Payment

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**

```typescript
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

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**

```typescript
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

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**

```typescript
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: [...]
      }
    ],
  }
}
```

### Components

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:

`components/Gateway.tsx`

```typescript
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](https://developers.swell.is/apps/build-a-payment-gateway-tutorial), [Build a shipping service](https://developers.swell.is/apps/build-a-shipping-service-tutorial), and [Build a tax integration](https://developers.swell.is/apps/build-a-tax-integration-tutorial) tutorials, each with full source code on GitHub.
