From openfunnel
Enriches company domains into OpenFunnel account IDs, relevant contacts, and work emails. Batch-process multiple domains for account-level contact lists with email coverage.
npx claudepluginhub openfunnel/openfunnel-skillsThis skill uses the workspace's default tool permissions.
Resolve one or more company domains in a batch, discover relevant people at each account, enrich missing work emails, and return a clean account-by-account contact list.
Enriches LinkedIn profiles from people-search with verified emails and phones using providers like Prospeo or Fullenrich. Supports single-provider and waterfall modes; outputs contact CSV.
Builds targeted company and contact lists using Common Room Prospector for net-new prospects or existing accounts with signals. Clarifies object types and refines iteratively.
Automates Apollo.io lead generation: search organizations, discover contacts, enrich prospect data, manage stages, and build outreach lists using natural language via Composio MCP.
Share bugs, ideas, or general feedback.
Resolve one or more company domains in a batch, discover relevant people at each account, enrich missing work emails, and return a clean account-by-account contact list.
If the user wants contacts + emails for one company, this skill still applies.
This skill bundles two scripts in the same directory as this SKILL.md file. Never read or reference API credentials directly.
signup.sh — handles authentication. Writes credentials to .env internally. Never exposes the API key.api.sh — handles all authenticated API calls. Reads credentials from .env internally.First, resolve the script paths relative to this file's location:
SKILL_DIR="$(dirname "$(find ~/.agents/skills -name SKILL.md -path "*/enrich-accounts-with-contacts-and-emails/*" 2>/dev/null | head -1)")"
API="$SKILL_DIR/api.sh"
SIGNUP="$SKILL_DIR/signup.sh"
Then use $SIGNUP for auth and $API for all other calls.
Before anything, test if credentials are working by running:
bash "$API" POST /api/v1/signal/get-signal-list '{"pagination": {"limit": 1, "offset": 0}}'
If the call succeeds (returns JSON with signals): skip to Step 1.
If the call fails (returns an error or missing credentials message):
### Welcome to OpenFunnel
OpenFunnel turns daily events in your market into pipeline
— using OpenFunnel's Event Intelligence engine.
To get started, I'll authenticate you via the API and fetch your key.
**Step 0: Agent auth** — what's your work email?
Wait for user input. Then:
Run bash "$SIGNUP" start "<user_email>"
If the call succeeds, tell the user a 6-digit verification code was sent and ask for it:
I sent a 6-digit verification code to **{email}**.
Reply with the code and I'll finish authentication.
Wait for user input. Then run bash "$SIGNUP" verify "<user_email>" "<code>"
On success, the response is: {"status": "authenticated", "user_id": "..."}. Credentials are written to .env and .gitignore is updated automatically.
Verify with bash "$API" POST /api/v1/signal/get-signal-list '{"pagination": {"limit": 1, "offset": 0}}'
If verification succeeds → continue to ICP check.
If sign-up fails → tell the user the email could not be authenticated and ask them to retry.
If verify fails → tell the user the code was invalid or expired, explain they get up to 10 attempts within 24 hours, and ask whether to retry the code or send a new one by calling sign-up again.
After auth, fetch ICP profiles via bash "$API" GET /api/v1/icp/list.
If ICPs exist: note the available ICPs and continue to Step 1.
If no ICPs exist:
You don't have an ICP profile yet. A quick one will make results much sharper —
it filters by company size, location, and the roles you're targeting.
1. **Quick setup** (recommended) — takes 30 seconds
2. **Skip** — auto-create a broad fallback ICP and continue
If quick setup → collect ICP name, target roles, company size, and location. Create via bash "$API" POST /api/v1/icp/create '<json_body>'.
If skip → auto-create a broad fallback ICP:
{
"name": "Broad Default ICP",
"target_roles": ["Any"],
"employee_ranges": ["1-10", "11-50", "51-200", "201-500", "501-1000", "1001-5000", "5001-10000", "10001+"],
"location": ["Any"]
}
Call bash "$API" POST /api/v1/icp/create '<json_body>', then tell the user:
I created a default ICP profile: **{name}** (ID: {id})
This keeps things running. For sharper results, set up a proper ICP segment
with your target roles, company size, and location using the `advanced-account-setup` skill.
Continue to Step 1.
The user should provide a list of company domains or a list of OpenFunnel accounts.
If the input is mixed or unclear, normalize it to domains first.
Before making enrichment calls, collect these batch-level settings:
Recommended defaults for a general outbound batch:
ENGINEERING, PRODUCT, SECURITY, EXECUTIVEVP, HEAD, DIRECTOR, CXOIf the user does not specify filters, recommend these defaults and ask for confirmation. Do not silently guess.
Use this prompt:
I can enrich this list in three steps:
1. Batch account enrichment
2. Fast people discovery by account
3. Contact enrichment for missing emails
To discover the right people, I need batch filters:
- **Departments** (examples: ENGINEERING, PRODUCT, SECURITY, SALES, EXECUTIVE)
- **Seniority** (examples: VP, HEAD, DIRECTOR, CXO)
Optional:
- **Max credit limit** for fast people discovery
Recommended defaults for most B2B account enrichment:
- **Departments:** ENGINEERING, PRODUCT, SECURITY, EXECUTIVE
- **Seniority:** VP, HEAD, DIRECTOR, CXO
Should I use those defaults, or would you like to override them for this batch?
Clean every domain before using it:
http:// or https://www.Use batch account enrichment first, even if the input contains only one domain.
Call:
bash "$API" POST /api/v1/enrich/accounts '{"domains": [...]}'
Then poll:
bash "$API" GET /api/v1/enrich/accounts/{job_id}
Polling guidance:
completed or failedWhen the poll completes, record for each domain:
domainaccount_idnameis_new_accountfields_updatedstatusIf the batch job fails entirely, stop and report the error.
If the batch completes with mixed results, continue with all successful accounts and clearly mark failed domains.
After batch enrichment completes, fetch current account details with:
bash "$API" POST /api/v2/account/batch '{"account_ids": [...], "icp_people_page": 1, "icp_people_page_size": 100}'
Present a coverage summary before enrichment:
### Accounts to Process
| Domain | Account ID | Account Name | Account Enrichment Status | Existing ICP People | Next Step |
|--------|------------|--------------|---------------------------|---------------------|-----------|
| acme.com | 123 | Acme | created | 2 | Run fast people enrichment |
| beta.io | 456 | Beta | unchanged | 0 | Run fast people enrichment |
| gamma.dev | - | - | failed | - | Skip |
Rules:
Present a brief execution summary, then continue automatically:
Processing plan:
1. **Batch account enrichment** — create or refresh account records from the input domains
2. **Fast people enrichment** — run per resolved account to find relevant people by department and seniority
3. **Email enrichment** — fill in missing work emails for discovered people
Batch settings:
- **Departments:** {department_filters}
- **Seniority:** {seniority_filters}
- **Max credit limit:** {max_credit_limit or "default"}
I'll reuse existing people and emails where OpenFunnel already has them.
This works for a single account too — it just runs as a one-domain batch.
For each resolved account returned from the batch account enrichment job, start a fast people enrichment job:
bash "$API" POST /api/v1/enrich/fast-people-enrichment '<json_body>'
Body:
{
"account_id": 12345,
"seniority_filters": ["VP", "DIRECTOR"],
"department_filters": ["ENGINEERING", "PRODUCT"],
"max_credit_limit": 50
}
Run these jobs in parallel across accounts where possible.
Then poll each job:
bash "$API" GET /api/v1/enrich/fast-people-enrichment/{job_id}
Polling guidance:
completed or failedFor each account, record:
account_idjob_idpeople_idscredits_usedtotal_foundtotal_storederror_messageRules:
Build one deduplicated people ID list from:
icp_people from the V2 account batch callpeople_ids returned by fast people enrichmentThen call:
bash "$API" POST /api/v1/people/batch '{"people_ids": [...]}'
This is the source of truth for person details:
person_idperson_nameperson_roleperson_emailperson_locationperson_linkedin_urlperson_phone_numberperson_team_namedepartmentseniorityaccount_idaccount_nameaccount_domainSplit people into three groups:
For eligible people, call:
bash "$API" POST /api/v1/enrich/people '<json_body>'
Body:
{
"people_ids": [101, 102, 103],
"enrich_emails": true,
"enrich_phones": false
}
Then poll:
bash "$API" GET /api/v1/enrich/people/{job_id}
Polling guidance:
completed or failedImportant constraints:
no_linkedin_url cannot be enrichednot_found means lookup completed but no email was foundIf the people batch is larger than 500, split it into chunks and process sequentially.
Merge the email enrichment results back into the people records.
Return results grouped by account using this format:
## Enriched Accounts
### {account_name} ({domain})
| Name | Role | Department | Seniority | Team | Email | LinkedIn | Status |
|------|------|------------|-----------|------|-------|----------|--------|
| Jane Doe | VP Engineering | ENGINEERING | VP | Platform | jane@acme.com | [Profile](...) | enriched |
| John Roe | Director Product | PRODUCT | DIRECTOR | Core Product | missing | [Profile](...) | not_found |
After the table, include a short account summary:
- Total contacts returned: {n}
- Emails present: {n}
- Emails newly enriched: {n}
- Missing emails: {n}
If any account failed or stayed unresolved, include a separate section:
### Incomplete Accounts
| Domain | Stage | Reason |
|--------|-------|--------|
| gamma.dev | account resolution | not found |
| delta.ai | email enrichment | no_linkedin_url |
Skip fast people enrichment only if the user explicitly says:
Otherwise, prefer running fast people enrichment to improve account coverage after batch account enrichment has resolved the accounts.
Skip email enrichment only if:
Mention deep enrichment (bash "$API" POST /api/v1/enrich/deep-enrich '<json_body>') only as an optional fallback when:
Do not auto-run it in this workflow.