# Search Leads (v2)

Search leads using structured filters and an optional text query. Each result uses the same response shape as Get Lead by ID, except `duplicatedConnections` is omitted from search results.

#### Authentication

Pass your customer-managed API key in the `Authorization` header.

`Authorization: <your-api-key>`

If you are using an OAuth2 token instead:

`Authorization: Bearer <oauth2-token>`

#### Endpoint

`POST https://api.popl.co/api/pub/v2/leads/search`

#### Request Body

```json
{
  "filters": {
    "assignedMemberIds": [111, 222],
    "startTime": "2024-01-01T00:00:00+00:00",
    "endTime": "2024-12-31T23:59:59+00:00",
    "tagIds": [12, 15],
    "campaignIds": [101],
    "leadSource": ["QR_CODE_SCAN", "APP_TO_APP"],
    "exported": false,
    "leadEntries": "single",
    "hasEmail": true
  },
  "query": [
    {
      "fields": ["firstName", "lastName"],
      "value": "john",
      "match": "FUZZY"
    }
  ],
  "sort": {
    "field": "timestamp",
    "direction": "DESC"
  },
  "cursor": null,
  "includeDefaultLeads": true
}
```

#### Request Parameters

* `filters` is required. Exactly one of these scope filters must be provided: `assignedMemberIds`, `subteamIds`, or `teamId`
* Optional filters: `startTime`, `endTime`, `tagIds`, `campaignIds`, `leadSource`, `exported`, `leadEntries`, `hasEmail`
* `query` is an optional array of text search clauses
* `query.fields` must use `camelCase`, such as `firstName`, `lastName`, `companyName`
* `query.match` can be `EXACT` or `FUZZY`
* `sort.field` is currently only `timestamp`
* `sort.direction` can be `ASC` or `DESC`
* `cursor` is an opaque pagination cursor
* `includeDefaultLeads` defaults to `true`

#### Response

```json
{
  "data": {
    "leads": [
      {
        "leadId": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
        "legacyLeadId": "1547",
        "assignedMembers": [4822],
        "systemFields": {
          "leadId": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
          "legacyLeadId": "1547",
          "ownerId": "owner-uuid-1",
          "captureDatetime": "2024-01-15T10:30:00.000Z",
          "email": "john.smith@gmail.com",
          "firstName": "John",
          "lastName": "Smith",
          "fullName": "John Smith",
          "jobTitle": "Head of Strategy",
          "companyName": "ABC Industries",
          "leadSource": "QR_CODE_SCAN"
        },
        "userDefinedFields": [],
        "tags": [
          { "id": 12, "value": "VIP", "archived": false }
        ],
        "phoneNumbers": [],
        "crmExportData": [],
        "systemFieldLabelOverrides": {},
        "memberDetails": [
          {
            "memberId": 4822,
            "name": "Jason - CEO @ Popl",
            "email": "ceo@popl.co",
            "profileImageUrl": "https://cdn.popl.co/4822-icon.jpg"
          }
        ],
        "campaignDetails": { "name": "Dreamforce 2024" },
        "templateDetails": { "name": "Sales Card" },
        "calendarLinks": [],
        "calendarBookings": []
      }
    ],
    "cursor": "dGVzdC1jdXJzb3I="
  }
}
```

#### Notes

* Search results omit `duplicatedConnections`
* `assignedMemberId`, `memberData`, and `systemFields.assignedMemberId` are not returned in the pub/v2 response
* Use `assignedMembers` and `memberDetails` instead
* Pagination uses a cursor. Pass the returned `cursor` to retrieve the next page

#### Errors

* `400 INVALID_REQUEST` — Request body failed validation
* `401 TOKEN_UNAUTHORIZED` — API key is missing, invalid, or the requester lacks access
