Pre-Black Friday: 20% off, for as long as you stayEARLYBFon Solo and AgencyEnds Nov 28Start free

How-to guide

How to Use Hiring Signals to Time Your Sales Outreach (With a People Data API)

A hiring signal tells you who to contact. Its age tells you when. Here is the query, the clock and the output, with LeadOcean.

Get your free API key →Free to start. No credit card. 1,000 records to spend whenever you like.

Timing beats targeting once your list is decent. A hiring signal gives you a date, and the date sets when you send.

LeadOcean holds no job postings. It holds the people those postings become: current roles with start dates, career history and company headcount, refreshed monthly. This guide builds the timing layer on top of that. For the tracking side, see how to track hiring signals.

TL;DR

  • It takes about 25 minutes to size a segment, pull new leaders and assign each one a send window.
  • It spends about 30 records: 25 from one search page and a few from enrichment. Counts are free.
  • The windows are a rule of thumb, not a LeadOcean figure: recruiter build-up means act now, a new leader means wait a few weeks, then go.

Prerequisites

  • A LeadOcean API key from app.leadocean.io. Free gives 1,000 records, one-off, no card.
  • The key in your shell as $LEADOCEAN_API_KEY.
  • curl and jq.
  • One account domain to test on. The examples use acme.com.
bash
export LEADOCEAN_API_KEY="paste-your-key-here"

Step 1: Map each signal to a send window

Write the rules down before you query anything. Each signal has a different clock.

SignalWhat it meansWhen to send
Several recruiters at a small companyHiring at volume, headcount painNow, while the team is building
New VP or Director in your buyer's functionNew owner, budget resetAfter 3 to 6 weeks, once they have a view
New hire below manager levelCapacity addedLow priority, add to a nurture list
Headcount up between monthly snapshotsGrowthWithin the month, to the function head

The week counts are judgment. Test them against your own reply rates and change them.

Step 2: Size the segment for free

Count first. A people count with count=true and limit=1 as query parameters spends nothing, and meta.distinctCompanies tells you how many accounts it spans.

bash
curl -s -G https://api.leadocean.io/v1/people/search \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  --data-urlencode "title=Talent Acquisition,Recruiter" \
  --data-urlencode "jobFunction=Human Resources" \
  --data-urlencode "industry=Computer Software" \
  --data-urlencode "employeeRange=51-200" \
  --data-urlencode "country=US" \
  --data-urlencode "count=true" \
  --data-urlencode "limit=1" | jq '.meta | {total, distinctCompanies}'

Step 3: Pull new leaders at one account

Search by domain and function, then sort by start date on your side. Each row carries the current role and its start_date. The body is flat JSON and the filters are arrays.

bash
curl -s https://api.leadocean.io/v1/people/search \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": ["acme.com"],
    "jobFunction": ["Sales & Business Development"],
    "jobLevel": ["VP", "Director"],
    "limit": 25
  }' > page.json

This costs 25 records for the page. Print one row before you write a date cutoff. The person schema uses YYYY-MM-DD strings for dates.

bash
jq '.data[0].contact_data.contact_current_experiences[0]' page.json

Step 4: Confirm the hire is external

A recent start date can be a promotion. A promoted leader already has a view and vendors, so the "new owner" window does not apply. Enrich the person and read the career history. Enrich takes one of linkedin_url, email, phone or person_id.

bash
curl -s https://api.leadocean.io/v1/people/enrich \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"person_id": "PERSON_ID_FROM_STEP_3"}' \
  | jq '.data.resume_data.experiences[0:2][] | {job_title, company_name, start_date, end_date}'

If the previous role is at another company, it is an external hire. Past employers carry no company_id yet, so compare names. An enrichment that finds nobody is a 404 and costs nothing.

Step 5: Assign the send date

Do this in code so the calendar is repeatable. The script reads the page from Step 3, keeps rows with a start date, and adds a send date four weeks after it.

bash
jq -r '.data[]
  | {name: .profile_data.profile_full_name,
     role: .contact_data.contact_current_experiences[0]}
  | select(.role.start_date != null)
  | [.name, .role.job_title, .role.start_date] | @csv' page.json > leaders.csv

Then add the offset in whatever tool you use to send. Four weeks is a starting point.

Step 6: Get emails only when the date arrives

Do not pull contact data for people you will not message this month. Wait for the send date, then reveal the email on the enrich call. reveal_email defaults to false and costs no extra record.

bash
curl -s https://api.leadocean.io/v1/people/enrich \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"person_id": "PERSON_ID", "reveal_email": true}' \
  | jq '.data.contact_data | {email: .contact_emails[0]}'

Read email_status before you send. Bounced emails are not refunded.

What you get

Step 2 is free. We ran two counts on 2026-10-21 with leadocean_count_leads, both for US software companies with 51 to 200 staff.

FilterMailable peopleDistinct companiesWithout an email filter
Head of Sales, VP Sales, VP of Sales, Chief Revenue Officer (title keywords)11943
Talent Acquisition or Recruiter, in Human Resources191580

"Mailable" means verified, catch_all_valid or catch_all, the tool's default. The recruiter count is larger than the sales-leader count, which is the point: at this size a dedicated recruiter is a visible flag. Title matching is by keyword, so read a sample.

A row from Step 3 comes back in the shape below. This is the response shape from the API reference, with placeholder values.

json
{
  "success": true,
  "data": [
    {
      "profile_data": { "profile_full_name": "Jane Doe" },
      "contact_data": {
        "contact_current_experiences": [
          { "job_title": "VP of Sales", "company_name": "Acme", "start_date": "2026-09-01" }
        ]
      },
      "meta": { "source_ids": { "person_id": "PERSON_ID" } }
    }
  ],
  "meta": { "count": 1 }
}

Troubleshooting

ErrorCauseFix
401The x-api-key header is missing, or the key is wrong or revoked.Copy a fresh key from the app and reload $LEADOCEAN_API_KEY.
402Your records are spent. The Free 1,000 are a one-off allowance.Check GET /v1/account, or move to a paid plan (Solo, from $97 a month).
429More requests a second than your plan allows: 5 on Free, 200 on Agency.Wait the Retry-After seconds and retry, or slow the loop.
Empty resultsA filter value is not an exact enum string, such as Sales for Sales & Business Development.Call leadocean_list_enum_values for job_function and pass the exact string.
meta.depthCapped is trueOne search pages to 10,000 rows.Narrow the filters instead of walking the index.
Export refusedOne export is capped at 50,000 rows a request and 500,000 rows a day.Split the job across requests and days.

FAQ

How soon after a hire should I reach out?

There is no universal number. Start at 3 to 6 weeks for a new external leader, and move the offset by your reply data.

Does LeadOcean see job postings?

No. We hold people, start dates, career history and headcount. A posting feed tells you a role opened. We tell you who filled it. See signal APIs for internal sales tools for combining sources.

How fresh is the date?

The dataset is refreshed monthly, and each record carries its own fetched_at. Polling more than monthly just reruns the same answer.

Can I run the counts from Claude?

Yes. Connect Claude to https://api.leadocean.io/mcp and use leadocean_count_leads for Step 2. It is free.

Related readingLink
Buying signals for B2B outreachread the guide

Find your next hiring-signal accounts free

Free to start. No credit card. 1,000 records to spend whenever you like.

Get your free API key →