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

How-to guide

How to Enrich ActiveCampaign Contacts for Personalization (8 Ways to Run It)

One LeadOcean enrich call, one PUT back to ActiveCampaign, then eight ways to run it. Job title and company land in custom fields you can merge into emails.

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

TL;DR

  • Fetch the contact's email, call POST /v1/people/enrich once, and PUT job title and company into ActiveCampaign custom fields. Eight runners can do it.
  • The first runner takes about 40 minutes. Each extra one takes about 10.
  • It spends one LeadOcean record per contact we hold. A miss is a 404 and costs nothing, so the free 1,000 covers a real test.

ActiveCampaign's API reference describes contacts, custom fields and automations. It does not show a built-in step that fills a title or company from outside data. So "enrichment tool" here means a runner you wire up once, around one lookup and one write.

The eight runners are the same recipe in different clothes:

  1. A small script you host.
  2. An ActiveCampaign webhook that calls your script.
  3. Zapier.
  4. Make.
  5. n8n.
  6. Clay.
  7. A CSV from the LeadOcean Exports page.
  8. A nightly cron sweep.

Prerequisites

  • An ActiveCampaign account with API access. Your API URL and key sit on the My Settings page, Developer tab (ActiveCampaign docs, September 2026).
  • Two custom contact fields, for example Job title and Company. Note their numeric field IDs.
  • A LeadOcean key from app.leadocean.io. Free has no card, 1,000 records for life and 5 requests a second.
  • Secrets as shell variables, never in a page or repo.
bash
export LEADOCEAN_API_KEY="paste-your-leadocean-key"
export AC_BASE="https://youraccountname.api-us1.com/api/3"
export AC_API_KEY="paste-your-activecampaign-key"

ActiveCampaign authenticates with an Api-Token header and allows 5 requests per second per account (ActiveCampaign docs, September 2026). That is the real ceiling for every runner below.

Step 1: Size the job before you spend anything

A count costs nothing. This one ran on 2026-10-21 through the MCP tool leadocean_count_leads.

json
{
  "jobFunction": ["Advertising & Marketing"],
  "jobLevel": ["Director"],
  "employeeRange": ["51-200"],
  "country": ["US"],
  "facets": false
}

It returned 32,611 people with a verified, catch_all_valid or catch_all email, out of 102,507 with no email condition, across 18,848 employers. That is a mailable count, not everyone matching. Use it to judge a list you plan to add. For contacts already in ActiveCampaign, the cost is the number you enrich.

Step 2: Read the contact

List or fetch contacts from ActiveCampaign and keep the email and ID. Skip any contact whose Job title field is already filled, so you never overwrite what a rep typed.

bash
curl -s "$AC_BASE/contacts/123" -H "Api-Token: $AC_API_KEY"

The 123 is a placeholder contact ID.

Step 3: Enrich by email

Send exactly one identifier: linkedin_url, email, phone or person_id (LeadOcean docs, September 2026). On an email lookup, reveal_email defaults to true.

bash
curl -s -X POST "https://api.leadocean.io/v1/people/enrich" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "content-type: application/json" \
  -d '{"email":"jane.doe@acme.com"}'

A 404 means we hold nothing for that person and costs nothing. Leave the contact alone.

Step 4: Write the fields back

ActiveCampaign updates a contact with PUT /contacts/{id}. Fields you leave out keep their values, and fieldValues saves custom fields in the same request (ActiveCampaign docs, September 2026).

bash
curl -s -X PUT "$AC_BASE/contacts/123" \
  -H "Api-Token: $AC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"contact":{"fieldValues":[
        {"field":"1","value":"VP Sales"},
        {"field":"2","value":"Acme"}]}}'

Field IDs 1 and 2 are placeholders for your own. Build the values from data.contact_data.contact_current_experiences[0].job_title and .company_name. Here is the whole loop:

python
import os, requests

LO = {"x-api-key": os.environ["LEADOCEAN_API_KEY"]}
AC = {"Api-Token": os.environ["AC_API_KEY"]}
BASE = os.environ["AC_BASE"]

def enrich(contact_id: int, email: str) -> None:
    p = requests.post("https://api.leadocean.io/v1/people/enrich",
                      headers=LO, json={"email": email})
    if p.status_code == 404:
        return
    p.raise_for_status()
    job = (p.json()["data"]["contact_data"].get("contact_current_experiences") or [{}])[0]
    if not job.get("job_title"):
        return
    requests.put(f"{BASE}/contacts/{contact_id}", headers=AC, json={"contact": {
        "fieldValues": [
            {"field": "1", "value": job["job_title"]},
            {"field": "2", "value": job.get("company_name", "")}]}})

Merge the two fields into a campaign with ActiveCampaign's personalization tags. Write "Hi, saw you lead marketing at Acme" only when both fields are filled.

Step 5: Pick a runner

All eight call the same two APIs. They differ in who hosts the trigger.

#RunnerTriggerWhat you build
1Your scriptWebhook or scheduleenrich() above behind a small web server
2ActiveCampaign webhookA contact is added (subscribe event)A webhook created through the API that posts to your script (ActiveCampaign docs, October 2026)
3ZapierActiveCampaign triggerWebhooks by Zapier to the enrich URL, then an ActiveCampaign update
4MakeActiveCampaign moduleTwo HTTP modules and a filter on status 404
5n8nActiveCampaign nodeHTTP Request to LeadOcean, ActiveCampaign node to update
6ClayA tableAn HTTP column, then a write to ActiveCampaign
7CSVManualExports page CSV, then your own import
8CronA scheduleThe sweep below

Zapier lists an ActiveCampaign app (Zapier, September 2026). Make documents an ActiveCampaign app that manages contacts and custom objects, and requires a paid ActiveCampaign account (Make, September 2026). n8n's node creates, gets, updates and deletes contacts, lists, tags and deals (n8n docs, September 2026). LeadOcean has no listing in any of them, so the enrich call is a plain HTTP request with an x-api-key header. See our Make recipe and Clay recipe.

For runner 7, the LeadOcean app has an Exports page with a filter builder, a column picker and the record price before you start. Bulk CSV export is not on Free. Request numbered columns such as email_1_address and phone_1_number.

For runner 8, stay under 5 requests a second on both sides:

bash
0 6 * * * /usr/bin/python3 /opt/enrich/sweep.py >> /var/log/enrich.log 2>&1

What you get

The response shape from the API reference, with placeholder values (not a real person).

json
{
  "data": {
    "profile_data": { "profile_full_name": "Jane Doe" },
    "contact_data": {
      "contact_current_experiences": [
        { "job_title": "VP Sales", "company_name": "Acme", "company_domain": "acme.com" }
      ],
      "contact_emails": [
        { "email": "jane.doe@acme.com", "type": "work", "status": "verified" }
      ],
      "contact_phones": [
        { "phone": "+1 415 555 0133", "type": "mobile" }
      ]
    }
  }
}

Since 17 October 2026 the response can also carry career history in resume_data: past roles, education and certifications, each when held. After the run, the contact shows VP Sales and Acme in the two custom fields.

Troubleshooting

ErrorCauseFix
401 from LeadOceanMissing or wrong x-api-keyRe-copy the key and check the header name
403 from ActiveCampaignThe user lacks the edit contacts permissionUse a key from a user who can edit contacts
404 from enrichWe hold nothing for that identifierSkip the contact. It cost nothing
429Above the plan's rate limit (5 a second on Free, 200 on Agency)Honor Retry-After and queue the calls
402Free records are spentMove to Solo at $97 a month or Agency at $497 a month
422 from ActiveCampaignValidation failed on the updateCheck the field IDs and the values in the body

FAQ

Does ActiveCampaign enrich contacts by itself?

Its API reference lists contact, custom field and automation endpoints. It shows no outside-data enrichment step (ActiveCampaign docs, September 2026). Check your plan in the app before you assume one exists.

Which runner should I pick?

Pick Zapier or Make if nobody writes code. Pick your script or n8n for full control of retries. Pick cron for a nightly sweep.

What does it cost?

Free gives 1,000 records once, with no card. Solo is $97 a month and Agency is $497 a month, with a fair-use pace instead of credits. See pricing and what enrichment is.

Will it overwrite what my reps typed?

Not with the guard in Step 2. Extend the same check to any field you want to protect.

Are there other CRMs I can do this for?

Yes. The shape is identical. See 5 enrichment tools for a less annoying CRM.

Fill your ActiveCampaign fields with real job titles

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

Get your free API key →