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

# Create and manage recurring subscriptions

> Step-by-step guide to creating products, prices, and subscriptions with Borga for recurring billing, including trials, pausing, and cancellation.

Borga subscriptions let you bill customers on a repeating schedule without writing any scheduling logic yourself. You define a product catalogue once — products, then prices — attach them to a subscription for a customer, and Borga takes care of invoice generation, payment collection, and proration when plans change mid-cycle. This guide walks through every step from an empty catalogue to a running subscription.

<Steps>
  <Step title="Create a product">
    A product represents what you are selling — a plan, a service, or a bundle. Create one with a name and an optional description.

    <CodeGroup>
      ```bash curl theme={null}
      curl --request POST \
        --url https://api.borga.is/v1/products \
        --header "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
        --header "X-Merchant-Id: mer_YOUR_MERCHANT_ID" \
        --header "Content-Type: application/json" \
        --data '{
          "name": "Pro Plan",
          "description": "Full access to all Pro features, unlimited projects, and priority support."
        }'
      ```

      ```javascript Node.js theme={null}
      const product = await fetch('https://api.borga.is/v1/products', {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer sk_test_YOUR_SECRET_KEY',
          'X-Merchant-Id': 'mer_YOUR_MERCHANT_ID',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          name: 'Pro Plan',
          description: 'Full access to all Pro features, unlimited projects, and priority support.',
        }),
      }).then(r => r.json());

      console.log(product.id); // pro_01HXYZ…
      ```
    </CodeGroup>

    Save the product `id` — you will reference it when creating a price.
  </Step>

  <Step title="Create a price">
    A price defines how much to charge for the product and how often. Attach it to the product you just created and set the billing interval.

    <CodeGroup>
      ```bash curl theme={null}
      curl --request POST \
        --url https://api.borga.is/v1/prices \
        --header "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
        --header "X-Merchant-Id: mer_YOUR_MERCHANT_ID" \
        --header "Content-Type: application/json" \
        --data '{
          "product": "pro_01HXYZ",
          "currency": "ISK",
          "type": "recurring",
          "unit_amount": 4990,
          "recurring": {
            "interval": "month"
          }
        }'
      ```

      ```javascript Node.js theme={null}
      const price = await fetch('https://api.borga.is/v1/prices', {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer sk_test_YOUR_SECRET_KEY',
          'X-Merchant-Id': 'mer_YOUR_MERCHANT_ID',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          product: 'pro_01HXYZ',
          currency: 'ISK',
          type: 'recurring',
          unit_amount: 4990,
          recurring: {
            interval: 'month',
          },
        }),
      }).then(r => r.json());

      console.log(price.id); // pri_01HXYZ…
      ```
    </CodeGroup>

    The `unit_amount` is in whole ISK — `4990` charges 4,990 kr per month. Supported intervals are `day`, `week`, `month`, and `year`.

    <Note>
      A product can have multiple prices — for example, a monthly price and an annual price at a discount. You can archive a price to stop new subscriptions from using it without affecting existing subscribers.
    </Note>
  </Step>

  <Step title="Create a customer">
    If you do not already have a customer in Borga, create one. A customer record links subscriptions, invoices, and saved payment methods to a single identity.

    ```bash curl theme={null}
    curl --request POST \
      --url https://api.borga.is/v1/customers \
      --header "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
      --header "X-Merchant-Id: mer_YOUR_MERCHANT_ID" \
      --header "Content-Type: application/json" \
      --data '{
        "email": "subscriber@example.is",
        "name": "Anna Sigurðardóttir"
      }'
    ```

    For `charge_automatically` subscriptions (the most common setup), the customer must have a default saved payment method before the first invoice is charged. You can collect and save a card using a payment session with `save_payment_method: true`, then set it as default with `POST /v1/payment_methods/{id}/set_default`.
  </Step>

  <Step title="Create a subscription">
    Create the subscription by specifying the customer and the price to bill. Pass `trial_period_days` to give new subscribers a free trial before the first charge.

    <CodeGroup>
      ```bash curl theme={null}
      curl --request POST \
        --url https://api.borga.is/v1/subscriptions \
        --header "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
        --header "X-Merchant-Id: mer_YOUR_MERCHANT_ID" \
        --header "Content-Type: application/json" \
        --data '{
          "customer": "cus_01HXYZ",
          "items": [
            { "price": "pri_01HXYZ", "quantity": 1 }
          ],
          "collection_method": "charge_automatically",
          "trial_period_days": 14
        }'
      ```

      ```javascript Node.js theme={null}
      const subscription = await fetch('https://api.borga.is/v1/subscriptions', {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer sk_test_YOUR_SECRET_KEY',
          'X-Merchant-Id': 'mer_YOUR_MERCHANT_ID',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          customer: 'cus_01HXYZ',
          items: [{ price: 'pri_01HXYZ', quantity: 1 }],
          collection_method: 'charge_automatically',
          trial_period_days: 14,
        }),
      }).then(r => r.json());

      console.log(subscription.id);     // sub_01HXYZ…
      console.log(subscription.status); // "trialing"
      ```
    </CodeGroup>

    A subscription created with `trial_period_days` starts in `trialing` status. The first invoice is generated when the trial ends. Without a trial the subscription starts `active` and Borga attempts to charge the customer immediately.
  </Step>

  <Step title="Handle renewals">
    Borga manages the renewal cycle automatically. At the end of each billing period, Borga:

    1. Generates a new invoice for the upcoming period.
    2. Attempts to collect payment from the customer's default payment method (for `charge_automatically`).
    3. Emits a `subscription.renewed` webhook event and an `invoice.paid` event on success.

    You do not need to write any scheduling code. Listen to webhook events to update your application state when renewals succeed or fail — see [Webhooks](/guides/webhooks) for setup details.
  </Step>

  <Step title="Cancel a subscription">
    Cancel a subscription at the end of the current billing period to let the customer keep access until they have paid for, or at the end of the period immediately on request.

    <CodeGroup>
      ```bash At period end theme={null}
      curl --request POST \
        --url https://api.borga.is/v1/subscriptions/sub_01HXYZ/cancel \
        --header "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
        --header "X-Merchant-Id: mer_YOUR_MERCHANT_ID" \
        --header "Content-Type: application/json" \
        --data '{ "at_period_end": true }'
      ```

      ```bash Immediately theme={null}
      curl --request POST \
        --url https://api.borga.is/v1/subscriptions/sub_01HXYZ/cancel \
        --header "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
        --header "X-Merchant-Id: mer_YOUR_MERCHANT_ID" \
        --header "Content-Type: application/json" \
        --data '{ "at_period_end": false }'
      ```
    </CodeGroup>

    Setting `at_period_end: true` moves the subscription to `canceling` status — billing continues until the period ends, then the subscription moves to `canceled`. If the customer changes their mind before the period ends, call `POST /v1/subscriptions/{id}/uncancel` to reverse the cancellation.
  </Step>

  <Step title="Pause and resume">
    Pausing a subscription suspends invoicing without ending the subscription. No invoices are generated while the subscription is paused. Resume it to restart billing from the next scheduled cycle.

    ```bash Pause theme={null}
    curl --request POST \
      --url https://api.borga.is/v1/subscriptions/sub_01HXYZ/pause \
      --header "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
      --header "X-Merchant-Id: mer_YOUR_MERCHANT_ID"
    ```

    ```bash Resume theme={null}
    curl --request POST \
      --url https://api.borga.is/v1/subscriptions/sub_01HXYZ/resume \
      --header "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
      --header "X-Merchant-Id: mer_YOUR_MERCHANT_ID"
    ```

    Pausing is useful for accommodating customer requests to temporarily freeze an account without losing the subscription history or configuration.
  </Step>
</Steps>

## Subscription lifecycle

```mermaid theme={null}
flowchart LR
    A[trialing] --> B[active]
    B --> C[past_due]
    B --> D[paused]
    D --> B
    B --> E[canceling]
    E --> F[canceled]
    C --> F
```

| Status      | Meaning                                           |
| ----------- | ------------------------------------------------- |
| `trialing`  | Within the trial period. No charges yet.          |
| `active`    | Billing normally.                                 |
| `past_due`  | Latest invoice is unpaid past its due date.       |
| `paused`    | Billing suspended. No invoices generated.         |
| `canceling` | Cancellation scheduled for end of current period. |
| `canceled`  | Subscription has ended. No further invoices.      |

<Tip>
  When a customer upgrades to a higher-tier plan mid-cycle, use `proration_behavior: "always_invoice"` when updating the subscription item. Borga generates and immediately finalizes a prorated invoice for the difference rather than rolling it into the next cycle.
</Tip>

## Usage-based billing

If you want to charge customers based on consumption rather than a fixed recurring amount, set up a metered price with a meter. See [Usage billing](/guides/usage-billing) for a full walkthrough.

## Next steps

* [Usage billing](/guides/usage-billing) — bill customers based on actual consumption using meters and events
* [Webhooks](/guides/webhooks) — receive `subscription.created`, `subscription.canceled`, and `invoice.paid` events
* [Accounting link](/guides/accounting-link) — sync invoices to your accounting software automatically
