# List quotes

Operation ID: `listQuotes`

Group: CRM › Quotes

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

`GET /crm/quotes`

Read-only: Reads and returns; changes nothing.

Lists quotes, most recently created first. Only ids, enums, booleans and dates filter this endpoint. To filter by the memo text, quoteNumber or salesArrangementId, or to pass more than one value of a field, use POST crm/quotes/search. An unrecognized quoteType, status, or approvalStatus value, or an id that is not a UUID, matches nothing rather than failing. The item schema here has the quote's main fields only. GET crm/quotes/:id and POST crm/quotes/search also return the quote's priced lines.

This endpoint does not follow the standard collection rules in Pagination and querying.

- Page with `pageSize` (default 50, maximum 200, minimum 1) and `cursor`, not `page[size]` and `page[cursor]`.
- The response has the records in `data.items` and the next page's cursor in `data.pagination.nextCursor`.
- Filter with the plain query parameters listed below, such as `status`, not `filter[field][op]`.
- There is no `sort` or `fields`.

This endpoint ignores any query parameter it does not declare, and returns no error. A request that follows the standard rules therefore gets the first page, unfiltered, every time.

## 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`. |
| `quoteId` | query | string | no | Limits results to the quote with this id. |
| `quoteType` | query | string | no | Limits results to quotes of this kind. Possible values: 'new', 'upsell', 'renewal', 'changeOrder'. Omit for every kind. |
| `status` | query | string | no | Limits results to quotes in this business state. Possible values: 'created', 'underApproval', 'approved', 'underSigning', 'signed', 'completed'. Omit for every state. |
| `approvalStatus` | query | string | no | Limits results to quotes in this approval state. Possible values: 'pendingSubmission', 'pendingApproval', 'approved', 'rejected'. Omit for every state. Example: `"approved"`. |
| `isPrimary` | query | boolean | no | Limits results to primary quotes when true, or non-primary quotes when false. Pair with opportunityId to find an opportunity's primary quote. Omit for both. |
| `opportunityId` | query | string | no | Limits results to quotes of this opportunity. Omit for every opportunity. Example: `"a1c4d7e0-5b62-4c19-8e73-9f0d2a6b4c88"`. |
| `quoteDateFrom` | query | string | no | Limits results to quotes drawn up on or after this date. Format YYYY-MM-DD. Inclusive. |
| `quoteDateTo` | query | string | no | Limits results to quotes drawn up on or before this date. Format YYYY-MM-DD. Inclusive. |
| `modifiedFrom` | query | string | no | Limits results to quotes changed at or after this time, in UTC. Format YYYY-MM-DDTHH:mm:ss.sssZ. Inclusive. |
| `modifiedTo` | query | string | no | Limits results to quotes changed at or before this time, in UTC. Format YYYY-MM-DDTHH:mm:ss.sssZ. Inclusive. |
| `cursor` | query | string | no | The cursor from the previous response's data.pagination.nextCursor. Omit on the first request. |
| `pageSize` | query | number | no | The number of quotes per page. Defaults to 50, and a value above 200 is treated as 200, not rejected. Example: `50`. |

## Response

`200` Success

Under `data` (listQuotesOutput):

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | array<object> | yes | The quotes on this page, most recently created first. An empty array when nothing matches. Example: `[{"id":"3b7d5e9c-1a24-4f80-9c6d-2e8f70b13a45","quoteNumber":"QT-1042","quoteType":"new","status":"approved","approvalStatus":"approved","isPrimary":true,"quoteDate":"2026-08-01","serviceStartDate":"2026-09-01","signDate":"2026-08-14","paymentTerm":"NET30","memo":"Two-year platform subscription, renegotiated after the pilot.","needsPSACalculation":false,"currency":"USD","totalPrice":"48000.00","oneTimeDiscountAmount":"2000.00","oneTimeDiscountAllocation":"firstInvoice","opportunityId":"a1c4d7e0-5b62-4c19-8e73-9f0d2a6b4c88","opportunityName":"Northwind — platform expansion","opportunityNumber":"OPP-2291","billToAddressId":"6f9a2b1c-33d4-4a55-9e21-0b7c8d4e1f02","soldToAddressId":"6f9a2b1c-33d4-4a55-9e21-0b7c8d4e1f02","lastModifiedDate":"2026-08-14T09:12:44.000Z"}]`. |
| `items[].id` | string | yes | The unique identifier for the quote. |
| `items[].quoteNumber` | string | no | The system-generated quote number, for example 'QT-1042'. Absent while none has been assigned. |
| `items[].quoteType` | string | yes | The kind of quote. Possible values: 'new', 'upsell', 'renewal', 'changeOrder'. |
| `items[].status` | string | no | Where the quote stands in its business process. Possible values: 'created', 'underApproval', 'approved', 'underSigning', 'signed', 'completed'. Absent on a quote that has not entered the process. |
| `items[].approvalStatus` | string | no | Where the quote stands in its approval process. Possible values: 'pendingSubmission', 'pendingApproval', 'approved', 'rejected'. Absent until the approval process has run. |
| `items[].isPrimary` | boolean | yes | Whether this is the primary quote of its opportunity. |
| `items[].quoteDate` | date | yes | The date the quote was drawn up. Format YYYY-MM-DD. Product prices are validated against the opportunity's price book as of this date. |
| `items[].serviceStartDate` | date | yes | The first date products or services on this quote are delivered. Format YYYY-MM-DD. No subscription on the quote starts before it. |
| `items[].signDate` | date | no | The date the quote was signed by the customer and the legal entity. Format YYYY-MM-DD. Absent when not recorded. |
| `items[].paymentTerm` | string | yes | The code of the payment term applied to invoices created from this quote. See code on GET accounting/payment-terms. |
| `items[].memo` | string | no | A free-text memo recorded on the quote. Absent when none is set. |
| `items[].needsPSACalculation` | boolean | no | Whether the quote takes its product data from a PSA project rather than from the product catalog. |
| `items[].currency` | string | no | The currency of every amount on the quote. A quote takes the currency of its opportunity and has none of its own. Format ISO 4217, for example 'USD'. |
| `items[].totalPrice` | decimal | no | The sum of the quote's lines before tax, less any one-time discount, in the quote's currency. |
| `items[].oneTimeDiscountAmount` | decimal | no | A one-time discount applied to the whole quote, in the quote's currency. |
| `items[].oneTimeDiscountAllocation` | string | no | How oneTimeDiscountAmount is spread across the quote's invoices. Possible values: 'firstInvoice', 'alignToInvoiceFrequency', 'custom'. |
| `items[].billableTimeEstimate` | decimal | no | The estimated total of the quote's billable-time lines, in the quote's currency. |
| `items[].billableTimeCappedPrice` | decimal | no | The ceiling on the total of the quote's billable-time lines, in the quote's currency. |
| `items[].opportunityId` | string | yes | The opportunity this quote belongs to. See id on GET crm/opportunities/:id. |
| `items[].opportunityName` | string | no | The name of the opportunity this quote belongs to. Absent when the opportunity has no name. |
| `items[].opportunityNumber` | string | no | The opportunity number of the opportunity this quote belongs to, for example 'OP-1042'. Absent while none has been assigned. |
| `items[].billToAddressId` | string | no | The bill-to address on the quote, a copy the quote keeps of its own rather than the source it was copied from. There is no endpoint for it. |
| `items[].soldToAddressId` | string | no | The sold-to address on the quote, a copy the quote keeps of its own rather than the source it was copied from. There is no endpoint for it. |
| `items[].salesArrangementId` | string | no | The sales arrangement this quote is assigned to. Set on change-order quotes. There is no endpoint for it. |
| `items[].lastModifiedDate` | date-time | yes | The date and time the quote record last changed, in UTC. Format YYYY-MM-DDTHH:mm:ss.sssZ. |
| `pagination` | object | yes | The pagination details for this page. Example: `{"nextCursor":"MTA","hasMore":true}`. |
| `pagination.nextCursor` | string | no | The cursor for the next page. Pass it back as cursor. Absent on the last page. |
| `pagination.hasMore` | boolean | yes | Whether another page follows. A full page may still be the last, so branch on this. |

```json
{
  "data": {
    "items": [
      {
        "id": "3b7d5e9c-1a24-4f80-9c6d-2e8f70b13a45",
        "quoteNumber": "QT-1042",
        "quoteType": "new",
        "status": "approved",
        "approvalStatus": "approved",
        "isPrimary": true,
        "quoteDate": "2026-08-01",
        "serviceStartDate": "2026-09-01",
        "signDate": "2026-08-14",
        "paymentTerm": "NET30",
        "memo": "Two-year platform subscription, renegotiated after the pilot.",
        "needsPSACalculation": false,
        "currency": "USD",
        "totalPrice": "48000.00",
        "oneTimeDiscountAmount": "2000.00",
        "oneTimeDiscountAllocation": "firstInvoice",
        "opportunityId": "a1c4d7e0-5b62-4c19-8e73-9f0d2a6b4c88",
        "opportunityName": "Northwind — platform expansion",
        "opportunityNumber": "OPP-2291",
        "billToAddressId": "6f9a2b1c-33d4-4a55-9e21-0b7c8d4e1f02",
        "soldToAddressId": "6f9a2b1c-33d4-4a55-9e21-0b7c8d4e1f02",
        "lastModifiedDate": "2026-08-14T09:12:44.000Z"
      }
    ],
    "pagination": {
      "nextCursor": "MTA",
      "hasMore": true
    }
  },
  "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
