You get a recipe that fills the emails and phones on a Notion contact database from LeadOcean, when a row is added and again on a schedule. Notion has no LeadOcean connector, so a small script sits in the middle. It reads a row through the Notion API, calls POST /v1/people/enrich and writes the result back with PATCH /v1/pages/{page_id}. The free LeadOcean plan covers the first 1,000 records, no card.
Related: the integrations hub, Retool, Folk, Attio and pricing.
How it works
The script runs anywhere that takes a POST: a small server, a serverless function or an n8n flow. Notion's own database automations can send that POST. The Send webhook action is on paid plans and supports POST only (Notion help, September 2026).
- Get a LeadOcean key. Sign up at app.leadocean.io and copy a key from the API keys page.
- Create a Notion connection. Make an internal connection, copy its token and share your contact database with it. An unshared database returns 404.
- Add the properties. Create
LinkedIn(URL),Email(Email),Phone(Phone),Enriched at(Date) andLeadOcean status(Text). - Add the automation. On the database, add an automation that fires when a page is added and run the Send webhook action to your script. Notion sends page properties only, not page content.
- Enrich. The script sends exactly one identifier to LeadOcean: the LinkedIn URL, else the email. A 404 means nothing was found and costs nothing.
- Write back.
PATCHthe page with the new email and phone, and stampEnriched at. - Add the sweep. On a cron schedule, query the data source for rows where
Enriched atis empty and run steps 5 and 6 on each.
Notion allows 180 requests a minute per connection on most plans and 600 on Business and Enterprise. Querying a data source is capped near 3 a second. A separate per-workspace budget is shared by every connection, so other integrations can slow yours. A 429 carries Retry-After (Notion request limits, September 2026).
Dedupe rests on one property. The automation and the sweep both skip any row where Enriched at is set, and a miss is stamped too, so a 404 is never retried every night. Clear the date on a row when you want it enriched again.
Configuration
The sweep query. Notion's current API queries a data source, not a database ID, and every request carries a Notion-Version header (Notion query docs, September 2026).
curl -X POST https://api.notion.com/v1/data_sources/$NOTION_DATA_SOURCE_ID/query \
-H "Authorization: Bearer $NOTION_TOKEN" \
-H "Notion-Version: 2026-03-11" \
-H "Content-Type: application/json" \
-d '{"filter": {"property": "Enriched at", "date": {"is_empty": true}}}'The LeadOcean call, per row:
curl -X POST https://api.leadocean.io/v1/people/enrich \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"linkedin_url": "https://www.linkedin.com/in/jane-doe", "reveal_email": true}'The Notion update:
curl -X PATCH https://api.notion.com/v1/pages/$PAGE_ID \
-H "Authorization: Bearer $NOTION_TOKEN" \
-H "Notion-Version: 2026-03-11" \
-H "Content-Type: application/json" \
-d '{"properties": {"Email": {"email": "jane@acme.com"}, "Phone": {"phone_number": "+1 415 555 0133"}, "Enriched at": {"date": {"start": "2026-10-21"}}, "LeadOcean status": {"rich_text": [{"text": {"content": "verified"}}]}}}'Send one identifier per enrich call. reveal_email: true returns the addresses and phones held and costs no extra record.
Field mapping
LeadOcean fields sit under data in the response. Notion properties take typed values.
| LeadOcean field | Notion property | Note |
|---|---|---|
data.contact_data.contact_emails[].email | Email (email) | One address only. Pick verified, else catch_all_valid. |
data.contact_data.contact_phones[].phone | Phone (phone_number) | Needs reveal_email: true. Notion does not check the format. |
data.contact_data.contact_emails[].status | LeadOcean status (rich_text) | Lets you filter out risky addresses in a view. |
data.profile_data.profile_full_name | Name (title) | Write only if the title is empty. |
| LinkedIn URL you sent | LinkedIn (url) | Keep it so later sweeps match. |
| Run date | Enriched at (date) | The dedupe stamp. |
Notion email and phone properties hold a single value. Omitted properties keep their value on update, and array values replace the whole array (Notion update page, September 2026). Extra emails go in a rich_text property or a second Email 2 column.
Cost at 10,000 rows
For 10,000 rows, LeadOcean costs one plan month and Notion costs your seats plus about an hour of API time. On Free you get 1,000 records, once. For 10,000 in a month use Solo at $97, which paces at 10k enrichments every 5 hours. Misses are free.
| Item | LeadOcean Free | LeadOcean Solo |
|---|---|---|
| LeadOcean price | $0, 1,000 records for life | $97 a month |
| Rows covered | First 1,000 hits | 10,000 in one run |
| LeadOcean rate | 5 requests a second | 50 requests a second |
| Notion writes at 180 a minute | About 56 minutes for 10,000 | Same |
| Notion writes at 600 a minute | About 17 minutes for 10,000 | Same |
Notion Plus is $12 per member a month billed monthly, or $10 billed yearly. Business is $24 billed monthly, or $20 billed yearly (Notion pricing, October 2026). The Send webhook action needs a paid plan. The sweep alone works on any plan, since Notion's request limits cover all plans. Notion lists no per-row API charge. The run time above is arithmetic from the published limits, not a measured test.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Notion returns 404 on query or update | The database is not shared with the connection. | Open the database menu and add the connection. |
| Notion returns 429 | Over 180 requests a minute, or 3 queries a second. | Wait for Retry-After, then queue requests. |
| Notion returns 400 on update | Property name or type does not match the schema. | Match names exactly and send typed values. |
| LeadOcean returns 404 | No record for that person. | Stamp Enriched at, set the status to not found. It costs nothing. |
| LeadOcean returns 400 | More than one identifier, or none. | Send only the LinkedIn URL or only the email. |
| Automation stops firing | Notion pauses an automation when its webhook action fails. | Fix the script, then resume the automation by hand. |
| Same row enriched twice | Automation and sweep overlap. | Skip rows where Enriched at is set. |
FAQ
Does Notion have a native LeadOcean integration?
No. This recipe uses the Notion API, a database automation webhook and LeadOcean's REST API. Nothing here is a Notion connector.
Which LeadOcean plan fits?
Free for a test of 1,000 rows. Solo at $97 a month for one workspace. Agency at $497 a month if you enrich for clients and need 200 requests a second.
Do I need a LinkedIn URL?
It is the best input. LeadOcean also accepts an email, a phone or a person_id. There is no name plus company lookup, so search by domain first, then enrich by person_id.
Can I store past roles too?
Yes. Person enrich returns career history under resume_data: past roles with title, company and dates, plus education. Write the last employer into a Text property if your team qualifies on it. Past employers carry no company_id yet.
Enrich your Notion database with a free LeadOcean key
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →