> ## Documentation Index
> Fetch the complete documentation index at: https://docs.swiftpay.cx/llms.txt
> Use this file to discover all available pages before exploring further.

# Checkout Integration

> Complete guide to integrating SwiftPay checkout

# Checkout Integration Guide

This guide covers everything you need to know about integrating SwiftPay checkout into your application.

## How It Works

<Steps>
  <Step title="Create Session">
    Your server creates a checkout session via the API
  </Step>

  <Step title="Redirect Customer">
    Redirect the customer to the SwiftPay hosted checkout page
  </Step>

  <Step title="Customer Pays">
    Customer enters payment details and completes payment
  </Step>

  <Step title="Handle Result">
    Customer is redirected back to your site; webhook confirms payment
  </Step>
</Steps>

## Creating a Checkout Session

### Basic Example

```javascript theme={null}
const session = await fetch("https://api.swiftpay.cx/api/checkout/sessions", {
   method: "POST",
   headers: {
      Authorization: "Bearer mp_live_your_api_key",
      "Content-Type": "application/json",
   },
   body: JSON.stringify({
      items: [
         {
            name: "Product Name",
            price: 29.99,
            quantity: 1,
            description: "Product description",
            imageUrl: "https://example.com/product.jpg",
         },
      ],
      customer: {
         email: "customer@example.com",
      },
      urls: {
         success: "https://yoursite.com/success?session_id={SESSION_ID}",
         cancel: "https://yoursite.com/cancel",
         failure: "https://yoursite.com/failure",
      },
   }),
});
```

### Request Parameters

<ParamField body="items" type="array" required>
  List of items in the checkout.

  <Expandable title="Item Object">
    <ParamField body="name" type="string" required>
      Product name (max 255 characters)
    </ParamField>

    <ParamField body="price" type="number" required>
      Unit price in dollars (e.g., 29.99)
    </ParamField>

    <ParamField body="quantity" type="integer" required>
      Quantity (minimum 1)
    </ParamField>

    <ParamField body="description" type="string">
      Product description (max 1000 characters)
    </ParamField>

    <ParamField body="imageUrl" type="string">
      URL to product image
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="customer" type="object" required>
  Customer information

  <Expandable title="Customer Object">
    <ParamField body="email" type="string" required>
      Customer email address
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="urls" type="object">
  Redirect URLs after checkout

  <Expandable title="URLs Object">
    <ParamField body="success" type="string">
      Redirect URL after successful payment. Use `{SESSION_ID}` placeholder.
    </ParamField>

    <ParamField body="cancel" type="string">
      Redirect URL if customer cancels
    </ParamField>

    <ParamField body="failure" type="string">
      Redirect URL if payment fails
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="description" type="string">
  Order description for your records
</ParamField>

<ParamField body="askShipping" type="boolean" default="false">
  Whether to collect shipping address
</ParamField>

<ParamField body="metadata" type="array">
  Custom metadata for your records

  <Expandable title="Metadata Item">
    <ParamField body="key" type="string" required>
      Metadata key
    </ParamField>

    <ParamField body="value" type="string | number | boolean" required>
      Metadata value
    </ParamField>
  </Expandable>
</ParamField>

## Checkout URL

After creating a session, redirect the customer to:

```
https://app.swiftpay.cx/checkout/{session_id}
```

<CodeGroup>
  ```javascript React/Next.js theme={null}
  // Using Next.js redirect
  import { redirect } from 'next/navigation';

  export async function createCheckout(formData) {
    const session = await createCheckoutSession(formData);
    redirect(`https://app.swiftpay.cx/checkout/${session.id}`);
  }
  ```

  ```html HTML theme={null}
  <script>
     async function checkout() {
        const response = await fetch("/api/create-checkout", { method: "POST" });
        const { sessionId } = await response.json();
        window.location.href = `https://app.swiftpay.cx/checkout/${sessionId}`;
     }
  </script>

  <button onclick="checkout()">Pay Now</button>
  ```
</CodeGroup>

## Handling the Result

### Success Redirect

When payment succeeds, the customer is redirected to your `success` URL:

```
https://yoursite.com/success?session_id=sess_abc123
```

<Warning>
  Never rely solely on the redirect to confirm payment. Always verify via
  webhook or API.
</Warning>

### Verify Payment Status

```javascript theme={null}
// Verify the payment was successful
const response = await fetch(
   `https://api.swiftpay.cx/api/checkout/sessions/${sessionId}`,
   {
      headers: { Authorization: "Bearer mp_live_your_api_key" },
   },
);

const session = await response.json();

if (session.data.status === "completed") {
   // Payment confirmed - fulfill the order
}
```

## Session Statuses

| Status       | Description                       |
| ------------ | --------------------------------- |
| `pending`    | Session created, awaiting payment |
| `processing` | Payment is being processed        |
| `completed`  | Payment successful                |
| `failed`     | Payment failed                    |
| `expired`    | Session expired (after 24 hours)  |

## Collecting Shipping Address

Set `askShipping: true` to collect the customer's shipping address:

```javascript theme={null}
const session = await createSession({
  items: [...],
  customer: { email: 'customer@example.com' },
  askShipping: true,
  urls: { ... }
});
```

The shipping address will be available in the session data:

```json theme={null}
{
   "shippingAddressLine1": "123 Main St",
   "shippingCity": "San Francisco",
   "shippingState": "CA",
   "shippingPostalCode": "94102",
   "shippingCountry": "US"
}
```

## Using Metadata

Store custom data with the session using metadata:

```javascript theme={null}
const session = await createSession({
  items: [...],
  customer: { email: 'customer@example.com' },
  metadata: [
    { key: 'order_id', value: 'ORD-12345' },
    { key: 'customer_id', value: 'cust_abc123' },
    { key: 'subscription', value: true }
  ],
  urls: { ... }
});
```

Metadata is returned in webhooks and when fetching the session.

## Webhook Integration

For production, always use webhooks to confirm payments:

```javascript theme={null}
// Your webhook endpoint
app.post("/webhooks/swiftpay", async (req, res) => {
   const signature = req.headers["x-webhook-signature"];

   // Verify signature
   if (!verifySignature(req.body, signature, webhookSecret)) {
      return res.status(401).send("Invalid signature");
   }

   const event = req.body;

   if (event.type === "checkout.succeeded") {
      const sessionId = event.payload.sessionId;
      // Fulfill the order
   }

   res.status(200).send("OK");
});
```

See the [Webhooks Guide](/guides/webhooks) for complete webhook setup instructions.

## Best Practices

<CardGroup cols={2}>
  <Card title="Always Use Webhooks" icon="webhook">
    Don't rely on redirects alone. Webhooks ensure you never miss a payment.
  </Card>

  <Card title="Store Session IDs" icon="database">
    Save the session ID with your order for easy reference and debugging.
  </Card>

  <Card title="Use Metadata" icon="tag">
    Link sessions to your internal orders using metadata.
  </Card>

  <Card title="Handle All Statuses" icon="list-check">
    Build UI for pending, completed, and failed states.
  </Card>
</CardGroup>
