TL;DR
- Search for CTOs with
hasPhoneset to true, then send eachperson_idtoGET /v2/people/phone. You get the direct dial and its type, not the main line. - A first batch takes about 15 minutes. It costs 1 record per CTO you pull and 1 record per phone lookup.
- Size the list first with a free count. The Free plan's 1,000 records cover roughly 500 CTOs end to end.
A CTO's phone number comes in two kinds. A direct dial rings the person or their assistant. A switchboard rings a company front desk, and the call ends at a gatekeeper.
Switchboards are easy to find and rarely useful. Direct dials are what you want, and they are what a data API returns when it holds one. LeadOcean returns the type with each number, so you can tell them apart before you dial.
Prerequisites
- A LeadOcean account on the Free plan: 1,000 records for life, no card, 5 requests a second. Start free.
- An API key in your shell:
export LEADOCEAN_API_KEY=... curlandjq.- Your own do-not-call check. LeadOcean does not answer it (see What is legal to call).
Step 1: Size the CTO list for free
Count before you spend. A count costs no records. The filter is hasPhone, so you only count CTOs we hold a number for.
Send count=true as a query parameter, with limit=1:
curl -s -X POST "https://api.leadocean.io/v1/people/search?count=true" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": ["Chief Technology Officer"],
"country": ["US"],
"hasPhone": true,
"limit": 1
}'meta.total is the answer. Add employeeRange, industry or jobLevel until the list is the size you can work.
Step 2: Pull CTOs who have a phone on file
Run the same filter as a real search. Each row you receive is 1 record. Start with 25.
curl -s -X POST "https://api.leadocean.io/v1/people/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": ["Chief Technology Officer", "CTO"],
"country": ["US"],
"employeeRange": ["1001-5000", "5001-10000"],
"hasPhone": true,
"limit": 25
}' | jq -r '.data[].meta.source_ids.person_id'The body is flat JSON and every filter is an array. Page with cursor from the previous response. Limit runs 1 to 100.
Titles are free text. Add the variants you see in your first page, such as "CTO", "Group CTO" or "VP Engineering" if you want the near neighbors.
Step 3: Fetch the direct dial
Each search row carries its id at meta.source_ids.person_id. Send it to the phone endpoint. It costs 1 record per call, including a call that finds nothing.
curl -s -G "https://api.leadocean.io/v2/people/phone" \
--data-urlencode "person_id=1234567" \
-H "x-api-key: $LEADOCEAN_API_KEY"Because Step 2 filtered on hasPhone, most calls find a number. That is the point of the filter: you do not pay for empty answers.
Prefer chat to code? The MCP tool leadocean_find_phone does the same lookup. See the Find Phone Number skill.
Step 4: Loop it over the list
At scale, script Steps 2 and 3 together. Stay under your plan's rate limit: 5 requests a second on Free, 200 on Agency.
curl -s -X POST "https://api.leadocean.io/v1/people/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" -H "Content-Type: application/json" \
-d '{"title":["Chief Technology Officer"],"country":["US"],"hasPhone":true,"limit":25}' \
| jq -r '.data[].meta.source_ids.person_id' \
| while read id; do
curl -s -G "https://api.leadocean.io/v2/people/phone" \
--data-urlencode "person_id=$id" \
-H "x-api-key: $LEADOCEAN_API_KEY" >> cto_phones.jsonl
echo >> cto_phones.jsonl
sleep 0.25
doneFor thousands of rows, use a bulk CSV export instead of a loop. POST /v1/exports takes up to 50,000 rows a request and 500,000 a day, and phones come as phone_N_number columns. Bulk CSV export is not on Free. It is included on Solo ($97 a month), and Agency ($497 a month) allows 50k rows a file. You can also build the export in the app at app.leadocean.io, which shows the record price before you download.
What you get
A free count on 2026-10-21 for CTOs in the US, titled "Chief Technology Officer":
| Filter | Total |
|---|---|
title, country US, hasPhone true | 73,563 |
title, country US, hasEmail true | 84,066 |
These are people with a phone number on file, or an email on file. They are not mailable counts and not call-ready counts. The two lists overlap.
Response shape from the API reference for one phone lookup, with placeholder values:
{
"success": true,
"data": {
"person_id": "1234567",
"found": true,
"phones": [ { "phone": "+14155550133", "type": "mobile" } ],
"best": { "phone": "+14155550133", "type": "mobile" }
}
}type is the source's own label, such as mobile, direct or office. Treat an unfamiliar value as unknown. Read best first.
Direct dial or switchboard
Call the direct dial first. Use the switchboard only when no direct number exists.
- Direct or mobile: rings the CTO or their assistant. Best answer rate. Highest care about when and why you call.
- Office: often a desk line behind a company system. Fine for business hours.
- Main line: a switchboard. You ask for the CTO by name and hope the gatekeeper connects you.
CTOs at small companies often pick up their own line. At larger ones they are screened. Pair the call with an email so the call has context. For the same method on another role, see how to find a VP of Sales phone number.
What is legal to call
This is not legal advice. Rules depend on the country the CTO sits in and on whether the number is a mobile or a business line.
- Check the number against your own do-not-call lists before you dial. LeadOcean does not return a do-not-call status. The v2 phone response has no
dncfield, and its absence is not clearance. - Rules for cold calls to mobiles are stricter than for business lines in many countries. Look up the rule for each country on your list.
- Keep a record of where each number came from and when you called.
- Honor an opt-out the first time you hear it.
Ask your counsel before you run a campaign in a new country.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key. | Re-export $LEADOCEAN_API_KEY from the app's API keys page. |
| 402 | The plan's records are spent. Free is 1,000, once. | Check GET /v1/account, then move to a paid plan. |
| 429 | Above the plan's rate limit: 5 a second on Free, 200 on Agency. | Slow the loop and honor Retry-After. |
| 404 | We hold nothing for that person_id. | No charge. Skip the row. |
| Empty results | A value in the filter is not an exact match. | Check leadocean_list_enum_values for job_level and country. |
| Export refused | Over 50,000 rows a request or 500,000 a day, or on the Free plan. | Split the export, or move to a plan with bulk CSV. |
FAQ
Can I find a CTO's phone number by name and company?
No. There is no name lookup. Search by title and company domain first, then send the person_id to the phone endpoint.
Do I pay when a lookup finds no number?
On the v2 phone endpoint, yes: a miss costs 1 record. A 404 costs nothing. Filter with hasPhone in search to avoid paying for empty answers.
How many CTOs can I look up on the Free plan?
Each CTO costs 1 record to pull and 1 for the phone, so 1,000 records covers about 500 people.
Does LeadOcean return a CTO's mobile number?
It returns the types it holds: mobile, direct and office. Not every CTO has a mobile on file. Read the type on each number.
Where do I see all phone options?
The Find Phone Number enrichment page covers the endpoint, the MCP tool and the limits. Prices are on the pricing page.
Find your first CTO phone number free
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →