# HubSpot to LinkedIn Ads, from your terminal.

Adwarp is an open-source MCP server and CLI that turns a HubSpot list or a CRM search into a LinkedIn matched audience. It reads with a read-only private app token, and only hashed emails leave your machine.

## What you can ask.

Real requests, answered from your terminal.

### Build an audience from our HubSpot list of open deals.

```text
> Build an audience from our HubSpot list of open deals.
adwarp.audience_from_hubspot open deals list, dry run: counts and a masked sample
Contact list, matched on email. Nothing uploaded yet.
adwarp.audience_from_hubspot same list: contact list
Only the email hashes uploaded. Matching now, ready in up to 48 hours.
```

### Preview a HubSpot list before it uploads.

```text
$ npx adwarp audience from-hubspot --dry-run -n "Open deals" --list 123
every member of the list read, with a read-only token
records read, valid and skipped, with the reason for each skip
5 cleaned rows, emails masked next to their SHA-256 hashes
Nothing uploaded. Run it again without --dry-run to upload.
```

### Target our marketing qualified leads from HubSpot.

```text
> Target our marketing qualified leads from HubSpot.
adwarp.audience_from_hubspot lifecyclestage EQ marketingqualifiedlead: contact list
Emails hashed with SHA-256 before upload
Matching now. I'll check when it clears 300 members.
```

### Build a company audience from our largest HubSpot accounts.

```text
> Build a company audience from our largest HubSpot accounts.
adwarp.audience_from_hubspot companies, annualrevenue GT 10000000: company list
Company names and websites uploaded, no emails
Matching now. Ready for account-based ads in up to 48 hours.
```

## How it works.

1. Create a private app. In HubSpot, create a private app with 3 read-only scopes: contacts, companies and lists.
2. Save the token. Put its token in ~/.adwarp/hubspot.json or the ADWARP_HUBSPOT_TOKEN variable, on your machine.
3. Ask or run it. Name a HubSpot list or describe the records. Adwarp previews first, then hashes the emails and uploads.

## Why it gets better results.

### Current on launch day

Audiences come straight from the lists you keep in HubSpot, so they match your pipeline the day you launch.

### No export step

No list export, no CSV cleanup and no file left in your downloads folder.

### Read-only by design

The token only needs read scopes, and Adwarp never writes to HubSpot.

## Questions, answered.

### Is my data sent anywhere?

Only to LinkedIn. Adwarp reads HubSpot on your machine, and for contacts it uploads only SHA-256 hashes of the emails. Company lists upload names and websites.

### Can I see what will upload first?

Yes. A dry run reads HubSpot and shows the counts and 5 cleaned rows, with emails masked, and uploads nothing.

### Does it keep the audience in sync?

Not on its own. Each run builds a fresh audience, so rerun it on a schedule, with cron or a scheduled agent, and swap the new one into targeting.

### Does it work on the hosted endpoint?

No. A token stored on a shared server would let any caller read that HubSpot account, so it runs through the local MCP server or the CLI.

### Which HubSpot scopes does it need?

3 read-only scopes on a private app: crm.objects.contacts.read, crm.objects.companies.read and crm.lists.read. Adwarp only reads, and never writes to HubSpot.

In HubSpot, go to Development, then Legacy apps, and create a private app. Creating one takes a super admin. On the Scopes tab, add these 3 and no others, then copy the token from the Auth tab.

| Scope | What it reads |
| --- | --- |
| crm.objects.contacts.read | Contact emails |
| crm.objects.companies.read | Company names and domains |
| crm.lists.read | The members of a list |

~/.adwarp/hubspot.json:

```text
{ "accessToken": "your-private-app-token" }
```

terminal:

```text
chmod 600 ~/.adwarp/hubspot.json
```

### Can I build an audience from a list or a search?

Either: a list's members, or a search with up to 6 property filters that all match.

A list builds the audience its members make up, contacts or companies. A search builds a contact audience unless you pass -t company. Each --filter is property:operator:value, with the property's internal name in HubSpot.

terminal:

```text
npx adwarp audience from-hubspot -n "Open deals" --list 123 --dry-run

npx adwarp audience from-hubspot -n "Marketing qualified leads" \
  --filter lifecyclestage:EQ:marketingqualifiedlead \
  --filter "email:CONTAINS_TOKEN:*@acme.com" --dry-run

npx adwarp audience from-hubspot -n "Large accounts" -t company \
  --filter annualrevenue:GT:10000000 --dry-run
```

### Which lists are worth building?

Open deals, marketing qualified leads, customers and target accounts.

| List | What it's for |
| --- | --- |
| Open deals | Reach the buying group while the deal is open |
| Marketing qualified leads | Keep warm leads seeing your ads |
| Customers | Exclude them from prospecting campaigns |
| Target accounts | Feed 1:1 account-based ads as a company list |

### Which tools and commands does it use?

3 MCP tools and 3 CLI commands, with what each one does.

| Tool | What it does |
| --- | --- |
| `audience_from_hubspot` | Build a matched audience from a HubSpot list or search |
| `get_audience_status` | Check how the list is matching |
| `update_campaign` | Swap a fresh audience into an ad group's targeting |

CLI:

```bash
npx adwarp audience from-hubspot -n <name> --list <id> --dry-run
npx adwarp audience from-hubspot -n <name> --filter <prop>:<op>:<value> -t contact|company
npx adwarp audience status <segmentId>
```

### What are the limits?

6 things to know before you start.

- Runs locally through the MCP server or the CLI, not on the hosted endpoint.
- A search reads at most 10,000 records. For more, save them as a HubSpot list and use --list.
- Up to 6 filters per search, and every one must match. For OR logic, build a list in HubSpot.
- Contacts match on their primary email only.
- Each run creates a new audience, and the change journal doesn't record audience creation.
- LinkedIn needs about 300 matched members before an audience serves, and uploads need its Audiences product on your developer app.

## Related

- [Salesforce audiences](https://adwarp.dev/integrations/salesforce): Build an audience from a SOQL query
- [Audiences](https://adwarp.dev/linkedin-ads/audiences): Size before you spend
- [Account-based ads](https://adwarp.dev/linkedin-ads/abm): 1 audience per target account

Unofficial. Not affiliated with or endorsed by LinkedIn or Google.

Canonical page: https://adwarp.dev/integrations/hubspot
Last updated: 2026-10-18
