> ## Documentation Index
> Fetch the complete documentation index at: https://help.hoopai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Opportunities Search API

> Advanced filtering, sorting, and pagination for searching opportunities in the HoopAI platform.

<Note>
  Due to the complexity of advanced filtering, updates may take a few seconds to appear in search results.
</Note>

The Opportunities Search API lets you search for opportunities using extensive filtering, sorting, and pagination options.

## Endpoint

```
POST /opportunities/search
```

***

## Request body

| Parameter                          | Type    | Required | Description                                                                   | Limit        |
| ---------------------------------- | ------- | -------- | ----------------------------------------------------------------------------- | ------------ |
| `locationId`                       | string  | Yes      | Location ID to search within.                                                 | —            |
| `page`                             | number  | No       | Page number for standard pagination. Do not use with `searchAfter`.           | min: 0       |
| `limit`                            | number  | Yes      | Results per page.                                                             | 1–500        |
| `searchAfter`                      | array   | No       | Cursor for pagination beyond 10,000 records. Value returned in each response. | —            |
| `query`                            | string  | No       | Full-text search against configured searchable fields.                        | max 75 chars |
| `filters`                          | array   | No       | Filter criteria — see [Filters](#filters) below.                              | —            |
| `sort`                             | array   | No       | Sort criteria — see [Sort](#sort) below.                                      | —            |
| `additionalDetails.notes`          | boolean | No       | Include notes (`true`/`false`).                                               | —            |
| `additionalDetails.tasks`          | boolean | No       | Include tasks (`true`/`false`).                                               | —            |
| `additionalDetails.calendarEvents` | boolean | No       | Include calendar events (`true`/`false`).                                     | —            |

### Sample request

```json theme={null}
{
  "locationId": "5DP41231LkQsiKESj6rh",
  "page": 1,
  "limit": 20,
  "query": "john@example.com",
  "filters": [
    { "field": "status", "operator": "eq", "value": "open" },
    {
      "group": "OR",
      "filters": [
        { "field": "pipeline_id", "operator": "eq", "value": "bCkKGpDsyPP4peuKowkG" },
        { "field": "pipeline_stage_id", "operator": "eq", "value": "7915dedc-8f18-44d5-8bc3-77c04e994a10" }
      ]
    }
  ],
  "sort": [{ "field": "date_added", "direction": "desc" }],
  "additionalDetails": { "notes": true, "tasks": true, "calendarEvents": false }
}
```

***

## Pagination

### Standard pagination (`page` + `limit`)

* Fetches up to **10,000 records** total.
* Maximum **500 records** per request.

### Cursor-based pagination (`searchAfter` + `limit`)

* Required for more than 10,000 records.
* Use the `searchAfter` value returned in each response as the start point for the next page.
* Do **not** include `page` when using `searchAfter`.

***

## Filters

Filters can be applied individually or grouped with **AND** / **OR** logical operators. Each filter has three components:

* **Field** — the opportunity attribute to filter on.
* **Operator** — the comparison to apply.
* **Value** — the value to compare against.

### Sample filter payload

```json theme={null}
{
  "group": "AND",
  "filters": [
    {
      "group": "AND",
      "filters": [
        { "field": "status", "operator": "eq", "value": "open" },
        { "field": "monetary_value", "operator": "range", "value": { "gte": 1000, "lte": 5000 } }
      ]
    },
    {
      "group": "OR",
      "filters": [
        { "field": "assigned_to", "operator": "eq", "value": "082goXVW3lIExEQPOnd3" },
        { "field": "source", "operator": "exists" }
      ]
    }
  ]
}
```

### Supported operators

| Operator       | Definition                           | Value type              | Limit |
| -------------- | ------------------------------------ | ----------------------- | ----- |
| `eq`           | Equals                               | Number, String, Boolean | —     |
| `not_eq`       | Not equals                           | Number, String, Boolean | —     |
| `contains`     | Contains (no special characters)     | String                  | 75    |
| `not_contains` | Not contains (no special characters) | String                  | 75    |
| `exists`       | Has a value                          | — (omit value)          | —     |
| `not_exists`   | Has no value                         | — (omit value)          | —     |
| `range`        | Range with `gte`, `lte`, `gt`, `lt`  | Object                  | —     |

### Supported filter fields

#### Opportunity information

| Display name      | Field name          | Supported operators                                                |
| ----------------- | ------------------- | ------------------------------------------------------------------ |
| Opportunity ID    | `id`                | `eq`, `not_eq`                                                     |
| Opportunity Name  | `name`              | `eq`, `not_eq`, `contains`, `not_contains`, `exists`, `not_exists` |
| Monetary Value    | `monetary_value`    | `eq`, `not_eq`, `range`, `exists`, `not_exists`                    |
| Pipeline ID       | `pipeline_id`       | `eq`, `not_eq`, `exists`, `not_exists`                             |
| Pipeline Stage ID | `pipeline_stage_id` | `eq`, `not_eq`, `exists`, `not_exists`                             |
| Status            | `status`            | `eq`, `not_eq`, `exists`, `not_exists`                             |
| Lost Reason ID    | `lost_reason_id`    | `eq`, `not_eq`, `exists`, `not_exists`                             |
| Source            | `source`            | `eq`, `not_eq`, `exists`, `not_exists`                             |
| Assigned To       | `assigned_to`       | `eq`, `not_eq`, `exists`, `not_exists`                             |
| Followers         | `followers`         | `eq`, `not_eq`, `contains`, `not_contains`, `exists`, `not_exists` |

#### Contact information (on opportunity)

| Display name | Field name     | Supported operators                                                |
| ------------ | -------------- | ------------------------------------------------------------------ |
| Contact ID   | `contact_id`   | `eq`, `not_eq`, `exists`, `not_exists`                             |
| Contact Name | `contact_name` | `eq`, `not_eq`, `contains`, `not_contains`, `exists`, `not_exists` |
| Company Name | `company_name` | `eq`, `not_eq`, `contains`, `not_contains`, `exists`, `not_exists` |
| Email        | `email`        | `eq`, `not_eq`, `contains`, `not_contains`, `exists`, `not_exists` |
| Phone        | `phone`        | `eq`, `not_eq`, `contains`, `not_contains`, `exists`, `not_exists` |

#### Date fields

| Display name       | Field name                | Supported operators             |
| ------------------ | ------------------------- | ------------------------------- |
| Date Added         | `date_added`              | `range`, `exists`, `not_exists` |
| Date Updated       | `date_updated`            | `range`, `exists`, `not_exists` |
| Last Status Change | `last_status_change_date` | `range`, `exists`, `not_exists` |
| Last Stage Change  | `last_stage_change_date`  | `range`, `exists`, `not_exists` |

#### Custom fields

| Field type                                    | Field name format                      | Operators                                                          |
| --------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------ |
| Text, Large Text, Single Option, Radio, Phone | `custom_fields.{custom_field_id}`      | `eq`, `not_eq`, `contains`, `not_contains`, `exists`, `not_exists` |
| Checkbox, Multiple Options                    | `custom_fields.{custom_field_id}`      | `eq`, `not_eq`, `exists`, `not_exists`                             |
| Numerical, Monetary                           | `custom_fields.{custom_field_id}`      | `range`, `eq`, `not_eq`, `exists`, `not_exists`                    |
| Date                                          | `custom_fields.{custom_field_id}`      | `range`, `exists`, `not_exists`                                    |
| Textbox List                                  | `custom_fields.{field_id}.{option_id}` | `eq`, `not_eq`, `contains`, `not_contains`, `exists`, `not_exists` |

***

## Sort

You can combine up to 2 sort criteria.

```json theme={null}
[
  { "field": "date_added", "direction": "desc" },
  { "field": "monetary_value", "direction": "asc" }
]
```

### Supported sort fields

| Display name       | Field name                |
| ------------------ | ------------------------- |
| Date Created       | `date_added`              |
| Date Updated       | `date_updated`            |
| Opportunity Name   | `name`                    |
| Monetary Value     | `monetary_value`          |
| Last Status Change | `last_status_change_date` |
| Last Stage Change  | `last_stage_change_date`  |
