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

Dynamics 365 integration

LeadOcean + Microsoft Dynamics 365: enrich contacts on a schedule

A Power Automate flow reads contacts with a LinkedIn URL, calls POST /v1/people/enrich, and writes the email, phone and job title back to Dataverse.

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

You get a Power Automate flow that finds Dynamics 365 contacts with a LinkedIn URL and no email, asks LeadOcean for each one, and writes the result back to Dataverse. The link is one HTTP action calling POST /v1/people/enrich. It runs on a schedule, skips contacts that already have an email, and never overwrites a value you typed.

This recipe uses Power Automate and the Dataverse connector, which offers List rows and Update a row (Microsoft Learn, September 2026). LeadOcean needs a free key.

How it works

  1. Create a LeadOcean key. Sign up at app.leadocean.io/register. The free plan has 1,000 records, one-off, no card.
  2. Add a LinkedIn column to Contact. Dynamics holds no standard LinkedIn field, so add a text column such as new_linkedinurl and fill it from your list.
  3. Create a scheduled cloud flow. Add a Recurrence trigger. Daily at night suits a backlog.
  4. Add List rows on Contacts. Filter to contacts that need data, and set Top Count to 100 so each run stays small.
  5. Add an Apply to each loop with an HTTP action. POST the LinkedIn URL to LeadOcean with the x-api-key header.
  6. Gate on email status. Continue only when the first email is verified or catch_all_valid. A 404 means LeadOcean holds nothing and costs nothing.
  7. Add Update a row. Write email, phone and job title to the contact.
  8. Test on five contacts. Set Top Count to 5, run the flow once, and open each record.

Licensing: a Power Automate Premium licence covers standard, premium and custom connectors. Dynamics 365 licences include only a limited set of Power Automate capabilities, listed in Microsoft's Power Platform Licensing Guide (Microsoft Learn, October 2026). Check yours before you build.

Configuration

Set the List rows filter in OData so only blank, enrichable contacts come back. emailaddress1 is the standard email column on Contact.

text
Table name:    Contacts
Filter rows:   emailaddress1 eq null and new_linkedinurl ne null
Top Count:     100

The HTTP action sends one identifier per call. The expression in the body is Power Automate's dynamic content for the new_linkedinurl column.

text
Method:   POST
URI:      https://api.leadocean.io/v1/people/enrich
Headers:  x-api-key: <your LeadOcean key>
          content-type: application/json
Body:     {
            "linkedin_url": "@{items('Apply_to_each')?['new_linkedinurl']}",
            "reveal_email": true
          }

Store the key in an environment variable or Azure Key Vault, not in the flow text. Test the same request from a terminal first.

bash
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}'

Send exactly one identifier. Two is a 400. reveal_email costs no extra record (LeadOcean docs, September 2026). Addresses come back best first, so the first entry is the one to write:

text
first(body('HTTP')?['data']?['contact_data']?['contact_emails'])?['email']

Field mapping

The response nests data under data.contact_data. Map these into Contact columns.

LeadOcean fieldDynamics 365 columnNote
data.contact_data.contact_emails[0].emailemailaddress1Write only when the status is verified or catch_all_valid.
data.contact_data.email_statuscustom text columnKeep it. It tells you which contacts are safe to email.
data.contact_data.contact_phones[0].phonemobilephoneReturned because reveal_email is true.
data.contact_data.contact_current_experiences[0].job_titlejobtitleThe current role. Update it only if the field is blank.
data.contact_data.contact_current_experiences[0].company_domaincustom text columnUse it to match the parent account.

Dedupe: Dynamics 365 ships default duplicate detection rules for accounts and contacts, and you can add rules for other tables (Microsoft Learn, September 2026). This flow only updates existing rows, so it creates no new duplicates. Two habits keep it clean.

  • Filter on emailaddress1 eq null. A contact with an email is never touched.
  • Match by new_linkedinurl, one URL per contact. Two contacts sharing a URL will both be enriched, so clean the column first.

Cost at 10,000 rows

At 10,000 contacts, LeadOcean costs $0 for the first 1,000 records and $97 on Solo for the rest. Power Automate adds its own licence cost.

LeadOcean. A hit counts as one record. A miss is a 404 and costs nothing. The Free plan covers 1,000 records, once. Solo is $97 a month with no per-record price and a pace of 10k enrichments every 5 hours, so 10,000 rows fit in one run (LeadOcean pricing). The Free rate limit is 5 requests a second, so keep the loop's concurrency low.

Dynamics 365 and Power Automate. Power Automate Premium is $15 per user a month, paid yearly; the page shows no monthly-billed rate (Microsoft, October 2026). Dataverse reads and updates count toward Power Platform request limits. A licensed Dynamics 365 Sales Enterprise user gets 40,000 requests per 24 hours (Microsoft Learn, September 2026). A run that lists, updates and calls out for 10,000 rows is roughly 20,000 or more requests, so batch over two nights on a small tenant.

Item10,000 contacts
LeadOcean on FreeFirst 1,000 free, then 402
LeadOcean on Solo$97 for the month
Power Automate Premium, one user$15 a month, billed yearly

The request count is arithmetic from the limits above, not a measured run.

Troubleshooting

SymptomCauseFix
Flow will not save or run, licence errorThe flow uses a capability outside the owner's licenceAssign a Power Automate Premium licence to the flow owner.
401 from LeadOceanMissing or wrong x-api-key headerRe-paste the key. The header is x-api-key, not Authorization.
400 from LeadOceanBlank or malformed new_linkedinurlAdd new_linkedinurl ne null to the filter and trim spaces.
404 on some contactsLeadOcean holds nothing for that personExpected. It costs nothing. Add a branch that tags the contact.
402 after a whileThe free 1,000 records are spentMove to Solo, or stop the flow.
429 errorsRequests above 5 a second on FreeSet Apply to each concurrency to 1 and honor Retry-After.
Run stops at the daily capDataverse request limit reachedLower Top Count or split the run across days.

FAQ

Can I enrich Leads and Accounts too?

Yes. Leads work the same way with POST /v1/people/enrich. For Accounts, POST /v1/companies/enrich takes a domain. Add a text column for the domain and repeat the flow.

Will it overwrite what my reps typed?

Not with the filter above. It only picks contacts whose email is empty. For job title, add a condition that writes only when jobtitle is empty.

Do I need a card to test this?

No. The free plan needs no card and gives the same API as Solo. Your 1,000 records last until you spend them.

Does LeadOcean keep my Dynamics data in sync?

No. It answers per call. The flow decides what to ask and when. Related recipes: Retool, Notion, Folk. Back to all integrations, or see pricing.

Enrich your Dynamics 365 contacts. Start free.

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

Get your free API key →