Find contacts using filters

ZoomInfo's GTM Data API helps you identify the right prospects through targeted search and enrichment. In this tutorial, you'll learn how to "find Marketing Directors at Software companies headquartered in California".

Credits Usage: Lookup and Search requests do not consume credits. Credits are only charged when you enrich a contact, and only the first time that contact is enriched.

This workflow uses four Data API v1 endpoints in the recommended sequence to build a targeted contact list.

  • Lookup: Resolves valid values for industries, states, management-levels, and job-functions.
  • Search Contacts: Finds Marketing Directors at Software companies in California and returns matching personIds with a match score.
  • Enrich Contacts: Retrieves verified contact details, including business email and phone, for the selected contactId.
flowchart LR
    A["Lookup
    Resolve valid filter values"]
    -->
    B["Search Contacts
    Find matching contacts"]
    -->
    C["Enrich Contacts
    Retrieve verified details"]

cURL Request

Step 1: Resolve filter with Lookup

Endpoint: GET /data/v1/lookup/{fieldName}

fieldName is a path parameter. For this scenario you need four fields: industries, states, management-levels, and job-functions.

Example: Resolve the management level

curl --request GET \
     --url 'https://api.zoominfo.com/gtm/data/v1/lookup/management-levels' \
     --header 'accept: application/vnd.api+json' \
     --header 'authorization: Bearer <access_token>'
{
"data": [
    { "type": "ManagementLevel", "id": "Director", "attributes": { "name": "Director" } },
    { "type": "ManagementLevel", "id": "VP Level Exec", "attributes": { "name": "VP Level Exec" } },
    { "type": "ManagementLevel", "id": "C Level Exec", "attributes": { "name": "C Level Exec" } }
  ]
}

Step 2: Search Contacts Using Lookup Results

Endpoint: POST /data/v1/contacts/search

This is the key thing to know about this endpoint: you don't need to search companies first. Search Contacts accepts company-level filters (industryCodes, state, metroRegion, employeeCount, revenue, companyName, etc.) in the exact same request as person-level filters (managementLevel, jobFunction, jobTitle). ZoomInfo matches both sides internally in one call — you just pass every filter you have.

This call is free and returns only match hints (hasEmail, hasDirectPhone, etc.) — no actual email addresses or phone numbers yet.

curl --request POST \
     --url 'https://api.zoominfo.com/gtm/data/v1/contacts/search?page%5Bnumber%5D=1&page%5Bsize%5D=25&sort=-contactAccuracyScore' \
     --header 'accept: application/vnd.api+json' \
     --header 'content-type: application/vnd.api+json' \
     --header 'authorization: Bearer <access_token>' \
     --data '
{
  "data": {
    "type": "ContactSearch",
    "attributes": {
      "industryCodes": "Computer Software",
      "state": "California",
      "locationSearchType": "HQ",
      "managementLevel": "Director",
      "jobFunction": "Marketing",
      "primaryIndustriesOnly": true,
      "contactAccuracyScoreMin": "80",
      "requiredFields": "email,phone"
    }
  }
}'
{
  "data": [
    {
      "type": "Contact",
      "id": "4191419698",
      "attributes": {
        "firstName": "Jordan",
        "lastName": "Reyes",
        "jobTitle": "Director of Marketing",
        "contactAccuracyScore": 95,
        "hasEmail": true,
        "hasDirectPhone": false,
        "hasMobilePhone": true,
        "company": {
          "id": 346572700,
          "name": "Acme Software Inc"
        }
      }
    }
  ],
  "meta": {
    "page": { "number": 1, "total": 1 },
    "totalResults": 14
  }
}

Collect id (contactId) for every contact you want full detail on, that's the input to Step 3.

Step 3: Enrich the contacts returned by the search

Endpoint: POST /data/v1/contacts/enrich

This is the only step in the workflow that charges credits — one per record, unless the record is already under management in your org's 12-month window. Enrich up to 25 records per call.

curl --request POST \
     --url 'https://api.zoominfo.com/gtm/data/v1/contacts/enrich' \
     --header 'accept: application/vnd.api+json' \
     --header 'content-type: application/vnd.api+json' \
     --header 'authorization: Bearer <access_token>' \
     --data '
{
  "data": [
    { "type": "ContactEnrich", "attributes": { "personId": "4191419698" } },
    { "type": "ContactEnrich", "attributes": { "personId": "4191419712" } }
  ],
  "outputFields": [
    "firstName", "lastName", "jobTitle", "managementLevel",
    "email", "phone", "mobilePhone", "companyName", "contactAccuracyScore"
  ],
  "requiredFields": ["email"]
}'
{
  "data": [
    {
      "type": "Contact",
      "id": "4191419698",
      "attributes": {
        "firstName": "Jordan",
        "lastName": "Reyes",
        "jobTitle": "Director of Marketing",
        "managementLevel": ["Director"],
        "email": "[email protected]",
        "phone": "+1-650-555-0142",
        "mobilePhone": "+1-650-555-0198",
        "company": { "id": 346572700, "name": "Acme Software Inc" },
        "contactAccuracyScore": 95
      },
      "meta": {
        "input": { "personId": 4191419698 },
        "matchStatus": "FULL_MATCH"
      }
    },
    {
      "id": "4191419712",
      "type": "Contact",
      "attributes": {},
      "meta": {
        "input": { "personId": 4191419712 },
        "matchStatus": "NO_MATCH"
      }
    }
  ]
}

Error Handling

StatusCodeMessageWhat it means here
400PFAPI0006Input parameter '[parameter]' is invalidUsually means a value like industryCodes or managementLevel didn't come from Lookup. Re-run Step 1 and use the exact returned value.
400PFAPI0004Missing required inputs...Search or Enrich body didn't include enough identifying fields.
401ZI0001Token invalid / expiredRefresh your OAuth token and retry.
403ZI0003You do not have access to this endpointYour package doesn't include this field/endpoint — contact your ZoomInfo Account Manager.
429ZI0004Rate limit exceededBack off exponentially and retry.

Full reference: error handling.

Rate Limits

Default: 25 requests/second. Premium add-on: 30/sec. Premium+: 35/sec. All 429/5xx responses should be retried with exponential backoff. See rate limits.


Did this page help you?