---
title: "List catalog items"
method: GET
path: "/catalog-items"
tags: ["Catalog"]
---

# List catalog items

`GET /catalog-items`

## Request

- Base URL: `https://joinways.app/api/v1`
- URL: `https://joinways.app/api/v1/catalog-items`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://joinways.app/oauth/authorize`, token URL `https://joinways.app/api/oauth/token`, scopes: `mcp.read`)

Catalog of a venue the token owner can see, by category then name. Prices are the catalog's unless `pax`, `date` or `event_id` is given: each item then also gets `resolved_unit_price`, `resolved_min_price` and `applied_price_rule` (price rules applied), without any other field changing. A package (`is_package: true`) lists its `components`; to quote it, send its id as the `location_item_id` of one quote line (see Packages). **Role permission:** none (any member; limited to the member's venues).

## Query parameters

- `venue_id` string, uuid, required
- `page` integer
- `per_page` integer
- `category` string
- `type` string
- `q` string
- `pax` integer
- `date` string, date
- `event_id` string, uuid

## Response `200`

Page of catalog items.

- object: Envelope wrapping a page of results.
  - `data` CatalogItem[], required: The page of results (item type depends on the endpoint).
    - `id` string, uuid
    - `name` string
    - `category` string, nullable
    - `type` string, nullable
    - `unit_label` string, nullable
    - `pricing_mode` 'flat' | 'per_person' | 'tiered': Which price applies: `flat` = `unit_price` per unit, `per_person` = `unit_price_per_person` × guests, `tiered` = the item's price rules.
    - `unit_price` number, nullable: Price per unit, excluding tax.
    - `unit_price_per_person` number, nullable
    - `cost_price` number, nullable: Internal cost.
    - `min_price` number, nullable: Minimum price a quote line may use.
    - `vat` number, nullable: Tax rate in %.
    - `vat_rate` number, nullable: Same value as `vat`.
    - `taxable` boolean, nullable
    - `is_package` boolean: The item is a package, made of the items in `components`. Its price (`unit_price`, or `unit_price_per_person` when `pricing_mode` is `per_person`) is the sum of `quantity × unit_price` of its components, and its `vat` only the lowest of their rates.
    - `components` CatalogItemComponent[]: Only on a package, in the order of its composition (written with `components` on create / update).
      - `item_id` string, uuid, required: The catalog item (an item of the same venue, never a package).
      - `name` string, nullable
      - `quantity` number, required: Quantity of the item in one package unit.
      - `unit_price` number, required: Unit price of the item inside the package, excluding tax.
      - `vat` number, nullable: Tax rate of the item, in %.
    - `created_at` string, date-time, nullable
    - `updated_at` string, date-time, nullable
    - `description` string, nullable: Create / update only.
    - `tags` string[], nullable: Create / update only.
    - `location_id` string, uuid, nullable: Create / update only.
    - `space_id` string, uuid, nullable: Create / update only.
    - `resolved_unit_price` number: Only when `pax`, `date` or `event_id` is passed. Price for that context, price rules applied.
    - `resolved_min_price` number, nullable: With `resolved_unit_price`. Floor of the applied rule, else of the catalog.
    - `applied_price_rule` object, nullable: With `resolved_unit_price`. The rule applied, or `null` when the catalog price applies.
      - `id` string, uuid
      - `label` string, nullable
  - `pagination` object, required
    - `page` integer, required: Current 1-based page.
    - `per_page` integer, required: Items per page.
    - `total` integer, nullable, required: Total matching items across all pages (`null` only on a page past the last one, when unknown).
    - `total_pages` integer, nullable, required

## Other responses

- `400`: Validation failed (`invalid_request`). For a body that fails the schema, `details` holds `formErrors` and `fieldErrors`.
- `401`: Missing, invalid, expired or revoked bearer token (`unauthorized`).
- `404`: Not found in this workspace, or the id of the path is not a UUID (`not_found`).
- `429`: Too many requests (`rate_limited`). `details.reason`: `per-ip`, `per-account-minute`, `per-account-day`, or `email_rate_limited` (email budget). Always carries `Retry-After`: wait that many seconds.

---

[API](https://skmtc.dev/joinways/apis/joinways-public-api.md) · [All operations](https://skmtc.dev/joinways/apis/joinways-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/joinways/apis/joinways-public-api/revisions/39e84309953e?raw)
