Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Avelero/avelero/llms.txt

Use this file to discover all available pages before exploring further.

Retrieve a paginated list of products from your catalog with support for filtering, searching, and sorting.

Endpoint

trpc.products.list.query(input)
Router location: apps/api/src/trpc/routers/products/index.ts:233

Request parameters

brand_id
string
UUID of the brand. Must match the active brand context if provided.
cursor
string
Cursor for pagination. Obtained from the previous response’s meta.cursor field.
limit
number
Number of products to return per page.Range: 1-100Default: 50
fields
string[]
Array of field names to return. If omitted, all available fields are returned.Available fields:
  • id
  • name
  • description
  • brand_id
  • category_id
  • season_id
  • manufacturer_id
  • image_path
  • product_handle
  • upid
  • status
  • created_at
  • updated_at
Search query to filter products by name, description, or other text fields.Max length: 100 characters
includeVariants
boolean
Include product variants in the response.Default: false
includeAttributes
boolean
Include product attributes (materials, environment, etc.) in the response.Default: false

Filtering

filters
object
Advanced filtering using FilterState structure. Groups are combined with AND logic, conditions within groups are combined with OR logic.

Sorting

sort
object
Sort configuration

Response

data
array
Array of product objects
meta
object
Pagination metadata

Example requests

Basic list

const products = await trpc.products.list.query({
  limit: 20
});

console.log(products.data.length); // Up to 20 products
console.log(products.meta.total); // Total matching products
console.log(products.meta.hasMore); // true if more pages available

With pagination

// First page
const firstPage = await trpc.products.list.query({
  limit: 50
});

// Next page
if (firstPage.meta.hasMore) {
  const secondPage = await trpc.products.list.query({
    cursor: firstPage.meta.cursor,
    limit: 50
  });
}
const products = await trpc.products.list.query({
  search: "cotton",
  limit: 20
});
// Returns products with "cotton" in name, description, etc.

With filters

const publishedProducts = await trpc.products.list.query({
  filters: {
    groups: [
      {
        id: "status-filter",
        conditions: [
          {
            id: "cond-1",
            fieldId: "status",
            operator: "equals",
            value: "published"
          }
        ]
      }
    ]
  }
});

Multiple filter conditions (OR logic)

const products = await trpc.products.list.query({
  filters: {
    groups: [
      {
        id: "category-filter",
        conditions: [
          // Products in category A OR category B
          {
            id: "cond-1",
            fieldId: "category_id",
            operator: "equals",
            value: "category-a-uuid"
          },
          {
            id: "cond-2",
            fieldId: "category_id",
            operator: "equals",
            value: "category-b-uuid"
          }
        ]
      }
    ]
  }
});

Multiple filter groups (AND logic)

const products = await trpc.products.list.query({
  filters: {
    groups: [
      {
        id: "status-group",
        conditions: [
          {
            id: "status-cond",
            fieldId: "status",
            operator: "equals",
            value: "published"
          }
        ]
      },
      {
        id: "date-group",
        conditions: [
          {
            id: "date-cond",
            fieldId: "created_at",
            operator: "greaterThan",
            value: { after: "2024-01-01" }
          }
        ]
      }
    ]
  }
});
// Returns products that are published AND created after 2024-01-01

With sorting

const products = await trpc.products.list.query({
  sort: {
    field: "createdAt",
    direction: "desc"
  },
  limit: 20
});
// Returns 20 most recently created products

With variants and attributes

const products = await trpc.products.list.query({
  includeVariants: true,
  includeAttributes: true,
  limit: 10
});

// Each product includes:
// - variants: Array of variant objects with SKU, barcode, etc.
// - materials: Array of material compositions
// - environment: Environmental impact data
// - journeySteps: Production journey

Field selection

const products = await trpc.products.list.query({
  fields: ["id", "name", "product_handle", "status"],
  limit: 100
});
// Returns only specified fields (more efficient for large lists)

Complex query

const products = await trpc.products.list.query({
  search: "organic",
  filters: {
    groups: [
      {
        id: "status-group",
        conditions: [
          {
            id: "status-cond",
            fieldId: "status",
            operator: "equals",
            value: "published"
          }
        ]
      },
      {
        id: "season-group",
        conditions: [
          {
            id: "season-cond",
            fieldId: "season_id",
            operator: "in",
            value: ["spring-2024", "summer-2024"]
          }
        ]
      }
    ]
  },
  sort: {
    field: "name",
    direction: "asc"
  },
  limit: 50,
  includeVariants: true
});

Date range filters

// Products created in 2024
const products = await trpc.products.list.query({
  filters: {
    groups: [
      {
        id: "date-range",
        conditions: [
          {
            id: "created-2024",
            fieldId: "created_at",
            operator: "between",
            value: {
              after: "2024-01-01T00:00:00Z",
              before: "2024-12-31T23:59:59Z"
            }
          }
        ]
      }
    ]
  }
});

Relative date filters

// Products created in the last 7 days
const products = await trpc.products.list.query({
  filters: {
    groups: [
      {
        id: "recent",
        conditions: [
          {
            id: "last-week",
            fieldId: "created_at",
            operator: "relative",
            value: {
              type: "relative",
              option: "last 7 days"
            }
          }
        ]
      }
    ]
  }
});
Available relative options:
  • today
  • yesterday
  • last 7 days
  • last 30 days
  • this month
  • last month
  • this quarter
  • this year
  • more than X days ago (with customDays field)

Performance optimization

Use includeVariants and includeAttributes only when needed. These flags trigger additional database queries and can impact performance for large result sets.
Use field selection to return only the data you need. This reduces response size and improves query performance.
// Efficient query for dropdown lists
const products = await trpc.products.list.query({
  fields: ["id", "name", "product_handle"],
  limit: 100
});

Error codes

BAD_REQUEST
error
Invalid input or validation errorCommon causes:
  • limit exceeds 100
  • Invalid field name in fields array
  • Active brand does not match brand_id
  • Invalid filter structure
  • Invalid sort field

Validation rules

  • limit: 1-100 (default: 50)
  • search: Max 100 characters
  • fields: Must be valid product field names from PRODUCT_FIELDS
  • brand_id: Must match active brand context if provided

Source code reference

  • Schema definition: apps/api/src/schemas/products.ts:519 (productsDomainListSchema)
  • Implementation: apps/api/src/trpc/routers/products/index.ts:233
  • Database query: @v1/db/queries/products (listProductsWithIncludes)
  • Available fields: apps/api/src/schemas/products.ts:45 (PRODUCT_FIELDS)

Build docs developers (and LLMs) love