# List products

Operation ID: `products`

Group: Accounting › Products

[Open in the interactive reference](https://docs.api.lensing.ai/lensing/v1/endpoints/products)

`GET /accounting/products`

Read-only: Reads and returns; changes nothing.

Lists products. Each item is the product without its itemIds and externalIdentifiers. To get both, use GET accounting/products/:id or POST accounting/products/search.

To match by free text or filter by CRM id, use POST accounting/products/search.

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Api-Version` | header | string · v1 | yes | The API version this request targets, named by its public identifier. Required on every request; omitting it, or naming a version this company does not have, is answered with 400. This document describes version `v1`. |

## Query surface

- `id` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between, like
- `productCode` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between, like
- `effectiveStartDate` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between
- `effectiveEndDate` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between
- `productFamily` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between, like
- `productType` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between, like
- `productStatus` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between, like
- `isInventory` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between
- `lastModifiedDate` — filter by eq, ne, gt, gte, lt, lte, in, notIn, between
- Orderable: id, productCode, productName, productStatus, productFamily, productType, isInventory, effectiveStartDate, effectiveEndDate, lastModifiedDate
- Selectable: id, productName, productCode, productNumber, description, internalDescription, crmProductId, effectiveStartDate, effectiveEndDate, productFamily, productType, productStatus, isInventory, lastModifiedDate
- `page[size]` — Page size
- `page[cursor]` — Opaque continuation cursor

## Response

`200` Success

Under `data`, an array of productsRow:

| Field | Type | Required | Filter | Sort | Description |
| --- | --- | --- | --- | --- | --- |
| `id` | string | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`), Pattern (`like`) | yes | The unique identifier for the product. |
| `productName` | string | no | no | yes | The product's display name. |
| `productCode` | string | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`), Pattern (`like`) | yes | The product's code, unique within the tenant. |
| `productNumber` | string \| null | no | no | no | The product number, assigned by the system and unique within the tenant. Absent while none has been assigned. |
| `description` | string \| null | no | no | no | A description of the product shown to customers. |
| `internalDescription` | string \| null | no | no | no | A description of the product for internal use, not shown to customers. |
| `crmProductId` | string \| null | no | no | no | The product's identifier in an external CRM system. |
| `effectiveStartDate` | date | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`) | yes | The date the product becomes available. Format YYYY-MM-DD. |
| `effectiveEndDate` | date \| null | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`) | yes | The date the product is no longer available. Format YYYY-MM-DD. Absent for a product with no end date. |
| `productFamily` | string \| null | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`), Pattern (`like`) | yes | The product family. Possible values: 'software', 'services', 'physicalProducts'. |
| `productType` | string \| null | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`), Pattern (`like`) | yes | The product type. Possible values: 'sub', 'termLicense', 'support', 'professionalServices', 'training', 'usage', 'billableTravelExpense', 'bundle', 'hardwareConsumables', 'billablePassThrough', 'merchandise', 'shipping'. |
| `productStatus` | string \| null | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`), Pattern (`like`) | yes | The product's availability status, computed by the system. Possible values: 'draft', 'available', 'unavailable', 'incomplete'. It is derived from the product's lines, pricing and effective dates and cannot be set directly. |
| `isInventory` | boolean \| null | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`) | yes | Whether the product is tracked as inventory. |
| `lastModifiedDate` | date-time | no | Exact (`eq`, `ne`), Range (`gt`, `gte`, `lt`, `lte`, `between`), Any of (`in`, `notIn`) | yes | The date and time the product record last changed, in UTC. Format YYYY-MM-DDTHH:mm:ss.sssZ. |

```json
{
  "data": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "productName": "<productName>",
      "productCode": "<productCode>",
      "productNumber": "<productNumber>",
      "description": "<description>",
      "internalDescription": "<internalDescription>",
      "crmProductId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "effectiveStartDate": "2026-01-15",
      "effectiveEndDate": "2026-01-15",
      "productFamily": "<productFamily>",
      "productType": "<productType>",
      "productStatus": "<productStatus>",
      "isInventory": true,
      "lastModifiedDate": "2026-01-15T09:30:00.000Z"
    }
  ],
  "pagination": {
    "hasMore": true,
    "nextCursor": "<nextCursor>"
  }
}
```

## Statuses

- `400` — Invalid request or business failure
- `401` — The request carries no valid access token.
- `403` — Not authorized
- `404` — Not found
- `429` — Too many requests from this client address. The response has no body and no `Retry-After` header.
- `500` — Internal server error
