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

# List Products

> Retrieve products in your workspace with pagination and filters

## Authorization

<ParamField header="Authorization" type="string" required>
  Bearer token for authentication. Format: `Bearer qwoty_your_token`
</ParamField>

## Query Parameters

<ParamField query="limit" type="integer" default="30">
  Number of results per page (max 200)
</ParamField>

<ParamField query="page" type="integer" default="1">
  Page number (1-based)
</ParamField>

<ParamField query="external_id" type="string">
  Filter by external identifier. Matches against `identifiers[erp]`,
  `identifiers[crm]`, and `identifiers[accounting]`.
</ParamField>

<ParamField query="api_name" type="string">
  Filter by exact API name
</ParamField>

<ParamField query="sku" type="string">
  Filter by SKU (`inventory[sku]`)
</ParamField>

<ParamField query="reference" type="string">
  Filter by internal reference
</ParamField>

## Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl https://qwoty.app/api/products \
    -H "Authorization: Bearer qwoty_your_token"
  ```

  ```bash With Filters theme={null}
  curl "https://qwoty.app/api/products?limit=30&sku=CONS-SEN-001" \
    -H "Authorization: Bearer qwoty_your_token"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://qwoty.app/api/products?limit=30', {
    headers: {
      Authorization: 'Bearer qwoty_your_token',
    },
  })

  const data = await response.json()
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      'https://qwoty.app/api/products',
      params={'limit': 30},
      headers={
          'Authorization': 'Bearer qwoty_your_token'
      }
  )

  data = response.json()
  ```
</CodeGroup>

## Response

<ResponseField name="total" type="integer">
  Total number of products matching the query (across all pages)
</ResponseField>

<ResponseField name="next" type="string | null">
  URL to fetch the next page, or `null` if this is the last page
</ResponseField>

<ResponseField name="data" type="array">
  Array of product objects for the current page

  <Expandable title="Product Object">
    <ResponseField name="id" type="string">
      Unique identifier (UUID)
    </ResponseField>

    <ResponseField name="product_parent_id" type="string">
      ID of parent product (UUID)
    </ResponseField>

    <ResponseField name="workspace_id" type="string">
      Workspace ID (UUID)
    </ResponseField>

    <ResponseField name="name" type="string">
      Product name (display name combining parent + variant options)
    </ResponseField>

    <ResponseField name="api_name" type="string">
      API identifier
    </ResponseField>

    <ResponseField name="reference" type="string">
      Internal reference
    </ResponseField>

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

    <ResponseField name="description_inherit_from_product" type="boolean">
      Whether description is inherited from the parent product
    </ResponseField>

    <ResponseField name="primary_image_inherit_from_product" type="boolean">
      Whether the primary image is inherited from the parent product
    </ResponseField>

    <ResponseField name="is_active" type="boolean">
      Active status
    </ResponseField>

    <ResponseField name="is_default" type="boolean">
      Whether this is the default product under its parent
    </ResponseField>

    <ResponseField name="catalogs" type="array">
      Catalogs linked to the parent product

      <Expandable title="Catalog Entry">
        <ResponseField name="id" type="string">Catalog ID (UUID)</ResponseField>
        <ResponseField name="api_name" type="string">Catalog API name</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="categories" type="array">
      Categories linked to the parent product

      <Expandable title="Category Entry">
        <ResponseField name="id" type="string">Category ID (UUID)</ResponseField>
        <ResponseField name="api_name" type="string">Category API name</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="settings" type="object">
      Product settings and configuration
    </ResponseField>

    <ResponseField name="shipping" type="object">
      Shipping information
    </ResponseField>

    <ResponseField name="inventory" type="object">
      Inventory information
    </ResponseField>

    <ResponseField name="identifiers" type="object">
      External system identifiers
    </ResponseField>

    <ResponseField name="accounting" type="object">
      Accounting information
    </ResponseField>

    <ResponseField name="options" type="array">
      Option values for this product (e.g., color, size)

      <Expandable title="Option Object">
        <ResponseField name="option_id" type="string">Option definition ID (UUID)</ResponseField>
        <ResponseField name="option_name" type="string">Option name (e.g., "Color")</ResponseField>
        <ResponseField name="option_api_name" type="string">Option API name</ResponseField>
        <ResponseField name="value_id" type="string">Option value ID (UUID)</ResponseField>
        <ResponseField name="value_name" type="string">Option value (e.g., "Blue")</ResponseField>
        <ResponseField name="value_api_name" type="string">Value API name</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="prices" type="array">
      Prices associated with this product across all pricebooks

      <Expandable title="Price Entry">
        <ResponseField name="id" type="string">Price ID (UUID)</ResponseField>
        <ResponseField name="pricebook_id" type="string">Pricebook ID (UUID)</ResponseField>
        <ResponseField name="pricebook_api_name" type="string">API name of the pricebook</ResponseField>

        <ResponseField name="pricing_model" type="string">
          Pricing model (`flat`, `volume`, `graduated`, `percent`, `cost_based`, `none`)
        </ResponseField>

        <ResponseField name="amount" type="number | null">
          Unit price. Only populated when `pricing_model` is `flat`, otherwise `null`.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="primary_image_id" type="string">
      UUID of the primary media for this product. Null if none is set.
    </ResponseField>

    <ResponseField name="parent_primary_image_id" type="string">
      UUID of the primary media of the parent product. Read-only.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Success Response theme={null}
  {
    "total": 42,
    "next": "https://qwoty.app/api/products?limit=30&page=2",
    "data": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "product_parent_id": "660e8400-e29b-41d4-a716-446655440001",
        "workspace_id": "880e8400-e29b-41d4-a716-446655440003",
        "name": "Consulting Services - Senior",
        "api_name": "consulting_services_senior",
        "reference": "SERV-001",
        "description": "Senior consultant hourly rate",
        "description_inherit_from_product": true,
        "primary_image_inherit_from_product": true,
        "is_active": true,
        "is_default": true,
        "catalogs": [
          {
            "id": "770e8400-e29b-41d4-a716-446655440002",
            "api_name": "catalog_main"
          }
        ],
        "categories": [],
        "settings": {
          "unit_per_pack": 1,
          "product_type": "service",
          "language_code": "en",
          "unit_of_measure": "hour",
          "recurrence_type": "recurring"
        },
        "shipping": {
          "weight": null,
          "weight_unit": null,
          "height": null,
          "length": null,
          "width": null,
          "length_unit": null,
          "country_of_origin": null,
          "harmonized_system_code": null
        },
        "inventory": {
          "sku": "CONS-SEN-001"
        },
        "identifiers": {
          "crm": null,
          "accounting": null,
          "erp": null
        },
        "accounting": {
          "ledger_account": null
        },
        "options": [
          {
            "option_id": "opt-001",
            "option_name": "Seniority",
            "option_api_name": "seniority",
            "value_id": "val-001",
            "value_name": "Senior",
            "value_api_name": "senior"
          }
        ],
        "prices": [
          {
            "id": "price-001",
            "pricebook_id": "pb-001",
            "pricebook_api_name": "standard",
            "pricing_model": "flat",
            "amount": 1990
          }
        ],
        "primary_image_id": null,
        "parent_primary_image_id": null,
        "created_at": "2024-12-21T10:30:00Z",
        "updated_at": "2024-12-21T10:30:00Z"
      }
    ]
  }
  ```
</ResponseExample>

## Error Responses

<ResponseExample>
  ```json Unauthorized theme={null}
  {
    "error": "Invalid API token"
  }
  ```
</ResponseExample>
