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

How-to guide

How to Design Outbound Workflow Automations That Book Meetings (With a Data API)

Five steps, each with a gate that stops bad data before it reaches a mailbox. About 50 records to test it on the free plan.

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

TL;DR

  • A workflow that books meetings is five stages with a gate between each: size, search, enrich, filter, hand off. Skip a gate and you pay for it in bounces.
  • It takes about 45 minutes to build and test against the LeadOcean API.
  • The first run spends about 50 records of the 1,000 on the free plan. Sizing the list costs none.

Prerequisites

  • A LeadOcean API key in $LEADOCEAN_API_KEY (free plan: 1,000 records for life, no card, 5 requests a second).
  • curl and jq, or any workflow tool that sends HTTP requests with a header. See LeadOcean + n8n for one way to wire it.
  • A sending tool that takes a CSV or an API push. LeadOcean is the data layer. It has no sequencer, dialer or CRM.

Step 1: Size the list before you build anything

Count first. A count is free, so run it as often as you like and tighten the filters until the list fits one sender's capacity.

The filter names below are the ones the search endpoint and the MCP tool share. This count ran through the free leadocean_count_leads tool on 2026-10-21:

json
{
  "jobLevel": ["VP"],
  "jobFunction": ["Sales & Business Development"],
  "country": ["US"],
  "employeeRange": ["51-200"]
}
text
total: 18,567   (mailable: verified, catch_all_valid or catch_all)
totalAll: 60,456   (same filters, no email condition)
distinctCompanies: 12,192

Read the gap. 60,456 people match, 18,567 have an address worth sending to. Your real list is the smaller number.

Design rule: if the count is over what one team can work in a month, narrow it. Add a title or a company filter. Do not sample a big list.

Why the order matters: the cheapest mistake is a wrong filter, and the count catches it at zero cost. The most expensive mistake is a wrong filter you only notice after 500 emails bounced. Size first, always. More workflow guides live in the blog.

Step 2: Search the people you sized

Search with the same filters plus emailStatus so you only pull mailable rows. Page size is 1 to 100. One page of 25 is 25 records.

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"],
    "country": ["US"],
    "employeeRange": ["51-200"],
    "emailStatus": ["verified", "catch_all_valid", "catch_all"],
    "limit": 25
  }' | jq '.meta'

The body is flat JSON and every filter is an array. Enum values are exact strings: VP, not vp. Look them up with GET /v1/enums/job_level (free) before guessing.

To get the next page, pass the cursor from the previous response. One search pages to 10,000 rows. The last page has meta.depthCapped set to true and no nextCursor. Narrow the filters instead of walking further.

Step 3: Enrich only the rows that passed your own rules

Search is for breadth. Enrichment adds the detail your message needs. Run it after you drop rows you would never contact, such as competitors and existing customers.

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 '{"person_id": "PERSON_ID_FROM_SEARCH", "reveal_email": true}'

Pass exactly one of linkedin_url, email, phone or person_id. Every search row carries its id at meta.source_ids.person_id. There is no name plus domain lookup, so search by domain first, then enrich by person_id. A person we hold nothing for returns 404 and costs nothing.

Since October 2026 the response includes career history (resume_data): past roles with dates, education, certifications. Use it for one specific line in the first email, not five.

Keep the personalization rule simple: one fact the reader would recognize as true, tied to the offer. A past role at a company you both know works. A list of three certifications does not. If the field is empty for a person, send the plain version instead of forcing a line.

Step 4: Gate on email status, not on hope

This is the step most designs skip. Read contact_data.email_status on each enrich response and send only what you chose to trust.

bash
jq -r '.data
  | select(.contact_data.email_status == "verified")
  | [.profile_data.profile_full_name, .contact_data.contact_emails[0].email]
  | @csv' enriched/*.json

My default: verified goes to the sequence. catch_all goes to a small separate test batch. risky, unknown and untested stay out. There is no refund for bounced emails, so the gate is your protection.

Step 5: Hand off and design the loop that stops itself

Push the gated rows to your sender. For volume, use a CSV export: POST /v1/exports takes up to 50,000 rows a request and 500,000 a day. Bulk CSV export is not on the free plan.

Whatever sends the mail, build three stops into the workflow:

  1. Reply stops the sequence. One reply, positive or not, ends the steps for that person.
  2. Daily cap per mailbox. Set it in the sender. Never let the list size set your send rate.
  3. Meeting booked removes the contact and the colleagues you were also writing to at that company.

A worked example of the stops. Say you send to 200 people at 60 companies with a daily cap of 30 a mailbox. Day one reaches 30. A reply from a VP at Acme pauses her sequence and holds every other Acme contact until you decide. Without that hold, three people at one company get the same pitch in one week, and the account is burned.

Keep the data side stateless. The API does not know what you sent, so store sent status in your own table, keyed on person_id. Re-running a search then never re-mails someone, and a re-run costs only the new rows you actually pull.

Then close the loop on data. Log each outcome next to the person_id. After two weeks, recount Step 1 with the filters that produced replies and drop the ones that did not.

What you get

Response shape from the API reference, placeholder values (this is not a real record):

json
{
  "success": true,
  "data": {
    "profile_data": { "profile_full_name": "Jane Doe", "profile_headline": "VP Sales at Acme" },
    "contact_data": {
      "has_email": true,
      "has_phone": true,
      "email_status": "verified",
      "email_type": "work",
      "contact_emails": [{ "email": "jane@acme.com", "type": "work", "status": "verified" }]
    },
    "resume_data": { "experiences": [], "educations": [] }
  },
  "meta": { "credits": 1 }
}

Run against the free plan, the whole loop is the 50-record test in the TL;DR. Scale the same five steps to a list in the thousands only after the reply rate on the first batch tells you the filters are right.

Cost check before you scale. A search page of 25 is 25 records, and each enrichment is one record, so the 1,000 free records cover about 20 batches of 50. Counts, filter lookups and enrichments that find nobody spend nothing. Check GET /v1/usage between runs. That way a loop never surprises you with a 402.

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-keyCheck $LEADOCEAN_API_KEY is exported and sent as that header
429Above your plan's rate limit (5 a second on Free, 200 on Agency)Honor the Retry-After header and space the calls
402Records spent (1,000 for life on Free)Move to a paid plan, see pricing
Empty resultsA bad enum value, such as vp for a job levelFetch the exact strings from GET /v1/enums/{name}
Export refusedOver 50,000 rows a request or 500,000 a daySplit the export by filter into smaller requests
Search stops with no nextCursorThe 10,000 row depth cap (meta.depthCapped)Narrow the filters and search again

FAQ

How many steps should an outbound workflow have?

Five is enough: size, search, enrich, filter, hand off. Add steps only when a gate fails in practice. More steps mean more places to break.

Where should the email-status gate sit?

After enrichment, before anything sends. Count and search can run on any status, but nothing unverified should reach a mailbox without a deliberate choice.

Can an AI agent run this instead of a script?

Yes. LeadOcean has a hosted MCP server with 13 tools, and the count and filter tools are free. Read the Claude Code workflow guide for the agent route. Keep the gate in code, not in a prompt.

How big should the first batch be?

Fifty rows is enough to test the gates. You are checking that the filters return the right people and that the status filter holds, not measuring reply rates. Grow the batch once the first fifty look right.

What does this cost beyond the free plan?

Solo is $97 a month for one person and Agency is $497 a month for teams. Paid plans have a fair-use pace, not credits. See pricing.

Which tools should I compare before building?

Start with best AI outbound tools that actually book meetings and the outbound sales automation guide. They cover the sending side. This page covers the data side.

Build your outbound workflow on real, gated data

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

Get your free API key →