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

# Products API — define what you sell

> Create and manage product objects that represent what you sell. Each product can have one or more prices attached, which define the amount and billing interval.

A product represents an item or service you offer — for example, "Pro Plan" or "Storage Add-on". Products are linked to one or more [prices](/api-reference/billing/prices), which define the amount, currency, and billing interval. Use `POST /v1/products` to create a product, then attach prices before using it in a subscription or payment.

<Note>
  Deactivating a product by setting `active: false` does not cancel existing subscriptions that use it. Active subscriptions continue until they are explicitly canceled.
</Note>

***

## Create a product

`POST /v1/products`

Creates a new product object.

### Request parameters

<ParamField body="name" type="string" required>
  Display name for the product. Shown in the dashboard and on invoices.
</ParamField>

<ParamField body="description" type="string">
  An optional description of the product. Useful for internal reference.
</ParamField>

<ParamField body="metadata" type="object">
  Set of key-value pairs you can attach to the product. Values must be strings.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.borga.is/v1/products \
    --header "Authorization: Bearer sk_live_..." \
    --header "X-Merchant-Id: mer_xxx" \
    --header "Content-Type: application/json" \
    --data '{
      "name": "Pro Plan",
      "description": "Full access to all features with priority support.",
      "metadata": {
        "tier": "pro"
      }
    }'
  ```
</RequestExample>

### Response fields

<ResponseField name="id" type="string" required>
  Unique identifier for the product (e.g. `prod_xxx`).
</ResponseField>

<ResponseField name="name" type="string" required>
  Display name of the product.
</ResponseField>

<ResponseField name="description" type="string">
  Product description.
</ResponseField>

<ResponseField name="active" type="boolean" required>
  Whether the product is currently available. Defaults to `true`.
</ResponseField>

<ResponseField name="metadata" type="object">
  Key-value pairs attached to the product.
</ResponseField>

<ResponseField name="created_at" type="string" required>
  ISO 8601 timestamp of when the product was created.
</ResponseField>

<ResponseExample>
  ```json 201 theme={null}
  {
    "id": "prod_01hx9z3k2mfq7nbvd4cw8ej5rt",
    "name": "Pro Plan",
    "description": "Full access to all features with priority support.",
    "active": true,
    "metadata": {
      "tier": "pro"
    },
    "created_at": "2026-04-29T10:15:00Z"
  }
  ```
</ResponseExample>

***

## List products

`GET /v1/products`

Returns a paginated list of products, ordered by creation date descending.

### Query parameters

<ParamField query="starting_after" type="string">
  Cursor for pagination. Pass the `id` of the last product from the previous page to retrieve the next page.
</ParamField>

<ParamField query="limit" type="number">
  Maximum number of products to return per page.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request GET \
    --url "https://api.borga.is/v1/products?limit=20" \
    --header "Authorization: Bearer sk_live_..." \
    --header "X-Merchant-Id: mer_xxx"
  ```
</RequestExample>

### Response fields

<ResponseField name="data" type="object[]" required>
  Array of product objects.

  <Expandable title="product fields">
    <ResponseField name="id" type="string" required>
      Unique product identifier.
    </ResponseField>

    <ResponseField name="name" type="string" required>
      Display name.
    </ResponseField>

    <ResponseField name="description" type="string">
      Product description.
    </ResponseField>

    <ResponseField name="active" type="boolean" required>
      Whether the product is active.
    </ResponseField>

    <ResponseField name="metadata" type="object">
      Key-value pairs attached to the product.
    </ResponseField>

    <ResponseField name="created_at" type="string" required>
      ISO 8601 creation timestamp.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="has_more" type="boolean" required>
  Whether more products exist beyond this page.
</ResponseField>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": [
      {
        "id": "prod_01hx9z3k2mfq7nbvd4cw8ej5rt",
        "name": "Pro Plan",
        "description": "Full access to all features with priority support.",
        "active": true,
        "metadata": {
          "tier": "pro"
        },
        "created_at": "2026-04-29T10:15:00Z"
      }
    ],
    "has_more": false
  }
  ```
</ResponseExample>

***

## Retrieve a product

`GET /v1/products/{id}`

Retrieves the details of an existing product.

### Path parameters

<ParamField path="id" type="string" required>
  The ID of the product to retrieve.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://api.borga.is/v1/products/prod_01hx9z3k2mfq7nbvd4cw8ej5rt \
    --header "Authorization: Bearer sk_live_..." \
    --header "X-Merchant-Id: mer_xxx"
  ```
</RequestExample>

### Response fields

<ResponseField name="id" type="string" required>
  Unique product identifier.
</ResponseField>

<ResponseField name="name" type="string" required>
  Display name of the product.
</ResponseField>

<ResponseField name="description" type="string">
  Product description.
</ResponseField>

<ResponseField name="active" type="boolean" required>
  Whether the product is currently active.
</ResponseField>

<ResponseField name="metadata" type="object">
  Key-value pairs attached to the product.
</ResponseField>

<ResponseField name="created_at" type="string" required>
  ISO 8601 timestamp of when the product was created.
</ResponseField>

<ResponseExample>
  ```json 200 theme={null}
  {
    "id": "prod_01hx9z3k2mfq7nbvd4cw8ej5rt",
    "name": "Pro Plan",
    "description": "Full access to all features with priority support.",
    "active": true,
    "metadata": {
      "tier": "pro"
    },
    "created_at": "2026-04-29T10:15:00Z"
  }
  ```
</ResponseExample>

***

## Update a product

`PATCH /v1/products/{id}`

Updates an existing product. Only the fields you provide are changed.

### Path parameters

<ParamField path="id" type="string" required>
  The ID of the product to update.
</ParamField>

### Request parameters

<ParamField body="name" type="string">
  Updated display name.
</ParamField>

<ParamField body="description" type="string">
  Updated description.
</ParamField>

<ParamField body="active" type="boolean">
  Set to `false` to deactivate the product. Deactivating does not affect existing subscriptions.
</ParamField>

<ParamField body="metadata" type="object">
  Updated metadata. Replaces the existing metadata object entirely.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request PATCH \
    --url https://api.borga.is/v1/products/prod_01hx9z3k2mfq7nbvd4cw8ej5rt \
    --header "Authorization: Bearer sk_live_..." \
    --header "X-Merchant-Id: mer_xxx" \
    --header "Content-Type: application/json" \
    --data '{
      "active": false,
      "metadata": {
        "tier": "pro",
        "deprecated": "true"
      }
    }'
  ```
</RequestExample>

### Response fields

Returns the updated product object. See [retrieve a product](#retrieve-a-product) for the full field reference.

<ResponseExample>
  ```json 200 theme={null}
  {
    "id": "prod_01hx9z3k2mfq7nbvd4cw8ej5rt",
    "name": "Pro Plan",
    "description": "Full access to all features with priority support.",
    "active": false,
    "metadata": {
      "tier": "pro",
      "deprecated": "true"
    },
    "created_at": "2026-04-29T10:15:00Z"
  }
  ```
</ResponseExample>
