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

# Product catalog

> Fetch the latest catalog of products available for use in payouts

Whether you're showing the latest product offering to your customers, or verifying constraints during your order process, you'll want the latest catalog details.

## Countries & currencies

To create a payout link, you'll need to provide one or more products that are all redeemable in the same currency. See the [currencies](/reference/currencies) reference for a list of currency supported countries.

You may also want to limit the products you return to only those that can be redeemed in a specific country. You can fetch a list of countries using the [list countries](/reference/2024-02-05/endpoint/products/countries) endpoint. This will return a list of ISO3166 ALPHA-2 country codes. We'll be modifying this list over time, so your implementation should handle the addition and removal of countries from this list.

You can use this to aggregate products that belong to a country for ordering by using the `countries_redeemable_in` query parameter, in the endpoint described below.

## Retrieving your catalog

We recommend that you query the [list endpoint](/reference/2024-02-05/endpoint/products/list) to retrieve full catalog details periodically and in any critical journeys where you [fetch the details of an individual product](/reference/2024-02-05/endpoint/products/get) by using the `code` query parameter to return the latest details of a product in a timely manner. You can also use the [product update webhook](/reference/2024-02-05/webhook/product.update) to be notified of changes to products.

<CardGroup cols={2}>
  <Card title="List all products" icon="grid" href="/reference/2024-02-05/endpoint/products/list" horizontal arrow>
    Endpoint details for listing all products, filterable by country
  </Card>

  <Card title="Get details of a specific product" icon="square" href="/reference/2024-02-05/endpoint/products/get" horizontal arrow>
    Endpoint details for getting details of a specific product by its code
  </Card>
</CardGroup>

## Filtering the catalog

You can filter by a number of fields in the list endpoint to reduce the number of products returned to only those that are relevant to your customers.

| Query parameter           | Description                                                                                                                                                                     |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `is_orderable`            | When set to `true` only returns products that can be ordered. If you're presenting a list of products to your customers, you should only display products where this is `true`. |
| `countries_redeemable_in` | Only return products that can be redeemed in a specific country, see the [countries reference](/reference/countries) for currently supported countries.                         |
| `categories`              | Limit the products to one or more categories, see the [categories endpoint](/reference/2024-02-05/endpoint/products/categories) for a list of all current categories.           |

## Important fields

A few of the key fields that should influence your implementation are detailed below. For details on all fields, see the [product list endpoint](/reference/2024-02-05/endpoint/products/list) reference.

### Generic fields

<ResponseField name="code" type="string">
  <Card>
    A unique code identifying the product. Use this code when placing an order.
  </Card>
</ResponseField>

<ResponseField name="is_orderable" type="boolean">
  <Card>
    This field indicates whether you are currently able to order a product or
    not. We recommend that you only ever display products to people placing
    orders when this field is `true` - we will reject any orders placed for
    products where this is `false` . You can pass this as a query parameter as
    part of your request.
  </Card>
</ResponseField>

<ResponseField name="currency" type="string">
  <Card>
    The currency of the product, represented by an ISO 4217 currency code. See
    [currencies](/reference/currencies) for a list of supported currencies.
    Orders can only be placed in one currency at a time, ensure you don't mix
    currencies in the same order.
  </Card>
</ResponseField>

<ResponseField name="countries_redeemable_in" type="string[]">
  <Card>
    The countries in which the product can be redeemed. See the [countries
    reference](/reference/countries) for a list of supported countries. You can
    filter by this field to only return products that can be redeemed in a
    specific country.
  </Card>
</ResponseField>

### Type specific fields

There are three different payout types that you can order, each with their own specific object for details.

* `gift_card`: A gift card is a payout that can be redeemed for a specific value.
* `subscription`: A subscription is a payout that can be ordered for a specific duration.
* `payment`: A payment is a payout that can be ordered for a specific value.

<ResponseField name="payout_type" type="string">
  <Card>
    You should use the `payout_type` field to determine which object to use to extract details for the product.

    We'll be adding more payout types in the future, and your implementation should handle these additions gracefully.
  </Card>
</ResponseField>

#### Specific `gift_card` fields

The `gift_card` object will only be present when the `payout_type` is `gift_card`.

<ResponseField name="gift_card.denominations" type="object">
  <Card>
    Gift cards are either `open` or `fixed` denomination.

    * `open` products will include `minimum_value` and `maximum_value` fields. This means that you can order gift cards within the range of `minimum_value` and `maximum_value`.
    * `fixed` products will include a list of values in the `available_list` field. You can only order values contained in the list that is returned to you.

    <CodeGroup>
      ```json Open denomination example theme={null}
      "denominations": {
          "type": "open",
          "minimum_value": "5.00",
          "maximum_value": "250.00",
          "available_list": null
      }
      ```

      ```json Fixed denomination example theme={null}
      "denominations": {
          "type": "fixed",
          "minimum_value": "10.00",
          "maximum_value": "100.00",
          "available_list": ["10.00", "20.00", "50.00", "100.00"]
      }
      ```
    </CodeGroup>
  </Card>
</ResponseField>

#### Specific `subscription` fields

The `subscription` object will only be present when the `payout_type` is `subscription`.

<ResponseField name="subscription.subscription_plans" type="object[]">
  <Card>
    Subscriptions each come with a list of subscription plans, detailing things such as the duration of the subscription and the price it costs to order each of the subscription plans – this is without your discount applied.

    ```json Subscription plan example theme={null}
    {
        "length_unit": "MONTHS",
        "length": 3,
        "name": "3 month subscription",
        "price": "10.00",
        "subscription_plan_code": "XYZ-US-SUB-1"
    },
    {
        "length_unit": "MONTHS",
        "length": 6,
        "name": "6 month subscription",
        "price": "20.00",
        "subscription_plan_code": "XYZ-US-SUB-2"
    }
    ```

    <Info>
      **`subscription_plan_code`** is returned as part of the subscription plan. You must use this code, not the top-level code as part of your order.
    </Info>
  </Card>
</ResponseField>

#### Specific `payment` fields

The `payment` object will only be present when the `payout_type` is `payment`.

<ResponseField name="payment.denominations" type="object">
  <Card>
    Similar to gift cards, payments have denomination constraints with `minimum_value` and `maximum_value` fields that define the allowed payment ranges, but will always be open denomination. Therefore, we don't have the list of available denominations here.

    ```json Payment denomination example theme={null}
    "denominations": {
        "minimum_value": "5.00",
        "maximum_value": "250.00",
    }
    ```
  </Card>
</ResponseField>

## Paging through the catalog

The catalog is paginated, with a default page size of 500 products. You can use the `after` and `limit` query parameters to control the page size and the cursor to fetch the next page of products.

```http theme={null}
GET /product?after={cursor}&limit=100
```

The response will include a `pagination` object with the following fields. You can use the `after` cursor to fetch the next page of products, and the `before` cursor to fetch the previous page of products.

```json {3} theme={null}
"pagination": {
    "cursors": {
        "after": "MMM-US",
        "before": "AAA-US"
    },
    "page": {
        "limit": 100
    }
}
```

<Card title="Pagination reference" icon="file" href="/reference/pagination" horizontal arrow>
  More details on how pagination works in the Runa API.
</Card>

## Keeping your catalog in sync

If you maintain a copy of the product catalog in your system you can use the [product update webhook](/reference/2024-02-05/webhook/product.update) to keep it synchronized and avoid order failures.

<Card title="How to implement real-time product updates" href="/features/realtime-product-updates" icon="webhook" horizontal arrow>
  Next take a read of our guide to implement real-time product updates in your
  system.
</Card>
