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

How-to guide

How to build a LinkedIn Ads audience (with the LeadOcean API)

Size the audience for free, pull the list, upload it as a Matched Audience. About 20 minutes.

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

Size the segment with a free count. Pull the matching people. Upload the CSV as a Matched Audience. This guide does it with real filters and the real output of a free count run on 2026-10-21.

TL;DR

  • Build the audience in about 20 minutes: count, pull, export, upload.
  • Sizing is free. A test pull of 100 people spends 100 of your 1,000 free records.
  • Use company lists when the buyer is the account, and people lists when the buyer is a role.

Prerequisites

  • A LeadOcean API key from the free plan, exported as $LEADOCEAN_API_KEY. Free is 1,000 records for life, no card, 5 requests a second.
  • curl and jq.
  • A LinkedIn Campaign Manager account with permission to create Matched Audiences.
  • Optional: the LeadOcean MCP server, if you would rather size the audience from Claude. The tool is leadocean_count_leads.

Step 1: Pick the filters that match your ad targeting

Match the list to the offer, not to the widest audience you can find. LinkedIn already lets you target by job title and company size, so the reason to bring your own list is control: named accounts, verified contacts, and exclusions LinkedIn cannot do.

Our example: VPs and C-level marketers at US software companies with 51 to 500 employees.

Enum values are exact strings. Check them before you guess.

bash
curl -s "https://api.leadocean.io/v1/enums" \
  -H "x-api-key: $LEADOCEAN_API_KEY" | jq 'keys'

The values used below are jobLevel VP and C-Team, jobFunction Advertising & Marketing, industry Computer Software, and employeeRange 51-200 and 201-500. The MCP tool leadocean_list_enum_values resolves any of them for free.

Step 2: Size the audience before you spend anything

A count costs zero records. Send count=true as a query parameter with limit=1. The body stays flat JSON and every filter is an array.

bash
curl -s -X POST "https://api.leadocean.io/v1/people/search?count=true&limit=1" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "jobLevel": ["VP", "C-Team"],
    "jobFunction": ["Advertising & Marketing"],
    "country": ["US"],
    "industry": ["Computer Software"],
    "employeeRange": ["51-200", "201-500"]
  }' | jq '.meta'

meta.total is capped at 100,000 on this call. If you hit the cap, narrow the filters. For company-level sizing use GET /v1/companies/count, which is also free and returns breakdowns by industry, headcount band and HQ state.

Keep the size in context. LinkedIn needs at least 300 rows to accept a contact list. The list must then match 300 member accounts before an ad set can use it (LinkedIn help: contact list targeting, October 2026). A list of 46 people will not run. Widen to Director level or drop the headcount filter until the count is in the thousands.

Step 3: Pull a test page

Pull 100 people to look at the data before you export the whole audience. This spends 100 records.

bash
curl -s -X POST "https://api.leadocean.io/v1/people/search" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "jobLevel": ["VP", "C-Team"],
    "jobFunction": ["Advertising & Marketing"],
    "country": ["US"],
    "industry": ["Computer Software"],
    "employeeRange": ["51-200", "201-500"],
    "limit": 100
  }' > page1.json

jq '.meta' page1.json

To read the next page, send cursor with the value from meta.nextCursor. One search pages to 10,000 rows. When meta.depthCapped is true there is no nextCursor, so split the audience by country or headcount band instead of walking further.

Read email_status on each record before you decide what to upload. If you also mail the list, we do not refund bounces, so filter on status first.

Step 4: Export the full audience as a CSV

For anything past a test page, use an export. In the app at app.leadocean.io, open the Exports page, build the same filters, pick the columns, check the price preview, and download the CSV. The same job runs from the API with POST /v1/exports, up to 50,000 rows a request and 500,000 rows a day. Bulk CSV export is not on Free. It is included on Solo ($97 a month).

Ask for the columns LinkedIn matches on: first name, last name, email, job title and company name. Column ids come from GET /v1/exports/columns.

bash
curl -s -X POST "https://api.leadocean.io/v1/exports" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "name": "linkedin-us-software-marketing",
    "filters": {
      "jobLevel": ["VP", "C-Team"],
      "jobFunction": ["Advertising & Marketing"],
      "country": ["US"],
      "industry": ["Computer Software"],
      "employeeRange": ["51-200", "201-500"]
    },
    "limit": 5000,
    "columns": ["profile_first_name", "profile_last_name", "email_N_address",
                "current_job_title", "current_company_name"],
    "caps": { "emails": 1 }
  }'

The answer is a job id. Poll GET /v1/exports/{id} until status is done, then download the file. With one email cap the CSV header comes back as email_1_address, in column 3.

Then clean the file.

bash
awk -F, 'NR==1 || ($3 != "" && !seen[$3]++)' export.csv > linkedin-upload.csv

Change the column number if you reorder the columns. A spreadsheet works too, as long as each email appears once.

Step 5: Upload to Campaign Manager

Download the CSV template in Campaign Manager and paste your rows under its headers. LinkedIn rejects a file whose template headers were changed or removed, and the email column header must be email. It matches on email, or on first and last name plus company name. A list can take up to 48 hours to build (LinkedIn help, October 2026).

LinkedIn recommends uploading at least 10,000 email addresses so the list matches at least 300 members (same source). Compare the matched count with your file before you set a budget.

Two habits save budget:

  • Upload accounts, not people, when the offer is sold to a buying committee. Pull company domains with POST /v1/companies/search and upload a company list.
  • Refresh monthly. The dataset refreshes monthly, and each record carries its own fetched_at date. Stale lists lose match rate.

Step 6: Layer exclusions so you stop paying for the wrong people

Build a second list of people to skip. Think current customers, open opportunities and your own staff. Upload it as its own Matched Audience, then exclude it in the campaign. Export your customers from your CRM and keep the same email column.

Exclusion lists pay for themselves. Every impression spent on a customer is an impression not spent on a prospect.

What you get

This is the output of the free MCP tool leadocean_count_leads for the Step 2 filters, run on 2026-10-21. It spent zero records.

json
{
  "total": 46,
  "totalIsExact": true,
  "totalAll": 132,
  "distinctCompanies": 31,
  "distinctCompaniesIsExact": true,
  "credits": 0,
  "defaults": "Counted only addresses worth sending to (emailStatus: verified or catch_all_valid or catch_all)",
  "unsupportedFilters": []
}

Read it carefully. The 46 is a mailable count: people with a verified, catch-all-valid or catch-all email, at 31 companies. Without an email condition the same filters match 132 people (totalAll).

The company side comes from leadocean_count_companies, same date, US HQ, 51 to 500 employees, Computer Software:

json
{
  "total": 728,
  "totalIsExact": true,
  "facets": {
    "employee_range": [
      { "value": "51-200", "count": 460 },
      { "value": "201-500", "count": 268 }
    ],
    "hq_state": [
      { "value": "California", "count": 204 },
      { "value": "Massachusetts", "count": 51 },
      { "value": "New York", "count": 51 }
    ]
  },
  "credits": 0
}

The lesson is plain. There are 728 target companies but only 46 mailable VP and C-level marketers. For a LinkedIn list that is a small audience. Computer Software is also an older industry label, so add Software Development to widen. Or widen the level to Director, or upload the 728 as a company list and let LinkedIn's own targeting pick the roles. A company list also needs at least 300 rows.

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-key headerCheck $LEADOCEAN_API_KEY is exported and sent as x-api-key
429Above the plan's rate limit (5 requests a second on Free, 200 on Agency)Wait for the Retry-After seconds, then slow the loop
402Out of recordsFree is 1,000 records for life, so move to Solo ($97 a month) or Agency ($497 a month)
Empty resultsA filter value is not an exact enum stringLook it up with /v1/enums or leadocean_list_enum_values
meta.depthCapped true, no nextCursorOne search reached 10,000 rowsSplit by country or headcount band and run each slice
Export refusedOver 50,000 rows a request or 500,000 a daySplit the export into several requests

FAQ

Do I need the API, or can I use the app?

The app is enough for one list. Its Exports page has a filter builder, a column picker and a price preview, then a CSV download. Use the API when you rebuild the list on a schedule.

How big should a LinkedIn Ads audience be?

The floor is 300 matched member accounts per ad set, and LinkedIn suggests uploading at least 10,000 emails to reach it (LinkedIn help, October 2026). Count first, then decide whether to widen.

What does a lookalike audience have to do with this?

LinkedIn can build one from your uploaded list. Read the lookalike audiences glossary entry for what that means and when it helps.

Can Claude size the audience for me?

Yes. The audience sizer skill calls the free count tools and returns the numbers with the filters it used. For the wider list-building workflow see list building.

What does it cost?

Sizing is free. Pulling people spends one record per person returned. Free gives 1,000 records for life, then see pricing: Solo is $97 a month and Agency is $497 a month.

Back to the blog for more recipes.

Build your LinkedIn Ads audience from real filters, free

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

Get your free API key →