External API docs

Build a company list and find owner contacts

Follow one complete workflow from a business search to owner and decision-maker emails and phone numbers.

Workflow at a glance

The search and people APIs do not connect automatically. You take the company domain from each search result and send it to the contact search.

1Search businesses
2Prepare domains
3Start contact search
4Wait for completion
5Get task IDs
6Read contacts

Before you start

  • Keep your API key in server-side code or a secret manager.
  • Choose the business type and location you want to search.
  • Decide which role you want, such as owner or managing partner.

Authentication. We recommend sending your API key as Authorization: Bearer <your_api_key>. If your current integration already uses X-API-Key: <your_api_key>, it will continue to work.

1

Search for businesses

This example searches for cardiology clinics across the United States and keeps businesses with a valid website. A valid website is useful because the next step needs a company domain.

cURL
curl --request POST \
  --url https://api.openmart.ai/api/v1/search \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <your_api_key>' \
  --header 'Content-Type: application/json' \
  --data '{
    "query": "cardiology clinics",
    "location": [{"country": "US"}],
    "has_website": true,
    "has_valid_website": true,
    "limit": 100,
    "estimate_total": false
  }'

Response example

JSON
[
  {
    "id": "clinic-001",
    "content": {
      "business_name": "HeartCare Cardiology",
      "root_domain": "heartcarecardiology.com",
      "city": "Austin",
      "state": "Texas",
      "country": "US"
    },
    "cursor": [24.26, "clinic-001"]
  }
]

Need more than one page? Copy the last result's cursor into the next search request. Continue until no records are returned. For broad national coverage, you can also search one state at a time and combine the results.

See all search filters and pagination options
2

Prepare the companies for contact enrichment

Keep only results with a non-empty domain. Normalize and deduplicate the domains, then create one contact-search item per company.

From search result
content.root_domain
Send to find_people
domain
Why it matters
Identifies the company. Remove https://, paths, and www.
From search result
content.business_name
Send to find_people
company_name
Why it matters
Helps distinguish companies with similar or shared domains.
From search result
id
Send to find_people
tracking_id
Why it matters
Connects each contact result back to the original business.

Contact-search request body

JSON
[
  {
    "domain": "heartcarecardiology.com",
    "company_name": "HeartCare Cardiology",
    "title": "Owner or decision maker",
    "max_k": 3,
    "info_access": ["EMAIL", "PHONE"],
    "tracking_id": "clinic-001"
  }
]
  • Send a domain such as example.com, not an email address or full website URL.
  • Each batch can contain 1–100 companies.
  • max_k can be 1–8 contacts per company.
  • Use EMAIL, PHONE, or both in info_access.
Optional: build the first 100 tasks with jq
Save the search array as search-results.json, then run:
Shell
jq '[
  .[]
  | select((.content.root_domain // "") != "")
  | {
      domain: (
        .content.root_domain
        | ascii_downcase
        | sub("^www\\."; "")
      ),
      company_name: (
        .content.business_name
        // .content.store_name
        // .content.root_domain
      ),
      title: "Owner or decision maker",
      max_k: 3,
      info_access: ["EMAIL", "PHONE"],
      tracking_id: (.id | tostring)
    }
]
| unique_by(.domain)
| .[:100]' search-results.json > owner-request.json
3

Start owner contact enrichment

Submit the prepared array to find_people. The request starts a background job and returns a batch_id. Allow at least 60 seconds for this request to return.

cURL
curl --request POST \
  --max-time 90 \
  --url https://api.openmart.ai/api/v1/task/batch/find_people \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <your_api_key>' \
  --header 'Content-Type: application/json' \
  --data '[
    {
      "domain": "heartcarecardiology.com",
      "company_name": "HeartCare Cardiology",
      "title": "Owner or decision maker",
      "max_k": 3,
      "info_access": ["EMAIL", "PHONE"],
      "tracking_id": "clinic-001"
    }
  ]'

Response example

JSON
{
  "batch_id": "183219bc-066e-4641-9d6f-48205b7fbada",
  "submit_for": "find_people",
  "status": {
    "processing": 1,
    "completed": 0,
    "errored": 0,
    "total": 1,
    "batch_ready": false
  }
}
4

Wait until the batch is ready

Replace <batch_id> with the ID from the previous response. Check about every 10 seconds until batch_ready is true. Stop after eight minutes and investigate if it never becomes ready.

cURL
curl --request GET \
  --url https://api.openmart.ai/api/v1/task/batch/<batch_id>/status \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <your_api_key>'
JSON
{
  "processing": 0,
  "completed": 1,
  "errored": 0,
  "total": 1,
  "batch_ready": true
}

Review errored as well as completed. A ready batch can contain both successful and failed tasks.

5

Get completed task IDs

Each company in the batch has its own task. Retrieve the completed task IDs, then fetch every task result.

cURL
curl --request GET \
  --url https://api.openmart.ai/api/v1/task/batch/<batch_id>/task_ids?status=COMPLETED \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <your_api_key>'
JSON
[
  "2fc8b627-1111-2222-3333-123456789abc"
]
6

Retrieve emails and phone numbers

Call the task endpoint once for every completed task ID. The original business ID returns as tracking_id, so you can attach the people to the correct business record.

cURL
curl --request GET \
  --url https://api.openmart.ai/api/v1/task/<task_id> \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <your_api_key>'

Completed result

JSON
{
  "task_id": "2fc8b627-1111-2222-3333-123456789abc",
  "status": "COMPLETED",
  "tracking_id": "clinic-001",
  "data": [
    {
      "first_name": "Jane",
      "last_name": "Doe",
      "title": "Owner",
      "linkedin_url": "https://www.linkedin.com/in/jane-doe",
      "email": {
        "email": "jane@heartcarecardiology.com",
        "verified": true
      },
      "phones": [
        {
          "phone_number": "+15125550123",
          "valid": true,
          "line_type": "MOBILE",
          "confidence_grade": "A"
        }
      ]
    }
  ]
}
  • Check email.verified before using an email.
  • Check phones[].valid before using a phone number.
  • A completed task may still return no person, only an email, or only a phone number.

What to expect from company-level matching

Contact enrichment works at the company-domain level. If several locations share one website, Openmart may return an organization-level owner or decision maker instead of a separate owner for every physical location.

If “Owner or decision maker” is too broad, try a more specific title such as “Owner”, “Managing Partner”, or “Practice Administrator” in a separate request.

See every find_people parameter