# Returns the products that match the given free-text term and filters.

`POST /accounting/products/search`

Group: Accounting › Products · Operation ID: `searchAccountingProducts`

[Open in the interactive reference](https://docs.api.lensing.ai/?op=searchAccountingProducts)

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Api-Version` | header | `"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`. |

## Request body

Required, `application/json`: searchAccountingProductsInput.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `filters` | object | no | The filters to apply. A product must match every filter you send. Omit to return all products. |
| `filters.term` | string | no | Limits results to products whose name, code or description contains this text. The match is case-insensitive. |
| `filters.productCode` | string | no | Limits results to the product with this product code. The match is exact. |
| `filters.crmProductId` | string | no | Limits results to the product with this CRM identifier. The match is exact. |
| `filters.productStatus` | string | no | Limits results to products with this status. Accepted values: 'draft', 'available', 'unavailable', 'incomplete'. |
| `filters.productFamily` | string | no | Limits results to products of this family. Accepted values: 'software', 'services', 'physicalProducts'. |
| `filters.productType` | string | no | Limits results to products of this type. Accepted values: 'sub', 'termLicense', 'support', 'professionalServices', 'training', 'usage', 'billableTravelExpense', 'bundle', 'hardwareConsumables', 'billablePassThrough', 'merchandise', 'shipping'. |
| `filters.isInventory` | boolean | no | Limits results to products with this inventory-tracking flag. |
| `filters.effectiveStartDate` | object | no | Limits results by the date the product becomes available. Bounds are inclusive. |
| `filters.effectiveStartDate.start` | string | no | The inclusive lower bound. Use format YYYY-MM-DD. |
| `filters.effectiveStartDate.end` | string | no | The inclusive upper bound. Use format YYYY-MM-DD. |
| `filters.effectiveEndDate` | object | no | Limits results by the date the product is no longer available. Bounds are inclusive. A product with no end date matches any lower bound. |
| `filters.effectiveEndDate.start` | string | no | The inclusive lower bound. Use format YYYY-MM-DD. |
| `filters.effectiveEndDate.end` | string | no | The inclusive upper bound. Use format YYYY-MM-DD. |
| `filters.lastModifiedDate` | object | no | Limits results by the date and time the product last changed. Bounds are inclusive. |
| `filters.lastModifiedDate.start` | string | no | The inclusive lower bound, in UTC. Format YYYY-MM-DDTHH:mm:ss.sssZ. |
| `filters.lastModifiedDate.end` | string | no | The inclusive upper bound, in UTC. Format YYYY-MM-DDTHH:mm:ss.sssZ. |
| `filters.entityId` | string | no | Limits results to products visible to this legal entity: shared products and products assigned to it. See id on GET base/entities. An identifier that matches no entity returns an empty page, not an error. |
| `page` | object | no | The pagination controls. Omit for the first page. |
| `page.cursor` | string | no | The cursor from the previous response's pagination.nextCursor. Omit for the first page. |
| `page.size` | number | no | The number of products per page. Defaults to 50. A value above 200 is treated as 200, not rejected. |

Example:

```json
{
  "filters": {
    "term": "<term>",
    "productCode": "<productCode>",
    "crmProductId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "productStatus": "<productStatus>",
    "productFamily": "<productFamily>",
    "productType": "<productType>",
    "isInventory": true,
    "effectiveStartDate": {
      "start": "<start>",
      "end": "<end>"
    },
    "effectiveEndDate": {
      "start": "<start>",
      "end": "<end>"
    },
    "lastModifiedDate": {
      "start": "<start>",
      "end": "<end>"
    },
    "entityId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  },
  "page": {
    "cursor": "<cursor>",
    "size": 0
  }
}
```

## Response

`200` Success

Under `data` (searchAccountingProductsOutput):

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | array of object | yes | The products on this page. An empty array when nothing matches. |
| `items[].id` | string | yes | The unique identifier for the product. |
| `items[].productName` | string | yes | The product's display name. |
| `items[].productCode` | string | yes | The product's code, unique within the tenant. |
| `items[].productNumber` | string | no | The product number, assigned by the system and unique within the tenant. Absent while none has been assigned. |
| `items[].description` | string | no | A description of the product shown to customers. |
| `items[].internalDescription` | string | no | A description of the product for internal use, not shown to customers. |
| `items[].crmProductId` | string | no | The product's identifier in an external CRM system. |
| `items[].effectiveStartDate` | string (date) | yes | The date the product becomes available. Format YYYY-MM-DD. |
| `items[].effectiveEndDate` | string (date) | no | The date the product is no longer available. Format YYYY-MM-DD. Absent for a product with no end date. |
| `items[].productFamily` | string | no | The product family. Possible values: 'software', 'services', 'physicalProducts'. |
| `items[].productType` | string | no | The product type. Possible values: 'sub', 'termLicense', 'support', 'professionalServices', 'training', 'usage', 'billableTravelExpense', 'bundle', 'hardwareConsumables', 'billablePassThrough', 'merchandise', 'shipping'. |
| `items[].productStatus` | string | no | 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. |
| `items[].isInventory` | boolean | no | Whether the product is tracked as inventory. |
| `items[].itemIds` | array of string | no | The inventory items linked to this product. Used only when isInventory is true. Absent when the product has none. There is no endpoint for inventory items. |
| `items[].createdDate` | string (date-time) | no | The date and time the product record was created, in UTC. Format YYYY-MM-DDTHH:mm:ss.sssZ. |
| `items[].lastModifiedDate` | string (date-time) | yes | The date and time the product record last changed, in UTC. Format YYYY-MM-DDTHH:mm:ss.sssZ. |
| `items[].externalIdentifiers` | array of object | no | External identifiers owned by other systems, at most one per fieldName. Absent when the product has none. |
| `items[].externalIdentifiers[].fieldName` | string | yes | The configured key of the external identifier, a camelCase slug rather than the display label. |
| `items[].externalIdentifiers[].value` | string | yes | The identifier's value in the source system. |
| `items[].externalIdentifiers[].externalUrl` | string | no | An absolute http or https link to the object in the source system. Absent when none is stored. |
| `pagination` | object | yes | The pagination cursor for this page. |
| `pagination.nextCursor` | string | no | The cursor for the next page. Pass it as page.cursor. Absent on the last page. |
| `pagination.hasMore` | boolean | yes | True when more products remain beyond this page. |

## Statuses

- `400` — Invalid request or business failure
- `401` — Missing or invalid access token
- `403` — Not authorized
- `404` — Not found
- `429` — Too many requests
- `500` — Internal server error
