# Search sales returns

Operation ID: `searchSalesReturns`

Group: Inventory › Sales Returns

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

`POST /inventory/sales-returns/search`

Read-only: A read that takes its filters in the body. Changes nothing, and ignores Idempotency-Key.

Searches sales returns. Each return comes back with its lines, including their batches, serials, bins, and inspection details, in the same shape as GET inventory/sales-returns/:id.

Only this endpoint filters by customer, reference number, tracking number, item, or warehouse. A return matches itemId or locationId when any of its lines has that item or warehouse.

## 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`. |

## Request body

Required, `application/json`: searchSalesReturnsInput.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `filters` | object | yes | The criteria to apply, combined with AND. Omit to return all sales returns. Example: `{"documentStatus":"RECEIVED"}`. |
| `filters.documentNumber` | string | no | Limits results to the return with this document number. The match is exact. |
| `filters.documentStatus` | string | no | Limits results to returns with this status. The match is exact. Possible values: 'DRAFT', 'OPEN', 'COMMITTED', 'RECEIVED', 'INSPECTED', 'PROCESSED', 'COMPLETED', 'CANCELLED'. |
| `filters.entityId` | string | no | Limits results to returns for the legal entity with this identifier. |
| `filters.businessPartnerId` | string | no | Limits results to returns for the customer with this identifier. Despite the name, this is a customer id. |
| `filters.locationId` | string | no | Limits results to returns with a line for the warehouse with this identifier. |
| `filters.itemId` | string | no | Limits results to returns with a line for the item with this identifier. |
| `filters.referenceNumber` | string | no | Limits results to returns with this customer reference, for example an RMA number. The match is exact. |
| `filters.trackingNumber` | string | no | Limits results to returns with this carrier tracking number. The match is exact. |
| `filters.fromDate` | date | no | Limits results to returns dated on or after this date. Use format YYYY-MM-DD. |
| `filters.toDate` | date | no | Limits results to returns dated on or before this date. Use format YYYY-MM-DD. |
| `filters.modifiedSince` | date-time | no | Limits results to returns changed on or after this time, in UTC. Use format YYYY-MM-DDTHH:mm:ss.sssZ. |
| `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 on the first request. |
| `page.size` | number | no | The maximum number of returns to return. Defaults to 50. The maximum is 200. |

```json
{
  "filters": {
    "documentStatus": "RECEIVED"
  },
  "page": {
    "cursor": "<cursor>",
    "size": 0
  }
}
```

## Response

`200` Success

Under `data` (searchSalesReturnsOutput):

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | array<object> | yes | The matching returns for this page, oldest first, each with its lines. An empty array when nothing matches. Example: `[{"id":"5e9b0c74-1a26-4d83-b5f0-73c8e2a91d46","documentNumber":"SR-1042","documentStatus":"INSPECTED","documentDate":"2026-08-14","deliveryDate":"2026-08-18","entityId":"1a9c4e70-38b5-4d26-9f01-7c2e5b8a6d43","entityName":"Acme Netherlands B.V.","businessPartnerId":"c73f2b81-5d94-4e60-a812-0f9b6d3e45c7","businessPartnerName":"Bakker Retail B.V.","sourceDocumentId":"55120","sourceDocumentType":"SalesDelivery","referenceNumber":"RMA-2026-0087","trackingNumber":"3SABCD1234567","currency":"EUR","totalAmount":"144.00","returnFeeAmount":"0.00","notes":"Customer reports transit damage","createdDate":"2026-08-14T08:30:00.000Z","lastModifiedDate":"2026-08-19T15:10:00.000Z","lines":[{"id":"8c14a6f2-3b70-4d59-9e02-6f5a1d38b47c","itemId":"5f21c8b0-9d34-4a76-8e12-04b93c7de5a8","itemCode":"WIDGET-01","itemName":"Standard widget","locationId":"e1d84c07-5b39-4a26-9f70-2c8b613ad495","locationCode":"WH-01","locationName":"Rotterdam Distribution Centre","unitId":"3b7d5e9c-1a24-4f80-9c6d-2e8f70b13a45","unitCode":"EA","quantity":"6.00","inventoryQuantity":"6.00","openQuantity":"0.00","condition":"DAMAGED","disposition":"SCRAP","unitPrice":"24.00","reasonCode":"damagedInTransit","sourceDocumentLineId":"5c1d9a72-0e64-4a1f-8b39-2c7f4a6e15d8","sourceDocumentLineType":"IMInventorySalesDeliveryLine","notes":"Carton crushed in transit","inspectedQuantity":"6.00","approvedQuantity":"2.00","rejectedQuantity":"4.00","inspectedDate":"2026-08-19","qualityGrade":"C","rejectionReason":"Water ingress","inspectionDetails":[{"approvalStatus":"APPROVED","inspectedQuantity":"2.00","condition":"GOOD","disposition":"RETURN_TO_STOCK"},{"approvalStatus":"REJECTED","inspectedQuantity":"4.00","condition":"DAMAGED","disposition":"SCRAP","rejectionReason":"Water ingress"}]}]}]`. |
| `items[].id` | string | yes | The unique identifier for the sales return. |
| `items[].documentNumber` | string | no | The sales return number, for example 'SR-1042'. Assigned on create and never supplied by you. |
| `items[].documentStatus` | string | yes | The status of the return. Possible values: 'DRAFT', 'OPEN', 'COMMITTED', 'RECEIVED', 'INSPECTED', 'PROCESSED', 'COMPLETED', 'CANCELLED'. |
| `items[].documentDate` | date | yes | The date the return is dated. Format YYYY-MM-DD. |
| `items[].deliveryDate` | date | no | When the goods are expected back, or came back. Format YYYY-MM-DD. |
| `items[].entityId` | string | yes | The unique identifier for the legal entity the return belongs to. See id on GET base/entities. |
| `items[].entityName` | string | no | The name of that legal entity. |
| `items[].businessPartnerId` | string | yes | The unique identifier for the customer returning the goods. Despite the name, this is a customer id. See id on GET accounting/customers/:id. |
| `items[].businessPartnerName` | string | no | The name of that customer. |
| `items[].sourceDocumentId` | string | no | The document the goods went out on, where the platform recorded one, as its own numeric id in a string. It is not an identifier this API can look up. The usable link is sourceDocumentLineId on the line. |
| `items[].sourceDocumentType` | string | no | What kind of document that was, for example 'SalesDelivery'. |
| `items[].referenceNumber` | string | no | The customer's own reference for the return, for example an RMA number. |
| `items[].trackingNumber` | string | no | The carrier's tracking number for the goods coming back. |
| `items[].returnType` | string | no | How the business classifies the return. |
| `items[].currency` | string | no | The currency every amount on the document is in. Format ISO 4217, for example 'EUR'. A return is valued in the currency it was sold in, which need not be the legal entity's functional currency. |
| `items[].totalAmount` | decimal | no | The total value of the return, in the document's currency. |
| `items[].returnFeeAmount` | decimal | no | The fee withheld across the return, in the document's currency. |
| `items[].notes` | string | no | Free text on the document. |
| `items[].createdDate` | date-time | no | The date and time the return was created, in UTC. Format YYYY-MM-DDTHH:mm:ss.sssZ. |
| `items[].lastModifiedDate` | date-time | no | The date and time the return record last changed, in UTC. Format YYYY-MM-DDTHH:mm:ss.sssZ. |
| `items[].lines` | array<object> | yes | The lines of the return, oldest first. A sales return always has at least one. |
| `items[].lines[].id` | string | yes | The unique identifier for the line. Use it in updateLines and deleteLines on PATCH inventory/sales-returns/:id. |
| `items[].lines[].itemId` | string | yes | The unique identifier for the item coming back. See id on GET inventory/items/:id. |
| `items[].lines[].itemCode` | string | no | The short code of that item. |
| `items[].lines[].itemName` | string | no | The name of that item. |
| `items[].lines[].locationId` | string | yes | The warehouse that receives the returned goods. See id on GET inventory/warehouses/:id. |
| `items[].lines[].locationCode` | string | no | The short code of that warehouse. |
| `items[].lines[].locationName` | string | no | The name of that warehouse. |
| `items[].lines[].unitId` | string | yes | The unique identifier for the unit the quantity is counted in. See id on GET inventory/unit-of-measures/:id. |
| `items[].lines[].unitCode` | string | no | The short code of that unit. |
| `items[].lines[].quantity` | decimal | yes | The quantity the customer is returning, in the line's unit. |
| `items[].lines[].inventoryQuantity` | decimal | no | The same quantity in the item's stocking unit. |
| `items[].lines[].openQuantity` | decimal | no | How much of the line has not yet been received. |
| `items[].lines[].inspectedQuantity` | decimal | no | How much of the line the inspection covered. |
| `items[].lines[].approvedQuantity` | decimal | no | How much of the line was approved back into stock. |
| `items[].lines[].rejectedQuantity` | decimal | no | How much of the line was rejected. Approved plus rejected equals inspected. |
| `items[].lines[].inspectedDate` | date | no | When the inspection took place. Format YYYY-MM-DD. |
| `items[].lines[].condition` | string | no | The condition the goods arrived in, restated by the inspection. Possible values: 'NEW', 'GOOD', 'USED', 'OPENED', 'DAMAGED', 'DEFECTIVE', 'EXPIRED', 'REFURBISHED'. |
| `items[].lines[].disposition` | string | no | What is to be done with the goods. Possible values: 'RETURN_TO_STOCK', 'RETURN_TO_VENDOR', 'SCRAP', 'DONATE', 'REPAIR', 'REWORK', 'CREDIT_ONLY'. |
| `items[].lines[].qualityGrade` | string | no | The grade assigned at inspection. |
| `items[].lines[].inspectionNotes` | string | no | Free text from the inspector. |
| `items[].lines[].rejectionReason` | string | no | Why the rejected portion was rejected. |
| `items[].lines[].unitPrice` | decimal | no | The value of one unit, in the document's currency. |
| `items[].lines[].returnFeeAmount` | decimal | no | The fee withheld on this line, in the document's currency. |
| `items[].lines[].reasonCode` | string | no | The customer-facing reason for the return, for example 'defectiveItem'. Reporting only, it does not affect how the return is processed. |
| `items[].lines[].reasonCodeId` | string | no | The unique identifier for an internal reason code, where one was set. See id on GET inventory/reason-codes/:id. |
| `items[].lines[].sourceDocumentLineId` | string | no | The shipment line the goods went out on, where the return cites one. It is a line's id on GET inventory/shipments/:id. |
| `items[].lines[].sourceDocumentLineType` | any | no | What kind of document line that was. One of: `"IMInventorySalesOrderLine"`, `"IMInventorySalesDeliveryLine"`, `"IMSalesOrderLine"`, `"IMInventoryPurchaseReturnLine"`, `"IMInventorySalesReturnLine"`, `"IMWarehouseTransferLine"`, `"IMInventoryDecreaseLine"`, `"IMInventoryIncreaseLine"`, `"IMInventoryRevaluationLine"`, `"IMInventoryTransferLine"`, `"IMInventoryAdjustmentLine"`, `"IMInventoryCountLine"`, `"IMInventoryPutAwayTask"`, `"IMInventoryPurchaseReturnReversal"`, `"PurchaseOrderLine"`, `"IMLandedCostAllocationLine"`, `"SalesOrderProductItem"`, `"IMWarehouseTransferOrderLine"`, `"VendorBillItemBase"`, `"InvPurchaseDeliveryLine"`. |
| `items[].lines[].notes` | string | no | Free text on the line. |
| `items[].lines[].batches` | array<object> | no | The batches coming back on this line, for a batch-tracked item. Absent when the item is not batch-tracked. |
| `items[].lines[].batches[].batchNumberId` | string | no | The unique identifier for the batch record. |
| `items[].lines[].batches[].batchNumber` | string | yes | The batch number as printed. |
| `items[].lines[].batches[].expirationDate` | date | no | The expiration date of the lot. Format YYYY-MM-DD. |
| `items[].lines[].batches[].quantity` | decimal | yes | The quantity of this batch coming back, in the item's inventory unit. |
| `items[].lines[].batches[].inventoryQuantity` | decimal | no | The same quantity in the item's stocking unit. |
| `items[].lines[].batches[].openQuantity` | decimal | no | How much of this batch has not yet been received. |
| `items[].lines[].batches[].unitCost` | decimal | no | The cost of one unit of this batch, in the document's currency. |
| `items[].lines[].serials` | array<object> | no | The serialized units coming back, one entry per unit. Absent when the item is not serialized. |
| `items[].lines[].serials[].serialNumberId` | string | no | The unique identifier for the serial record. |
| `items[].lines[].serials[].serialNumber` | string | yes | The serial number as stamped on the unit. |
| `items[].lines[].serials[].openQuantity` | decimal | no | How much of this unit is still outstanding, one or zero. |
| `items[].lines[].serials[].unitCost` | decimal | no | The cost of this unit, in the document's currency. |
| `items[].lines[].binLocations` | array<object> | no | The bins the goods go into, in a bin-tracked warehouse. One flat array. An entry naming a batchNumber or serialNumber belongs to that batch or unit, and one naming neither belongs to the line. |
| `items[].lines[].binLocations[].binLocationId` | string | yes | The unique identifier for the bin the goods go into. See id on GET inventory/bins/:id. |
| `items[].lines[].binLocations[].binLocationCode` | string | no | The short code of that bin. |
| `items[].lines[].binLocations[].quantity` | decimal | yes | The quantity going into this bin, in the item's inventory unit. |
| `items[].lines[].binLocations[].inventoryQuantity` | decimal | no | The same quantity in the item's stocking unit. |
| `items[].lines[].binLocations[].batchNumber` | string | no | Set when this bin entry belongs to one of the line's batches, naming it. |
| `items[].lines[].binLocations[].serialNumber` | string | no | Set when this bin entry belongs to one of the line's serialized units, naming it. |
| `items[].lines[].inspectionDetails` | array<object> | no | What the inspection found, broken down by batch or unit. Absent before the inspection runs. The line has the totals and these give the detail. |
| `items[].lines[].inspectionDetails[].approvalStatus` | string | yes | What was decided about this portion, recorded as given. |
| `items[].lines[].inspectionDetails[].inspectedQuantity` | decimal | yes | How much this finding covers. |
| `items[].lines[].inspectionDetails[].condition` | string | no | The condition of this portion. Possible values: 'NEW', 'GOOD', 'USED', 'OPENED', 'DAMAGED', 'DEFECTIVE', 'EXPIRED', 'REFURBISHED'. |
| `items[].lines[].inspectionDetails[].disposition` | string | no | What is to be done with this portion. Possible values: 'RETURN_TO_STOCK', 'RETURN_TO_VENDOR', 'SCRAP', 'DONATE', 'REPAIR', 'REWORK', 'CREDIT_ONLY'. |
| `items[].lines[].inspectionDetails[].qualityGrade` | string | no | The grade assigned at inspection, where the business uses one. |
| `items[].lines[].inspectionDetails[].inspectionNotes` | string | no | Free text from the inspector. |
| `items[].lines[].inspectionDetails[].rejectionReason` | string | no | Why this portion was rejected, where it was. |
| `items[].lines[].inspectionDetails[].batchNumber` | string | no | The batch this finding is about, where it is about one. |
| `items[].lines[].inspectionDetails[].serialNumber` | string | no | The serialized unit this finding is about, where it is about one. |
| `pagination` | object | yes | The pagination cursor for this page. Example: `{"hasMore":false}`. |
| `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 results remain beyond this page. |

```json
{
  "data": {
    "items": [
      {
        "id": "5e9b0c74-1a26-4d83-b5f0-73c8e2a91d46",
        "documentNumber": "SR-1042",
        "documentStatus": "INSPECTED",
        "documentDate": "2026-08-14",
        "deliveryDate": "2026-08-18",
        "entityId": "1a9c4e70-38b5-4d26-9f01-7c2e5b8a6d43",
        "entityName": "Acme Netherlands B.V.",
        "businessPartnerId": "c73f2b81-5d94-4e60-a812-0f9b6d3e45c7",
        "businessPartnerName": "Bakker Retail B.V.",
        "sourceDocumentId": "55120",
        "sourceDocumentType": "SalesDelivery",
        "referenceNumber": "RMA-2026-0087",
        "trackingNumber": "3SABCD1234567",
        "currency": "EUR",
        "totalAmount": "144.00",
        "returnFeeAmount": "0.00",
        "notes": "Customer reports transit damage",
        "createdDate": "2026-08-14T08:30:00.000Z",
        "lastModifiedDate": "2026-08-19T15:10:00.000Z",
        "lines": [
          {
            "id": "8c14a6f2-3b70-4d59-9e02-6f5a1d38b47c",
            "itemId": "5f21c8b0-9d34-4a76-8e12-04b93c7de5a8",
            "itemCode": "WIDGET-01",
            "itemName": "Standard widget",
            "locationId": "e1d84c07-5b39-4a26-9f70-2c8b613ad495",
            "locationCode": "WH-01",
            "locationName": "Rotterdam Distribution Centre",
            "unitId": "3b7d5e9c-1a24-4f80-9c6d-2e8f70b13a45",
            "unitCode": "EA",
            "quantity": "6.00",
            "inventoryQuantity": "6.00",
            "openQuantity": "0.00",
            "condition": "DAMAGED",
            "disposition": "SCRAP",
            "unitPrice": "24.00",
            "reasonCode": "damagedInTransit",
            "sourceDocumentLineId": "5c1d9a72-0e64-4a1f-8b39-2c7f4a6e15d8",
            "sourceDocumentLineType": "IMInventorySalesDeliveryLine",
            "notes": "Carton crushed in transit",
            "inspectedQuantity": "6.00",
            "approvedQuantity": "2.00",
            "rejectedQuantity": "4.00",
            "inspectedDate": "2026-08-19",
            "qualityGrade": "C",
            "rejectionReason": "Water ingress",
            "inspectionDetails": [
              {
                "approvalStatus": "APPROVED",
                "inspectedQuantity": "2.00",
                "condition": "GOOD",
                "disposition": "RETURN_TO_STOCK"
              },
              {
                "approvalStatus": "REJECTED",
                "inspectedQuantity": "4.00",
                "condition": "DAMAGED",
                "disposition": "SCRAP",
                "rejectionReason": "Water ingress"
              }
            ]
          }
        ]
      }
    ],
    "pagination": {
      "hasMore": false
    }
  },
  "diagnostics": [
    {
      "code": "<code>",
      "message": "<message>",
      "severity": "error",
      "path": [
        "<path>"
      ],
      "details": "<details>"
    }
  ]
}
```

## 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
