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

# List Bundles

Retrieve the bundles of your store, newest first, with cursor-based pagination.

---

## Endpoint

```
GET /api/v3/bundles
```

The list only returns the bundles of your own store.

---

## Query Parameters

### Pagination

| Parameter  | Type    | Default | Description                                    |
| ---------- | ------- | ------- | ---------------------------------------------- |
| `per_page` | integer | 100     | Items per page, between `1` and `500`          |
| `cursor`   | string  | -       | Cursor token from `links.next` or `links.prev` |

### Sorting

| Parameter | Type   | Default       | Description                                |
| --------- | ------ | ------------- | ------------------------------------------ |
| `sort`    | string | `-created_at` | Sort field. Prefix with `-` for descending |

**Allowed sort fields:** `created_at`, `updated_at`

Bundles that share a sort value are ordered by `id`, so pages never repeat or skip a bundle.

### Filters

| Parameter             | Type   | Description                                                                                                        |
| --------------------- | ------ | ------------------------------------------------------------------------------------------------------------------ |
| `filter[external_id]` | string | The bundle with this `external_id`. Matches the whole value without case: a comma is part of the value, not a list |

`filter[external_id]` is the list-side way to find a bundle after a create whose outcome you do not know. See [Retries](./bundles-v3-overview.md#retries).

### Included Blocks

| Parameter | Type   | Description                                                                                                                       |
| --------- | ------ | --------------------------------------------------------------------------------------------------------------------------------- |
| `include` | string | Comma-separated: `products`, `prices`, `availability`, `detailed_stock`. See [Included blocks](./bundles-v3-overview.md#includes) |

Without `include`, the list does not compute any block for its bundles. Ask only for the blocks you need.

### Fields Selection

| Parameter | Type   | Description                                                                                       |
| --------- | ------ | ------------------------------------------------------------------------------------------------- |
| `fields`  | string | Comma-separated list of fields to return. Applied after `include`, so it cannot add a block alone |

---

## Request Examples

```bash
# First page, 50 bundles
curl -X GET "https://yourstore.publica.la/api/v3/bundles?per_page=50" \
  -H "X-User-Token: your-api-token" \
  -H "Accept: application/json"

# With price and availability
curl -X GET "https://yourstore.publica.la/api/v3/bundles?include=prices,availability" \
  -H "X-User-Token: your-api-token" \
  -H "Accept: application/json"

# Find a bundle by your identifier
curl -g -X GET "https://yourstore.publica.la/api/v3/bundles?filter[external_id]=rock-icons" \
  -H "X-User-Token: your-api-token" \
  -H "Accept: application/json"

# Recently updated first, trimmed payload
curl -X GET "https://yourstore.publica.la/api/v3/bundles?sort=-updated_at&fields=id,external_id,updated_at" \
  -H "X-User-Token: your-api-token" \
  -H "Accept: application/json"
```

---

## Response

The response to `GET /api/v3/bundles?per_page=50&include=products,prices,availability`, trimmed to its first bundle. `meta.has_more` is `true` only when the page holds `per_page` bundles:

```json
{
  "data": [
    {
      "id": "318",
      "external_id": "rock-icons",
      "name": "Rock Icons",
      "slug": "rock-icons",
      "description": "The classics, together",
      "cover_url": null,
      "private": false,
      "published": true,
      "published_at": "2026-10-06T14:05:00.000000Z",
      "product_url": "https://yourstore.publica.la/library/bundle/rock-icons/318?signature=9f2c4e7a…",
      "buy_button_url": "https://yourstore.publica.la/library/bundle/rock-icons/318?signature=9f2c4e7a…&automatically_open_checkout=1",
      "created_at": "2026-10-06T14:00:00.000000Z",
      "updated_at": "2026-10-06T14:05:00.000000Z",
      "products": [
        {
          "id": "1201",
          "position": 0,
          "name": "Rock Icons, Volume 1",
          "available": true,
          "rejection_reason": null
        },
        {
          "id": "1202",
          "position": 1,
          "name": "Rock Icons, Volume 2",
          "available": true,
          "rejection_reason": null
        }
      ],
      "prices": [{ "currency_id": "USD", "amount": 15 }],
      "availability": { "available": true, "reasons": [] }
    }
  ],
  "links": {
    "next": "https://yourstore.publica.la/api/v3/bundles?per_page=50&include=products%2Cprices%2Cavailability&cursor=eyJ...",
    "prev": null
  },
  "meta": {
    "has_more": true
  }
}
```

Each item is a [bundle object](./bundles-v3-overview.md#the-bundle-object). Without `include`, each item ends at `updated_at`.

### Pagination Workflow

1. Make the first request without `cursor`.
2. Follow `links.next` as it is: it already carries your other parameters.
3. Stop when `meta.has_more` is `false`.

:::tip Best Practice
Always use `meta.has_more` to detect the end of results, not the number of items. These responses carry no total count.
:::

---

## Errors

| Status | Condition                                                                                                                                                                                                                                                                                                                        |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `401`  | Missing or invalid `X-User-Token`                                                                                                                                                                                                                                                                                                |
| `403`  | Selling is disabled for the store (`Selling is disabled for this store.`), or the token does not belong to an administrator                                                                                                                                                                                                      |
| `422`  | Invalid query parameter: `per_page` outside `1` to `500`, an unknown sort field, a filter other than `external_id` (reported under `filter.<name>`), an `include` other than `products`, `prices`, `availability` or `detailed_stock`, or a `sort`, `filter` or `include` of the wrong shape, such as `include` sent as an array |

---

## See Also

- [Bundles API Overview](./bundles-v3-overview.md): the bundle object and its codes
- [Get a Bundle](./bundles-v3-get.md): read one bundle
- [Create a Bundle](./bundles-v3-create.md): build a bundle from your products
