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

How-to guide

How to Use a Social Posts API for Real-Time B2B Data (With a People Layer Underneath)

Posts say what a buyer cares about today. A people API says who they are and how to reach them. Here is the join, with real queries.

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

A social posts API returns what a person or company published recently. That is a signal. It is not a contact record, and you still need to know who the person is and how to reach them.

LeadOcean does not return posts. It is the people and company layer: who to watch, and how to reach them. This guide builds the list in LeadOcean and shows where a posts source plugs in.

TL;DR

  • Build the watch list with LeadOcean search, enrich each person once, and hand their LinkedIn URL to a posts API. Setup takes about 45 minutes.
  • Sizing and testing spend 0 records. Each person enriched spends 1 record, so the walkthrough below spends 3.
  • Read the post first, then the email_status. Send only when both hold.

Prerequisites

  • A LeadOcean account on the Free plan: 1,000 records for life, no card, 5 requests a second. Register at app.leadocean.io.
  • An API key from the app, stored as $LEADOCEAN_API_KEY.
  • curl, jq and Python 3 with requests.
  • An account with a social posts API. This guide uses Crustdata's posts API as the example. Its page (September 2026) lists posts by person, posts by company and posts by keyword, with likes, comments and shares.

Step 1: Decide what each source answers

Posts answer "what is this person talking about this week". LeadOcean answers "who is this and can I email them". Keep the two jobs apart.

QuestionSource
Who are the VPs of sales at my target accounts?LeadOcean people search
Is their email sendable?LeadOcean email_status
What did they post this week?A posts API
Where did they work before?LeadOcean resume_data

One honest caveat. LeadOcean search has a keywords filter, but it matches the person's own profile text: headline, summary, skills and job descriptions. That is not their posts.

Step 2: Size the watch list for free

Count before you spend. A count costs 0 records. Send count=true as a query parameter, not in the JSON body.

bash
curl -s -X POST "https://api.leadocean.io/v1/people/search?count=true" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "jobLevel": ["VP"],
    "jobFunction": ["Sales & Business Development"],
    "keywords": ["outbound"],
    "country": ["US"],
    "limit": 1
  }' | jq '.meta | {total, totalIsExact, countOnly}'

Enum values are exact strings. VP works. Vice President returns nothing. Check GET /v1/enums/job_level if unsure.

Inside an agent, the free leadocean_count_leads MCP tool does the same.

Step 3: Pull the people

Search the same filters without count. Each person returned spends 1 record, so keep limit small while testing.

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"],
    "jobFunction": ["Sales & Business Development"],
    "keywords": ["outbound"],
    "country": ["US"],
    "limit": 3
  }' > people.json

jq -r '.data[].meta.source_ids.person_id' people.json

Three rows spend 3 records. The person_id is what you enrich by next. For more rows, page with the cursor from meta.nextCursor.

Step 4: Enrich and get the profile URL

Posts APIs key on a profile. Enrich by person_id to get the full record.

bash
PID=$(jq -r '.data[0].meta.source_ids.person_id' people.json)

curl -s -X POST "https://api.leadocean.io/v1/people/enrich" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "content-type: application/json" \
  -d "{\"person_id\": \"$PID\", \"reveal_email\": true}" > lead.json

jq -r '.data.profile_data.profile_url' lead.json

The LinkedIn URL is profile_data.profile_url (enrich docs). Search rows carry the same field, so you can read it from people.json and enrich only the people you will write to. About one person in five has no LinkedIn URL; skip those for a posts lookup.

Enrichment spends 1 record. A person we hold nothing for is a 404 and spends nothing.

Step 5: Fetch the posts

Send the profile URL to your posts provider. The call below is a placeholder: take the real path, parameters and auth from the provider's docs, not from this page.

python
import os, requests

POSTS_URL = os.environ["POSTS_API_URL"]  # from your posts provider's docs
POSTS_KEY = os.environ["POSTS_API_KEY"]

def recent_posts(profile_url):
    r = requests.get(
        POSTS_URL,
        headers={"authorization": f"Bearer {POSTS_KEY}"},
        params={"profile_url": profile_url},  # parameter name: check the provider's docs
        timeout=30,
    )
    r.raise_for_status()
    return r.json()

Crustdata's posts page (September 2026) says its API returns post text, hyperlinks and engagement counts. It names tracking hiring updates and founder announcements as use cases. It lists no price on that page, so confirm cost in their dashboard before you loop over a list.

Step 6: Join, filter and decide

Join on the LinkedIn URL. Keep a lead only when it has a recent post that matches your trigger and a sendable email.

python
import json

lead = json.load(open("lead.json"))["data"]
profile_url = lead["profile_data"].get("profile_url")
status = lead["contact_data"].get("email_status") or "none"
role = (lead["contact_data"].get("contact_current_experiences") or [{}])[0]

posts = recent_posts(profile_url)
hits = [p for p in posts.get("data", []) if "outbound" in json.dumps(p).lower()]

sendable = status in {"verified", "catch_all_valid", "catch_all"}
print({"role": role, "status": status, "post_hits": len(hits), "send": bool(hits) and sendable})

Two rules matter here. A post is a reason to write, not permission to quote it back at the person. And LeadOcean gives no refund for bounced emails, so read email_status first.

Dataset records are refreshed monthly and each carries a fetched_at date. A job title can lag a post by weeks. If the post says "excited to join", trust the post over the title.

What you get

Step 2 ran through the free leadocean_count_leads tool on 2026-10-21. Filters: jobLevel VP, jobFunction Sales & Business Development, keywords "outbound", country US.

json
{"total":510,"totalIsExact":true,"totalAll":997,"distinctCompanies":473,"credits":0}

That is a mailable count: the tool defaults to verified, catch_all_valid and catch_all emails. totalAll is the same filters with no email condition. The call spent 0 records.

An enrich response has this shape. Response shape from the API reference (placeholder values):

json
{
  "data": {
    "profile_data": { "profile_full_name": "Jane Doe", "profile_url": "https://www.linkedin.com/in/jane-doe" },
    "contact_data": {
      "has_email": true,
      "email_status": "verified",
      "contact_emails": [
        { "email": "jane.doe@acme.com", "type": "work", "status": "verified", "priority": 1 }
      ],
      "contact_current_experiences": [ { "job_title": "VP Sales", "company_name": "Acme" } ]
    },
    "resume_data": { "experiences": [], "educations": [] }
  },
  "meta": { "credits": 1 }
}

The posts side of the join comes from your posts provider, so its shape is theirs.

Troubleshooting

ErrorCauseFix
401Missing, wrong or revoked keyRe-copy the key from app.leadocean.io. The header is x-api-key.
429Above the plan's rate limit (5 a second on Free, 200 on Agency)Wait for Retry-After, then retry.
402Fewer records left than the request needsCheck GET /v1/account, or move to Solo or Agency.
Empty search resultsA filter value outside the list, such as Vice PresidentUse VP. Check GET /v1/enums/job_level.
404 on enrichNobody matched, or no enrichable identifier is heldCosts nothing. Skip the lead or try another person.
Search stops pagingOne search pages to 10,000 rows (meta.depthCapped)Narrow the filters instead of walking further.

FAQ

Does LeadOcean have a social posts API?

No. LeadOcean returns people and company records, with search, enrichment, email, phone and career history. Use a posts provider for posts and join on the profile URL.

What does this cost in LeadOcean records?

Counts spend 0. Search spends 1 record per person returned. Enrich spends 1 per person found. Free has 1,000 records for life. Solo is $97 a month and Agency is $497 a month, with a fair-use pace instead of credits. See pricing.

Is the data real time?

The posts side is the provider's. LeadOcean is refreshed monthly. For a live call per lead, see people data enrichment in real time.

Can an AI agent run this?

Yes. The hosted MCP server has 13 tools, including free counting. See real-time B2B data for AI agents. For web results as a signal, see the SERP API guide. More guides are on the blog.

Build the people side of your post signals free

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

Get your free API key →