Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a3516be13d | |||
| 90a7e84d0e | |||
| cac82f3a40 | |||
| 0c24410a0b |
@@ -167,7 +167,7 @@ This repository includes a tools registry for agent-compatible marketing tools.
|
||||
|
||||
- **Tool discovery**: Read `tools/REGISTRY.md` to see available tools and their capabilities
|
||||
- **Integration details**: See `tools/integrations/{tool}.md` for API endpoints, auth, and common operations
|
||||
- **MCP-enabled tools**: ga4, stripe, mailchimp, google-ads, resend, zapier, zoominfo, clay, supermetrics, coupler, outreach, crossbeam
|
||||
- **MCP-enabled tools**: ga4, stripe, mailchimp, google-ads, resend, zapier
|
||||
|
||||
### Registry Structure
|
||||
|
||||
|
||||
@@ -78,8 +78,8 @@ See each skill's **Related Skills** section for the full dependency map.
|
||||
| [product-marketing-context](skills/product-marketing-context/) | When the user wants to create or update their product marketing context document. Also use when the user mentions... |
|
||||
| [programmatic-seo](skills/programmatic-seo/) | When the user wants to create SEO-driven pages at scale using templates and data. Also use when the user mentions... |
|
||||
| [referral-program](skills/referral-program/) | When the user wants to create, optimize, or analyze a referral program, affiliate program, or word-of-mouth strategy.... |
|
||||
| [revops](skills/revops/) | When the user wants help with revenue operations, lead lifecycle management, or marketing-to-sales handoff... |
|
||||
| [sales-enablement](skills/sales-enablement/) | When the user wants to create sales collateral, pitch decks, one-pagers, objection handling docs, or demo scripts... |
|
||||
| [revops](skills/revops/) | When the user wants help with revenue operations, lead lifecycle management, or marketing-to-sales handoff processes.... |
|
||||
| [sales-enablement](skills/sales-enablement/) | When the user wants to create sales collateral, pitch decks, one-pagers, objection handling docs, or demo scripts. Also... |
|
||||
| [schema-markup](skills/schema-markup/) | When the user wants to add, fix, or optimize schema markup and structured data on their site. Also use when the user... |
|
||||
| [seo-audit](skills/seo-audit/) | When the user wants to audit, review, or diagnose SEO issues on their site. Also use when the user mentions "SEO... |
|
||||
| [signup-flow-cro](skills/signup-flow-cro/) | When the user wants to optimize signup, registration, account creation, or trial activation flows. Also use when the... |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: ab-test-setup
|
||||
description: When the user wants to plan, design, or implement an A/B test or experiment. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," or "how long should I run this test." Use this whenever someone is comparing two approaches and wants to measure which performs better. For tracking implementation, see analytics-tracking. For page-level conversion optimization, see page-cro.
|
||||
description: When the user wants to plan, design, or implement an A/B test or experiment. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," or "hypothesis." For tracking implementation, see analytics-tracking.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: ad-creative
|
||||
description: "When the user wants to generate, iterate, or scale ad creative — headlines, descriptions, primary text, or full ad variations — for any paid advertising platform. Also use when the user mentions 'ad copy variations,' 'ad creative,' 'generate headlines,' 'RSA headlines,' 'bulk ad copy,' 'ad iterations,' 'creative testing,' 'ad performance optimization,' 'write me some ads,' 'Facebook ad copy,' 'Google ad headlines,' 'LinkedIn ad text,' or 'I need more ad variations.' Use this whenever someone needs to produce ad copy at scale or iterate on existing ads. For campaign strategy and targeting, see paid-ads. For landing page copy, see copywriting."
|
||||
description: "When the user wants to generate, iterate, or scale ad creative — headlines, descriptions, primary text, or full ad variations — for any paid advertising platform. Also use when the user mentions 'ad copy variations,' 'ad creative,' 'generate headlines,' 'RSA headlines,' 'bulk ad copy,' 'ad iterations,' 'creative testing,' or 'ad performance optimization.' This skill covers generating ad creative at scale, iterating based on performance data, and enforcing platform character limits. For campaign strategy and targeting, see paid-ads. For landing page copy, see copywriting."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: ai-seo
|
||||
description: "When the user wants to optimize content for AI search engines, get cited by LLMs, or appear in AI-generated answers. Also use when the user mentions 'AI SEO,' 'AEO,' 'GEO,' 'LLMO,' 'answer engine optimization,' 'generative engine optimization,' 'LLM optimization,' 'AI Overviews,' 'optimize for ChatGPT,' 'optimize for Perplexity,' 'AI citations,' 'AI visibility,' 'zero-click search,' 'how do I show up in AI answers,' 'LLM mentions,' or 'optimize for Claude/Gemini.' Use this whenever someone wants their content to be cited or surfaced by AI assistants and AI search engines. For traditional technical and on-page SEO audits, see seo-audit. For structured data implementation, see schema-markup."
|
||||
description: "When the user wants to optimize content for AI search engines, get cited by LLMs, or appear in AI-generated answers. Also use when the user mentions 'AI SEO,' 'AEO,' 'GEO,' 'LLMO,' 'answer engine optimization,' 'generative engine optimization,' 'LLM optimization,' 'AI Overviews,' 'optimize for ChatGPT,' 'optimize for Perplexity,' 'AI citations,' 'AI visibility,' or 'zero-click search.' This skill covers content optimization for AI answer engines, monitoring AI visibility, and getting cited as a source. For traditional technical and on-page SEO audits, see seo-audit. For structured data implementation, see schema-markup."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: analytics-tracking
|
||||
description: When the user wants to set up, improve, or audit analytics tracking and measurement. Also use when the user mentions "set up tracking," "GA4," "Google Analytics," "conversion tracking," "event tracking," "UTM parameters," "tag manager," "GTM," "analytics implementation," "tracking plan," "how do I measure this," "track conversions," "attribution," "Mixpanel," "Segment," "are my events firing," or "analytics isn't working." Use this whenever someone asks how to know if something is working or wants to measure marketing results. For A/B test measurement, see ab-test-setup.
|
||||
description: When the user wants to set up, improve, or audit analytics tracking and measurement. Also use when the user mentions "set up tracking," "GA4," "Google Analytics," "conversion tracking," "event tracking," "UTM parameters," "tag manager," "GTM," "analytics implementation," or "tracking plan." For A/B test measurement, see ab-test-setup.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: churn-prevention
|
||||
description: "When the user wants to reduce churn, build cancellation flows, set up save offers, recover failed payments, or implement retention strategies. Also use when the user mentions 'churn,' 'cancel flow,' 'offboarding,' 'save offer,' 'dunning,' 'failed payment recovery,' 'win-back,' 'retention,' 'exit survey,' 'pause subscription,' 'involuntary churn,' 'people keep canceling,' 'churn rate is too high,' 'how do I keep users,' or 'customers are leaving.' Use this whenever someone is losing subscribers or wants to build systems to prevent it. For post-cancel win-back email sequences, see email-sequence. For in-app upgrade paywalls, see paywall-upgrade-cro."
|
||||
description: "When the user wants to reduce churn, build cancellation flows, set up save offers, recover failed payments, or implement retention strategies. Also use when the user mentions 'churn,' 'cancel flow,' 'offboarding,' 'save offer,' 'dunning,' 'failed payment recovery,' 'win-back,' 'retention,' 'exit survey,' 'pause subscription,' or 'involuntary churn.' This skill covers voluntary churn (cancel flows, save offers, exit surveys) and involuntary churn (dunning, payment recovery). For post-cancel win-back email sequences, see email-sequence. For in-app upgrade paywalls, see paywall-upgrade-cro."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: cold-email
|
||||
description: Write B2B cold emails and follow-up sequences that get replies. Use when the user wants to write cold outreach emails, prospecting emails, cold email campaigns, sales development emails, or SDR emails. Also use when the user mentions "cold outreach," "prospecting email," "outbound email," "email to leads," "reach out to prospects," "sales email," "follow-up email sequence," "nobody's replying to my emails," or "how do I write a cold email." Covers subject lines, opening lines, body copy, CTAs, personalization, and multi-touch follow-up sequences. For warm/lifecycle email sequences, see email-sequence. For sales collateral beyond emails, see sales-enablement.
|
||||
description: Write B2B cold emails and follow-up sequences that get replies. Use when the user wants to write cold outreach emails, prospecting emails, cold email campaigns, sales development emails, or SDR emails. Covers subject lines, opening lines, body copy, CTAs, personalization, and multi-touch follow-up sequences.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: competitor-alternatives
|
||||
description: "When the user wants to create competitor comparison or alternative pages for SEO and sales enablement. Also use when the user mentions 'alternative page,' 'vs page,' 'competitor comparison,' 'comparison page,' '[Product] vs [Product],' '[Product] alternative,' 'competitive landing pages,' 'how do we compare to X,' 'battle card,' or 'competitor teardown.' Use this for any content that positions your product against competitors. Covers four formats: singular alternative, plural alternatives, you vs competitor, and competitor vs competitor. For sales-specific competitor docs, see sales-enablement."
|
||||
description: "When the user wants to create competitor comparison or alternative pages for SEO and sales enablement. Also use when the user mentions 'alternative page,' 'vs page,' 'competitor comparison,' 'comparison page,' '[Product] vs [Product],' '[Product] alternative,' or 'competitive landing pages.' Covers four formats: singular alternative, plural alternatives, you vs competitor, and competitor vs competitor. Emphasizes deep research, modular content architecture, and varied section types beyond feature tables."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: content-strategy
|
||||
description: When the user wants to plan a content strategy, decide what content to create, or figure out what topics to cover. Also use when the user mentions "content strategy," "what should I write about," "content ideas," "blog strategy," "topic clusters," "content planning," "editorial calendar," "content marketing," "content roadmap," "what content should I create," "blog topics," "content pillars," or "I don't know what to write." Use this whenever someone needs help deciding what content to produce, not just writing it. For writing individual pieces, see copywriting. For SEO-specific audits, see seo-audit. For social media content specifically, see social-content.
|
||||
description: When the user wants to plan a content strategy, decide what content to create, or figure out what topics to cover. Also use when the user mentions "content strategy," "what should I write about," "content ideas," "blog strategy," "topic clusters," or "content planning." For writing individual pieces, see copywriting. For SEO-specific audits, see seo-audit.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: copy-editing
|
||||
description: "When the user wants to edit, review, or improve existing marketing copy. Also use when the user mentions 'edit this copy,' 'review my copy,' 'copy feedback,' 'proofread,' 'polish this,' 'make this better,' 'copy sweep,' 'tighten this up,' 'this reads awkwardly,' 'clean up this text,' 'too wordy,' or 'sharpen the messaging.' Use this when the user already has copy and wants it improved rather than rewritten from scratch. For writing new copy, see copywriting."
|
||||
description: "When the user wants to edit, review, or improve existing marketing copy. Also use when the user mentions 'edit this copy,' 'review my copy,' 'copy feedback,' 'proofread,' 'polish this,' 'make this better,' or 'copy sweep.' This skill provides a systematic approach to editing marketing copy through multiple focused passes."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: copywriting
|
||||
description: When the user wants to write, rewrite, or improve marketing copy for any page — including homepage, landing pages, pricing pages, feature pages, about pages, or product pages. Also use when the user says "write copy for," "improve this copy," "rewrite this page," "marketing copy," "headline help," "CTA copy," "value proposition," "tagline," "subheadline," "hero section copy," "above the fold," "this copy is weak," "make this more compelling," or "help me describe my product." Use this whenever someone is working on website text that needs to persuade or convert. For email copy, see email-sequence. For popup copy, see popup-cro. For editing existing copy, see copy-editing.
|
||||
description: When the user wants to write, rewrite, or improve marketing copy for any page — including homepage, landing pages, pricing pages, feature pages, about pages, or product pages. Also use when the user says "write copy for," "improve this copy," "rewrite this page," "marketing copy," "headline help," or "CTA copy." For email copy, see email-sequence. For popup copy, see popup-cro.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: email-sequence
|
||||
description: When the user wants to create or optimize an email sequence, drip campaign, automated email flow, or lifecycle email program. Also use when the user mentions "email sequence," "drip campaign," "nurture sequence," "onboarding emails," "welcome sequence," "re-engagement emails," "email automation," "lifecycle emails," "trigger-based emails," "email funnel," "email workflow," "what emails should I send," "welcome series," or "email cadence." Use this for any multi-email automated flow. For cold outreach emails, see cold-email. For in-app onboarding, see onboarding-cro.
|
||||
description: When the user wants to create or optimize an email sequence, drip campaign, automated email flow, or lifecycle email program. Also use when the user mentions "email sequence," "drip campaign," "nurture sequence," "onboarding emails," "welcome sequence," "re-engagement emails," "email automation," or "lifecycle emails." For in-app onboarding, see onboarding-cro.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: form-cro
|
||||
description: When the user wants to optimize any form that is NOT signup/registration — including lead capture forms, contact forms, demo request forms, application forms, survey forms, or checkout forms. Also use when the user mentions "form optimization," "lead form conversions," "form friction," "form fields," "form completion rate," "contact form," "nobody fills out our form," "form abandonment," "too many fields," "demo request form," or "lead form isn't converting." Use this for any non-signup form that captures information. For signup/registration forms, see signup-flow-cro. For popups containing forms, see popup-cro.
|
||||
description: When the user wants to optimize any form that is NOT signup/registration — including lead capture forms, contact forms, demo request forms, application forms, survey forms, or checkout forms. Also use when the user mentions "form optimization," "lead form conversions," "form friction," "form fields," "form completion rate," or "contact form." For signup/registration forms, see signup-flow-cro. For popups containing forms, see popup-cro.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: free-tool-strategy
|
||||
description: When the user wants to plan, evaluate, or build a free tool for marketing purposes — lead generation, SEO value, or brand awareness. Also use when the user mentions "engineering as marketing," "free tool," "marketing tool," "calculator," "generator," "interactive tool," "lead gen tool," "build a tool for leads," "free resource," "ROI calculator," "grader tool," "audit tool," "should I build a free tool," or "tools for lead gen." Use this whenever someone wants to build something useful and give it away to attract leads or earn links. For content-based lead generation, see content-strategy.
|
||||
description: When the user wants to plan, evaluate, or build a free tool for marketing purposes — lead generation, SEO value, or brand awareness. Also use when the user mentions "engineering as marketing," "free tool," "marketing tool," "calculator," "generator," "interactive tool," "lead gen tool," "build a tool for leads," or "free resource." This skill bridges engineering and marketing — useful for founders and technical marketers.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: launch-strategy
|
||||
description: "When the user wants to plan a product launch, feature announcement, or release strategy. Also use when the user mentions 'launch,' 'Product Hunt,' 'feature release,' 'announcement,' 'go-to-market,' 'beta launch,' 'early access,' 'waitlist,' 'product update,' 'how do I launch this,' 'launch checklist,' 'GTM plan,' or 'we're about to ship.' Use this whenever someone is preparing to release something publicly. For ongoing marketing after launch, see marketing-ideas."
|
||||
description: "When the user wants to plan a product launch, feature announcement, or release strategy. Also use when the user mentions 'launch,' 'Product Hunt,' 'feature release,' 'announcement,' 'go-to-market,' 'beta launch,' 'early access,' 'waitlist,' or 'product update.' This skill covers phased launches, channel strategy, and ongoing launch momentum."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: marketing-ideas
|
||||
description: "When the user needs marketing ideas, inspiration, or strategies for their SaaS or software product. Also use when the user asks for 'marketing ideas,' 'growth ideas,' 'how to market,' 'marketing strategies,' 'marketing tactics,' 'ways to promote,' 'ideas to grow,' 'what else can I try,' 'I don't know how to market this,' 'brainstorm marketing,' or 'what marketing should I do.' Use this as a starting point whenever someone is stuck or looking for inspiration on how to grow. For specific channel execution, see the relevant skill (paid-ads, social-content, email-sequence, etc.)."
|
||||
description: "When the user needs marketing ideas, inspiration, or strategies for their SaaS or software product. Also use when the user asks for 'marketing ideas,' 'growth ideas,' 'how to market,' 'marketing strategies,' 'marketing tactics,' 'ways to promote,' or 'ideas to grow.' This skill provides 139 proven marketing approaches organized by category."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: marketing-psychology
|
||||
description: "When the user wants to apply psychological principles, mental models, or behavioral science to marketing. Also use when the user mentions 'psychology,' 'mental models,' 'cognitive bias,' 'persuasion,' 'behavioral science,' 'why people buy,' 'decision-making,' 'consumer behavior,' 'anchoring,' 'social proof,' 'scarcity,' 'loss aversion,' 'framing,' or 'nudge.' Use this whenever someone wants to understand or leverage how people think and make decisions in a marketing context."
|
||||
description: "When the user wants to apply psychological principles, mental models, or behavioral science to marketing. Also use when the user mentions 'psychology,' 'mental models,' 'cognitive bias,' 'persuasion,' 'behavioral science,' 'why people buy,' 'decision-making,' or 'consumer behavior.' This skill provides 70+ mental models organized for marketing application."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: onboarding-cro
|
||||
description: When the user wants to optimize post-signup onboarding, user activation, first-run experience, or time-to-value. Also use when the user mentions "onboarding flow," "activation rate," "user activation," "first-run experience," "empty states," "onboarding checklist," "aha moment," "new user experience," "users aren't activating," "nobody completes setup," "low activation rate," "users sign up but don't use the product," "time to value," or "first session experience." Use this whenever users are signing up but not sticking around. For signup/registration optimization, see signup-flow-cro. For ongoing email sequences, see email-sequence.
|
||||
description: When the user wants to optimize post-signup onboarding, user activation, first-run experience, or time-to-value. Also use when the user mentions "onboarding flow," "activation rate," "user activation," "first-run experience," "empty states," "onboarding checklist," "aha moment," or "new user experience." For signup/registration optimization, see signup-flow-cro. For ongoing email sequences, see email-sequence.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: page-cro
|
||||
description: When the user wants to optimize, improve, or increase conversions on any marketing page — including homepage, landing pages, pricing pages, feature pages, or blog posts. Also use when the user says "CRO," "conversion rate optimization," "this page isn't converting," "improve conversions," "why isn't this page working," "my landing page sucks," "nobody's converting," "low conversion rate," "bounce rate is too high," "people leave without signing up," or "this page needs work." Use this even if the user just shares a URL and asks for feedback — they probably want conversion help. For signup/registration flows, see signup-flow-cro. For post-signup activation, see onboarding-cro. For forms outside of signup, see form-cro. For popups/modals, see popup-cro.
|
||||
description: When the user wants to optimize, improve, or increase conversions on any marketing page — including homepage, landing pages, pricing pages, feature pages, or blog posts. Also use when the user says "CRO," "conversion rate optimization," "this page isn't converting," "improve conversions," or "why isn't this page working." For signup/registration flows, see signup-flow-cro. For post-signup activation, see onboarding-cro. For forms outside of signup, see form-cro. For popups/modals, see popup-cro.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: paid-ads
|
||||
description: "When the user wants help with paid advertising campaigns on Google Ads, Meta (Facebook/Instagram), LinkedIn, Twitter/X, or other ad platforms. Also use when the user mentions 'PPC,' 'paid media,' 'ROAS,' 'CPA,' 'ad campaign,' 'retargeting,' 'audience targeting,' 'Google Ads,' 'Facebook ads,' 'LinkedIn ads,' 'ad budget,' 'cost per click,' 'ad spend,' or 'should I run ads.' Use this for campaign strategy, audience targeting, bidding, and optimization. For bulk ad creative generation and iteration, see ad-creative. For landing page optimization, see page-cro."
|
||||
description: "When the user wants help with paid advertising campaigns on Google Ads, Meta (Facebook/Instagram), LinkedIn, Twitter/X, or other ad platforms. Also use when the user mentions 'PPC,' 'paid media,' 'ROAS,' 'CPA,' 'ad campaign,' 'retargeting,' or 'audience targeting.' This skill covers campaign strategy, audience targeting, and optimization. For bulk ad creative generation and iteration, see ad-creative."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: paywall-upgrade-cro
|
||||
description: When the user wants to create or optimize in-app paywalls, upgrade screens, upsell modals, or feature gates. Also use when the user mentions "paywall," "upgrade screen," "upgrade modal," "upsell," "feature gate," "convert free to paid," "freemium conversion," "trial expiration screen," "limit reached screen," "plan upgrade prompt," "in-app pricing," "free users won't upgrade," "trial to paid conversion," or "how do I get users to pay." Use this for any in-product moment where you're asking users to upgrade. Distinct from public pricing pages (see page-cro) — this focuses on in-product upgrade moments where the user has already experienced value. For pricing decisions, see pricing-strategy.
|
||||
description: When the user wants to create or optimize in-app paywalls, upgrade screens, upsell modals, or feature gates. Also use when the user mentions "paywall," "upgrade screen," "upgrade modal," "upsell," "feature gate," "convert free to paid," "freemium conversion," "trial expiration screen," "limit reached screen," "plan upgrade prompt," or "in-app pricing." Distinct from public pricing pages (see page-cro) — this skill focuses on in-product upgrade moments where the user has already experienced value.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: popup-cro
|
||||
description: When the user wants to create or optimize popups, modals, overlays, slide-ins, or banners for conversion purposes. Also use when the user mentions "exit intent," "popup conversions," "modal optimization," "lead capture popup," "email popup," "announcement banner," "overlay," "collect emails with a popup," "exit popup," "scroll trigger," "sticky bar," or "notification bar." Use this for any overlay or interrupt-style conversion element. For forms outside of popups, see form-cro. For general page conversion optimization, see page-cro.
|
||||
description: When the user wants to create or optimize popups, modals, overlays, slide-ins, or banners for conversion purposes. Also use when the user mentions "exit intent," "popup conversions," "modal optimization," "lead capture popup," "email popup," "announcement banner," or "overlay." For forms outside of popups, see form-cro. For general page conversion optimization, see page-cro.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: pricing-strategy
|
||||
description: "When the user wants help with pricing decisions, packaging, or monetization strategy. Also use when the user mentions 'pricing,' 'pricing tiers,' 'freemium,' 'free trial,' 'packaging,' 'price increase,' 'value metric,' 'Van Westendorp,' 'willingness to pay,' 'monetization,' 'how much should I charge,' 'my pricing is wrong,' 'pricing page,' 'annual vs monthly,' 'per seat pricing,' or 'should I offer a free plan.' Use this whenever someone is figuring out what to charge or how to structure their plans. For in-app upgrade screens, see paywall-upgrade-cro."
|
||||
description: "When the user wants help with pricing decisions, packaging, or monetization strategy. Also use when the user mentions 'pricing,' 'pricing tiers,' 'freemium,' 'free trial,' 'packaging,' 'price increase,' 'value metric,' 'Van Westendorp,' 'willingness to pay,' or 'monetization.' This skill covers pricing research, tier structure, and packaging strategy."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: product-marketing-context
|
||||
description: "When the user wants to create or update their product marketing context document. Also use when the user mentions 'product context,' 'marketing context,' 'set up context,' 'positioning,' 'who is my target audience,' 'describe my product,' 'ICP,' 'ideal customer profile,' or wants to avoid repeating foundational information across marketing tasks. Use this at the start of any new project before using other marketing skills — it creates `.agents/product-marketing-context.md` that all other skills reference for product, audience, and positioning context."
|
||||
description: "When the user wants to create or update their product marketing context document. Also use when the user mentions 'product context,' 'marketing context,' 'set up context,' 'positioning,' or wants to avoid repeating foundational information across marketing tasks. Creates `.agents/product-marketing-context.md` that other marketing skills reference."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: programmatic-seo
|
||||
description: When the user wants to create SEO-driven pages at scale using templates and data. Also use when the user mentions "programmatic SEO," "template pages," "pages at scale," "directory pages," "location pages," "[keyword] + [city] pages," "comparison pages," "integration pages," "building many pages for SEO," "pSEO," "generate 100 pages," "data-driven pages," or "templated landing pages." Use this whenever someone wants to create many similar pages targeting different keywords or locations. For auditing existing SEO issues, see seo-audit. For content strategy planning, see content-strategy.
|
||||
description: When the user wants to create SEO-driven pages at scale using templates and data. Also use when the user mentions "programmatic SEO," "template pages," "pages at scale," "directory pages," "location pages," "[keyword] + [city] pages," "comparison pages," "integration pages," or "building many pages for SEO." For auditing existing SEO issues, see seo-audit.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: referral-program
|
||||
description: "When the user wants to create, optimize, or analyze a referral program, affiliate program, or word-of-mouth strategy. Also use when the user mentions 'referral,' 'affiliate,' 'ambassador,' 'word of mouth,' 'viral loop,' 'refer a friend,' 'partner program,' 'referral incentive,' 'how to get referrals,' 'customers referring customers,' or 'affiliate payout.' Use this whenever someone wants existing users or partners to bring in new customers. For launch-specific virality, see launch-strategy."
|
||||
description: "When the user wants to create, optimize, or analyze a referral program, affiliate program, or word-of-mouth strategy. Also use when the user mentions 'referral,' 'affiliate,' 'ambassador,' 'word of mouth,' 'viral loop,' 'refer a friend,' or 'partner program.' This skill covers program design, incentive structure, and growth optimization."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: revops
|
||||
description: "When the user wants help with revenue operations, lead lifecycle management, or marketing-to-sales handoff processes. Also use when the user mentions 'RevOps,' 'revenue operations,' 'lead scoring,' 'lead routing,' 'MQL,' 'SQL,' 'pipeline stages,' 'deal desk,' 'CRM automation,' 'marketing-to-sales handoff,' 'data hygiene,' 'leads aren't getting to sales,' 'pipeline management,' 'lead qualification,' or 'when should marketing hand off to sales.' Use this for anything involving the systems and processes that connect marketing to revenue. For cold outreach emails, see cold-email. For email drip campaigns, see email-sequence. For pricing decisions, see pricing-strategy."
|
||||
description: "When the user wants help with revenue operations, lead lifecycle management, or marketing-to-sales handoff processes. Also use when the user mentions 'RevOps,' 'revenue operations,' 'lead scoring,' 'lead routing,' 'MQL,' 'SQL,' 'pipeline stages,' 'deal desk,' 'CRM automation,' 'marketing-to-sales handoff,' or 'data hygiene.' For cold outreach emails, see cold-email. For email drip campaigns, see email-sequence. For pricing decisions, see pricing-strategy."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: sales-enablement
|
||||
description: "When the user wants to create sales collateral, pitch decks, one-pagers, objection handling docs, or demo scripts. Also use when the user mentions 'sales deck,' 'pitch deck,' 'one-pager,' 'leave-behind,' 'objection handling,' 'deal-specific ROI analysis,' 'demo script,' 'talk track,' 'sales playbook,' 'proposal template,' 'buyer persona card,' 'help my sales team,' 'sales materials,' or 'what should I give my sales reps.' Use this for any document or asset that helps a sales team close deals. For competitor comparison pages and battle cards, see competitor-alternatives. For marketing website copy, see copywriting. For cold outreach emails, see cold-email."
|
||||
description: "When the user wants to create sales collateral, pitch decks, one-pagers, objection handling docs, or demo scripts. Also use when the user mentions 'sales deck,' 'pitch deck,' 'one-pager,' 'leave-behind,' 'objection handling,' 'ROI calculator,' 'demo script,' 'talk track,' 'sales playbook,' 'proposal template,' or 'buyer persona card.' For competitor battle cards and comparison pages, see competitor-alternatives. For marketing website copy, see copywriting. For cold outreach emails, see cold-email."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: schema-markup
|
||||
description: When the user wants to add, fix, or optimize schema markup and structured data on their site. Also use when the user mentions "schema markup," "structured data," "JSON-LD," "rich snippets," "schema.org," "FAQ schema," "product schema," "review schema," "breadcrumb schema," "Google rich results," "knowledge panel," "star ratings in search," or "add structured data." Use this whenever someone wants their pages to show enhanced results in Google. For broader SEO issues, see seo-audit. For AI search optimization, see ai-seo.
|
||||
description: When the user wants to add, fix, or optimize schema markup and structured data on their site. Also use when the user mentions "schema markup," "structured data," "JSON-LD," "rich snippets," "schema.org," "FAQ schema," "product schema," "review schema," or "breadcrumb schema." For broader SEO issues, see seo-audit.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: seo-audit
|
||||
description: When the user wants to audit, review, or diagnose SEO issues on their site. Also use when the user mentions "SEO audit," "technical SEO," "why am I not ranking," "SEO issues," "on-page SEO," "meta tags review," "SEO health check," "my traffic dropped," "lost rankings," "not showing up in Google," "site isn't ranking," "Google update hit me," "page speed," "core web vitals," "crawl errors," or "indexing issues." Use this even if the user just says something vague like "my SEO is bad" or "help with SEO" — start with an audit. For building pages at scale to target keywords, see programmatic-seo. For adding structured data, see schema-markup. For AI search optimization, see ai-seo.
|
||||
description: When the user wants to audit, review, or diagnose SEO issues on their site. Also use when the user mentions "SEO audit," "technical SEO," "why am I not ranking," "SEO issues," "on-page SEO," "meta tags review," or "SEO health check." For building pages at scale to target keywords, see programmatic-seo. For adding structured data, see schema-markup.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: signup-flow-cro
|
||||
description: When the user wants to optimize signup, registration, account creation, or trial activation flows. Also use when the user mentions "signup conversions," "registration friction," "signup form optimization," "free trial signup," "reduce signup dropoff," "account creation flow," "people aren't signing up," "signup abandonment," "trial conversion rate," "nobody completes registration," "too many steps to sign up," or "simplify our signup." Use this whenever the user has a signup or registration flow that isn't performing. For post-signup onboarding, see onboarding-cro. For lead capture forms (not account creation), see form-cro.
|
||||
description: When the user wants to optimize signup, registration, account creation, or trial activation flows. Also use when the user mentions "signup conversions," "registration friction," "signup form optimization," "free trial signup," "reduce signup dropoff," or "account creation flow." For post-signup onboarding, see onboarding-cro. For lead capture forms (not account creation), see form-cro.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: site-architecture
|
||||
description: When the user wants to plan, map, or restructure their website's page hierarchy, navigation, URL structure, or internal linking. Also use when the user mentions "sitemap," "site map," "visual sitemap," "site structure," "page hierarchy," "information architecture," "IA," "navigation design," "URL structure," "breadcrumbs," "internal linking strategy," "website planning," "what pages do I need," "how should I organize my site," or "site navigation." Use this whenever someone is planning what pages a website should have and how they connect. NOT for XML sitemaps (that's technical SEO — see seo-audit). For SEO audits, see seo-audit. For structured data, see schema-markup.
|
||||
description: When the user wants to plan, map, or restructure their website's page hierarchy, navigation, URL structure, or internal linking. Also use when the user mentions "sitemap," "site map," "visual sitemap," "site structure," "page hierarchy," "information architecture," "IA," "navigation design," "URL structure," "breadcrumbs," "internal linking strategy," or "website planning." NOT for XML sitemaps (that's technical SEO — see seo-audit). For SEO audits, see seo-audit. For structured data, see schema-markup.
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: social-content
|
||||
description: "When the user wants help creating, scheduling, or optimizing social media content for LinkedIn, Twitter/X, Instagram, TikTok, Facebook, or other platforms. Also use when the user mentions 'LinkedIn post,' 'Twitter thread,' 'social media,' 'content calendar,' 'social scheduling,' 'engagement,' 'viral content,' 'what should I post,' 'repurpose this content,' 'tweet ideas,' 'LinkedIn carousel,' 'social media strategy,' or 'grow my following.' Use this for any social media content creation, repurposing, or scheduling task. For broader content strategy, see content-strategy."
|
||||
description: "When the user wants help creating, scheduling, or optimizing social media content for LinkedIn, Twitter/X, Instagram, TikTok, Facebook, or other platforms. Also use when the user mentions 'LinkedIn post,' 'Twitter thread,' 'social media,' 'content calendar,' 'social scheduling,' 'engagement,' or 'viral content.' This skill covers content creation, repurposing, and platform-specific strategies."
|
||||
metadata:
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
+3
-82
@@ -28,13 +28,8 @@ Quick reference for AI agents to discover tool capabilities and integration meth
|
||||
| keywords-everywhere | SEO | ✓ | - | [✓](clis/keywords-everywhere.js) | - | [keywords-everywhere.md](integrations/keywords-everywhere.md) |
|
||||
| clearbit | Data Enrichment | ✓ | - | [✓](clis/clearbit.js) | ✓ | [clearbit.md](integrations/clearbit.md) |
|
||||
| apollo | Data Enrichment | ✓ | - | [✓](clis/apollo.js) | - | [apollo.md](integrations/apollo.md) |
|
||||
| zoominfo | Data Enrichment | ✓ | ✓ | [✓](clis/zoominfo.js) | - | [zoominfo.md](integrations/zoominfo.md) |
|
||||
| clay | Data Enrichment | ✓ | ✓ | [✓](clis/clay.js) | - | [clay.md](integrations/clay.md) |
|
||||
| supermetrics | Data Aggregation | ✓ | ✓ | [✓](clis/supermetrics.js) | - | [supermetrics.md](integrations/supermetrics.md) |
|
||||
| coupler | Data Aggregation | ✓ | ✓ | [✓](clis/coupler.js) | - | [coupler.md](integrations/coupler.md) |
|
||||
| hubspot | CRM | ✓ | - | ✓ | ✓ | [hubspot.md](integrations/hubspot.md) |
|
||||
| salesforce | CRM | ✓ | - | ✓ | ✓ | [salesforce.md](integrations/salesforce.md) |
|
||||
| close | CRM | ✓ | - | [✓](clis/close.js) | - | [close.md](integrations/close.md) |
|
||||
| stripe | Payments | ✓ | ✓ | ✓ | ✓ | [stripe.md](integrations/stripe.md) |
|
||||
| paddle | Payments | ✓ | - | [✓](clis/paddle.js) | ✓ | [paddle.md](integrations/paddle.md) |
|
||||
| rewardful | Referral | ✓ | - | [✓](clis/rewardful.js) | - | [rewardful.md](integrations/rewardful.md) |
|
||||
@@ -67,11 +62,6 @@ Quick reference for AI agents to discover tool capabilities and integration meth
|
||||
| savvycal | Scheduling | ✓ | - | [✓](clis/savvycal.js) | - | [savvycal.md](integrations/savvycal.md) |
|
||||
| typeform | Forms | ✓ | - | [✓](clis/typeform.js) | ✓ | [typeform.md](integrations/typeform.md) |
|
||||
| intercom | Messaging | ✓ | - | [✓](clis/intercom.js) | ✓ | [intercom.md](integrations/intercom.md) |
|
||||
| outreach | Sales Engagement | ✓ | ✓ | [✓](clis/outreach.js) | - | [outreach.md](integrations/outreach.md) |
|
||||
| crossbeam | Partner Ecosystem | ✓ | ✓ | [✓](clis/crossbeam.js) | - | [crossbeam.md](integrations/crossbeam.md) |
|
||||
| pendo | Product Analytics | ✓ | - | [✓](clis/pendo.js) | - | [pendo.md](integrations/pendo.md) |
|
||||
| similarweb | Competitive Intelligence | ✓ | - | [✓](clis/similarweb.js) | - | [similarweb.md](integrations/similarweb.md) |
|
||||
| airops | AI Content | ✓ | - | [✓](clis/airops.js) | - | [airops.md](integrations/airops.md) |
|
||||
| buffer | Social | ✓ | - | [✓](clis/buffer.js) | - | [buffer.md](integrations/buffer.md) |
|
||||
| wistia | Video | ✓ | - | [✓](clis/wistia.js) | - | [wistia.md](integrations/wistia.md) |
|
||||
| trustpilot | Reviews | ✓ | - | [✓](clis/trustpilot.js) | - | [trustpilot.md](integrations/trustpilot.md) |
|
||||
@@ -125,9 +115,8 @@ Customer relationship management and sales tools.
|
||||
|------|----------|:-------------:|
|
||||
| **hubspot** | SMB, marketing + sales alignment | ✓ |
|
||||
| **salesforce** | Enterprise, complex sales processes | ✓ |
|
||||
| **close** | SMB, high-velocity sales | [✓](clis/close.js) |
|
||||
|
||||
**Agent recommendation**: HubSpot for startups/SMBs. Close for high-velocity inside sales. Salesforce for enterprise.
|
||||
**Agent recommendation**: HubSpot for startups/SMBs, Salesforce for enterprise.
|
||||
|
||||
### Payments
|
||||
|
||||
@@ -136,6 +125,7 @@ Payment processing and subscription management.
|
||||
| Tool | Best For | MCP Available |
|
||||
|------|----------|:-------------:|
|
||||
| **stripe** | SaaS subscriptions, developer-friendly | ✓ |
|
||||
|
||||
| **paddle** | SaaS billing with tax handling | - |
|
||||
|
||||
**Agent recommendation**: Stripe is the default for SaaS. Paddle for built-in tax compliance.
|
||||
@@ -266,10 +256,8 @@ Company and person data enrichment for sales and marketing.
|
||||
|------|----------|-------|
|
||||
| **clearbit** | Company/person enrichment | Now HubSpot Breeze |
|
||||
| **apollo** | B2B prospecting, email finding | Large database |
|
||||
| **zoominfo** | B2B contacts, intent data | Enterprise-grade |
|
||||
| **clay** | Waterfall enrichment, outbound | 75+ data providers |
|
||||
|
||||
**Agent recommendation**: Clearbit for enrichment. Apollo for prospecting and outbound. ZoomInfo for enterprise B2B data with intent signals. Clay for waterfall enrichment across multiple providers.
|
||||
**Agent recommendation**: Clearbit for enrichment. Apollo for prospecting and outbound.
|
||||
|
||||
### Reviews
|
||||
|
||||
@@ -303,56 +291,6 @@ Webinar and virtual event platforms.
|
||||
|
||||
**Agent recommendation**: Demio for marketing-focused webinars. Livestorm for full event engagement.
|
||||
|
||||
### Sales Engagement
|
||||
|
||||
Sales engagement and outreach automation platforms.
|
||||
|
||||
| Tool | Best For | Notes |
|
||||
|------|----------|-------|
|
||||
| **outreach** | Enterprise sales engagement | Sequences, tasks, analytics |
|
||||
|
||||
**Agent recommendation**: Outreach for enterprise sales teams managing multi-touch sequences at scale.
|
||||
|
||||
### Product Analytics
|
||||
|
||||
Product analytics, feature adoption tracking, and in-app guidance.
|
||||
|
||||
| Tool | Best For | Notes |
|
||||
|------|----------|-------|
|
||||
| **pendo** | Feature adoption, in-app guides | Product-led growth |
|
||||
|
||||
**Agent recommendation**: Pendo for tracking feature adoption and delivering targeted in-app guidance.
|
||||
|
||||
### Competitive Intelligence
|
||||
|
||||
Traffic analytics, competitor benchmarking, and market research.
|
||||
|
||||
| Tool | Best For | Notes |
|
||||
|------|----------|-------|
|
||||
| **similarweb** | Website traffic, competitor analysis | Traffic sources, keywords |
|
||||
|
||||
**Agent recommendation**: Similarweb for competitor traffic analysis and market benchmarking.
|
||||
|
||||
### AI Content
|
||||
|
||||
AI-powered content generation and optimization platforms.
|
||||
|
||||
| Tool | Best For | Notes |
|
||||
|------|----------|-------|
|
||||
| **airops** | AI content workflows, SEO content | Flow-based automation |
|
||||
|
||||
**Agent recommendation**: AirOps for building AI content workflows that generate SEO-optimized content at scale.
|
||||
|
||||
### Partner Ecosystem
|
||||
|
||||
Partner data sharing, co-sell, and ecosystem management.
|
||||
|
||||
| Tool | Best For | Notes |
|
||||
|------|----------|-------|
|
||||
| **crossbeam** | Account overlaps, co-sell | Now part of Reveal |
|
||||
|
||||
**Agent recommendation**: Crossbeam for identifying partner account overlaps and co-sell opportunities.
|
||||
|
||||
### Email Outreach
|
||||
|
||||
Cold email outreach and email finding tools for link building and sales prospecting.
|
||||
@@ -366,17 +304,6 @@ Cold email outreach and email finding tools for link building and sales prospect
|
||||
|
||||
**Agent recommendation**: Hunter for finding emails. Lemlist or Instantly for sending cold email campaigns. Snov for combined finding + outreach.
|
||||
|
||||
### Data Aggregation
|
||||
|
||||
Marketing data pipeline tools that connect multiple platforms for unified reporting.
|
||||
|
||||
| Tool | Best For | Notes |
|
||||
|------|----------|-------|
|
||||
| **supermetrics** | Cross-platform data pulling | 200+ connectors |
|
||||
| **coupler** | Automated data flows to sheets/BI | Scheduled pipelines |
|
||||
|
||||
**Agent recommendation**: Supermetrics for pulling data from multiple marketing platforms into unified reports. Coupler.io for automated data flows to spreadsheets and BI tools.
|
||||
|
||||
### Commerce & CMS
|
||||
|
||||
E-commerce platforms and content management systems.
|
||||
@@ -413,12 +340,6 @@ These tools have Model Context Protocol servers available, enabling direct agent
|
||||
- **google-ads** - Ad campaign management
|
||||
- **resend** - Transactional email sending
|
||||
- **zapier** - Workflow automation
|
||||
- **zoominfo** - B2B contacts and intent data
|
||||
- **clay** - Data enrichment and outbound automation
|
||||
- **supermetrics** - Cross-platform marketing data
|
||||
- **coupler** - Marketing data pipelines
|
||||
- **outreach** - Sales engagement sequences
|
||||
- **crossbeam** - Partner ecosystem data
|
||||
|
||||
To use MCP tools, ensure the appropriate MCP server is configured in your environment.
|
||||
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const API_KEY = process.env.AIROPS_API_KEY
|
||||
const WORKSPACE_ID = process.env.AIROPS_WORKSPACE_ID
|
||||
const BASE_URL = 'https://api.airops.com/public_api/v1'
|
||||
|
||||
if (!API_KEY) {
|
||||
console.error(JSON.stringify({ error: 'AIROPS_API_KEY environment variable required' }))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (!WORKSPACE_ID) {
|
||||
console.error(JSON.stringify({ error: 'AIROPS_WORKSPACE_ID environment variable required' }))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function api(method, path, body) {
|
||||
const url = `${BASE_URL}${path}`
|
||||
if (args['dry-run']) {
|
||||
return { _dry_run: true, method, url, headers: { 'Authorization': 'Bearer ***', 'Content-Type': 'application/json' }, body: body || undefined }
|
||||
}
|
||||
const res = await fetch(url, {
|
||||
method,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${API_KEY}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
const text = await res.text()
|
||||
try {
|
||||
return JSON.parse(text)
|
||||
} catch {
|
||||
return { status: res.status, body: text }
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgs(args) {
|
||||
const result = { _: [] }
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg.startsWith('--')) {
|
||||
const key = arg.slice(2)
|
||||
const next = args[i + 1]
|
||||
if (next && !next.startsWith('--')) {
|
||||
result[key] = next
|
||||
i++
|
||||
} else {
|
||||
result[key] = true
|
||||
}
|
||||
} else {
|
||||
result._.push(arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const args = parseArgs(process.argv.slice(2))
|
||||
const [cmd, sub, ...rest] = args._
|
||||
|
||||
async function main() {
|
||||
let result
|
||||
|
||||
switch (cmd) {
|
||||
case 'flows':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
result = await api('GET', `/workspaces/${WORKSPACE_ID}/flows`)
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/workspaces/${WORKSPACE_ID}/flows/${id}`)
|
||||
break
|
||||
}
|
||||
case 'execute': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
const inputs = args.inputs
|
||||
let parsedInputs = {}
|
||||
if (inputs) {
|
||||
try {
|
||||
parsedInputs = JSON.parse(inputs)
|
||||
} catch {
|
||||
result = { error: '--inputs must be valid JSON' }
|
||||
break
|
||||
}
|
||||
}
|
||||
result = await api('POST', `/workspaces/${WORKSPACE_ID}/flows/${id}/execute`, { inputs: parsedInputs })
|
||||
break
|
||||
}
|
||||
case 'runs': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/workspaces/${WORKSPACE_ID}/flows/${id}/runs`)
|
||||
break
|
||||
}
|
||||
case 'run-status': {
|
||||
const runId = args['run-id']
|
||||
if (!runId) { result = { error: '--run-id required' }; break }
|
||||
result = await api('GET', `/workspaces/${WORKSPACE_ID}/runs/${runId}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown flows subcommand. Use: list, get, execute, runs, run-status' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'workflows':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
result = await api('GET', `/workspaces/${WORKSPACE_ID}/workflows`)
|
||||
break
|
||||
}
|
||||
case 'execute': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
const inputs = args.inputs
|
||||
let parsedInputs = {}
|
||||
if (inputs) {
|
||||
try {
|
||||
parsedInputs = JSON.parse(inputs)
|
||||
} catch {
|
||||
result = { error: '--inputs must be valid JSON' }
|
||||
break
|
||||
}
|
||||
}
|
||||
result = await api('POST', `/workspaces/${WORKSPACE_ID}/workflows/${id}/execute`, { inputs: parsedInputs })
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown workflows subcommand. Use: list, execute' }
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
result = {
|
||||
error: 'Unknown command',
|
||||
usage: {
|
||||
flows: {
|
||||
list: 'flows list',
|
||||
get: 'flows get --id <id>',
|
||||
execute: 'flows execute --id <id> --inputs <json>',
|
||||
runs: 'flows runs --id <id>',
|
||||
'run-status': 'flows run-status --run-id <id>',
|
||||
},
|
||||
workflows: {
|
||||
list: 'workflows list',
|
||||
execute: 'workflows execute --id <id> --inputs <json>',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(result, null, 2))
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(JSON.stringify({ error: err.message }))
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -1,159 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const API_KEY = process.env.CLAY_API_KEY
|
||||
const BASE_URL = 'https://api.clay.com/v3'
|
||||
|
||||
if (!API_KEY) {
|
||||
console.error(JSON.stringify({ error: 'CLAY_API_KEY environment variable required' }))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function api(method, path, body) {
|
||||
if (args['dry-run']) {
|
||||
return { _dry_run: true, method, url: `${BASE_URL}${path}`, headers: { 'Authorization': 'Bearer ***', 'Content-Type': 'application/json' }, body: body || undefined }
|
||||
}
|
||||
const options = {
|
||||
method,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${API_KEY}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
if (body) options.body = JSON.stringify(body)
|
||||
const res = await fetch(`${BASE_URL}${path}`, options)
|
||||
const text = await res.text()
|
||||
try {
|
||||
return JSON.parse(text)
|
||||
} catch {
|
||||
return { status: res.status, body: text }
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgs(args) {
|
||||
const result = { _: [] }
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg.startsWith('--')) {
|
||||
const key = arg.slice(2)
|
||||
const next = args[i + 1]
|
||||
if (next && !next.startsWith('--')) {
|
||||
result[key] = next
|
||||
i++
|
||||
} else {
|
||||
result[key] = true
|
||||
}
|
||||
} else {
|
||||
result._.push(arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const args = parseArgs(process.argv.slice(2))
|
||||
const [cmd, sub, ...rest] = args._
|
||||
|
||||
async function main() {
|
||||
let result
|
||||
const page = args.page ? Number(args.page) : 1
|
||||
const perPage = args['per-page'] ? Number(args['per-page']) : 25
|
||||
|
||||
switch (cmd) {
|
||||
case 'tables':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
result = await api('GET', `/tables?page=${page}&per_page=${perPage}`)
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/tables/${id}`)
|
||||
break
|
||||
}
|
||||
case 'rows': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/tables/${id}/rows?page=${page}&per_page=${perPage}`)
|
||||
break
|
||||
}
|
||||
case 'add-row': {
|
||||
const id = args.id
|
||||
const data = args.data
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
if (!data) { result = { error: '--data required (JSON string)' }; break }
|
||||
let parsed
|
||||
try {
|
||||
parsed = JSON.parse(data)
|
||||
} catch {
|
||||
result = { error: 'Invalid JSON in --data' }
|
||||
break
|
||||
}
|
||||
result = await api('POST', `/tables/${id}/rows`, parsed)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown tables subcommand. Use: list, get, rows, add-row' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'people':
|
||||
switch (sub) {
|
||||
case 'enrich': {
|
||||
const body = {}
|
||||
if (args.email) body.email = args.email
|
||||
if (args.linkedin) body.linkedin_url = args.linkedin
|
||||
if (args['first-name']) body.first_name = args['first-name']
|
||||
if (args['last-name']) body.last_name = args['last-name']
|
||||
if (args['first-name'] && args['last-name'] && args.domain) body.domain = args.domain
|
||||
if (!args.email && !args.linkedin && !(args['first-name'] && args['last-name'] && args.domain)) {
|
||||
result = { error: '--email or --linkedin required (or --first-name + --last-name + --domain)' }
|
||||
break
|
||||
}
|
||||
result = await api('POST', '/people/enrich', body)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown people subcommand. Use: enrich' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'companies':
|
||||
switch (sub) {
|
||||
case 'enrich': {
|
||||
const domain = args.domain
|
||||
if (!domain) { result = { error: '--domain required' }; break }
|
||||
result = await api('POST', '/companies/enrich', { domain })
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown companies subcommand. Use: enrich' }
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
result = {
|
||||
error: 'Unknown command',
|
||||
usage: {
|
||||
tables: {
|
||||
list: 'tables list [--page <n>] [--per-page <n>]',
|
||||
get: 'tables get --id <table_id>',
|
||||
rows: 'tables rows --id <table_id> [--page <n>] [--per-page <n>]',
|
||||
'add-row': 'tables add-row --id <table_id> --data <json>',
|
||||
},
|
||||
people: {
|
||||
enrich: 'people enrich --email <email> | --linkedin <url> | --first-name <n> --last-name <n> --domain <d>',
|
||||
},
|
||||
companies: {
|
||||
enrich: 'companies enrich --domain <domain>',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(result, null, 2))
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(JSON.stringify({ error: err.message }))
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -1,232 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const API_KEY = process.env.CLOSE_API_KEY
|
||||
const BASE_URL = 'https://api.close.com/api/v1'
|
||||
|
||||
if (!API_KEY) {
|
||||
console.error(JSON.stringify({ error: 'CLOSE_API_KEY environment variable required' }))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function api(method, path, body) {
|
||||
const url = `${BASE_URL}${path}`
|
||||
if (args['dry-run']) {
|
||||
return { _dry_run: true, method, url, headers: { 'Content-Type': 'application/json', 'Authorization': 'Basic ***' }, body: body || undefined }
|
||||
}
|
||||
const res = await fetch(url, {
|
||||
method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'Authorization': `Basic ${btoa(API_KEY + ':')}`,
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
const text = await res.text()
|
||||
try {
|
||||
return JSON.parse(text)
|
||||
} catch {
|
||||
return { status: res.status, body: text }
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgs(args) {
|
||||
const result = { _: [] }
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg.startsWith('--')) {
|
||||
const key = arg.slice(2)
|
||||
const next = args[i + 1]
|
||||
if (next && !next.startsWith('--')) {
|
||||
result[key] = next
|
||||
i++
|
||||
} else {
|
||||
result[key] = true
|
||||
}
|
||||
} else {
|
||||
result._.push(arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const args = parseArgs(process.argv.slice(2))
|
||||
const [cmd, sub, ...rest] = args._
|
||||
|
||||
async function main() {
|
||||
let result
|
||||
|
||||
switch (cmd) {
|
||||
case 'leads':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
const params = new URLSearchParams()
|
||||
if (args.query) params.set('query', args.query)
|
||||
if (args.page) params.set('_skip', (parseInt(args.page) - 1) * 100)
|
||||
const qs = params.toString()
|
||||
result = await api('GET', `/lead/${qs ? '?' + qs : ''}`)
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/lead/${id}/`)
|
||||
break
|
||||
}
|
||||
case 'create': {
|
||||
const name = args.name
|
||||
if (!name) { result = { error: '--name required' }; break }
|
||||
const body = { name }
|
||||
if (args.url) body.url = args.url
|
||||
if (args.description) body.description = args.description
|
||||
result = await api('POST', '/lead/', body)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown leads subcommand. Use: list, get, create' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'contacts':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
const params = new URLSearchParams()
|
||||
if (args['lead-id']) params.set('lead_id', args['lead-id'])
|
||||
const qs = params.toString()
|
||||
result = await api('GET', `/contact/${qs ? '?' + qs : ''}`)
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/contact/${id}/`)
|
||||
break
|
||||
}
|
||||
case 'create': {
|
||||
const leadId = args['lead-id']
|
||||
const name = args.name
|
||||
if (!leadId) { result = { error: '--lead-id required' }; break }
|
||||
if (!name) { result = { error: '--name required' }; break }
|
||||
const body = { lead_id: leadId, name }
|
||||
if (args.email) {
|
||||
body.emails = [{ email: args.email, type: 'office' }]
|
||||
}
|
||||
if (args.phone) {
|
||||
body.phones = [{ phone: args.phone, type: 'office' }]
|
||||
}
|
||||
result = await api('POST', '/contact/', body)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown contacts subcommand. Use: list, get, create' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'opportunities':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
const params = new URLSearchParams()
|
||||
if (args.status) params.set('status', args.status)
|
||||
const qs = params.toString()
|
||||
result = await api('GET', `/opportunity/${qs ? '?' + qs : ''}`)
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/opportunity/${id}/`)
|
||||
break
|
||||
}
|
||||
case 'create': {
|
||||
const leadId = args['lead-id']
|
||||
const value = args.value
|
||||
if (!leadId) { result = { error: '--lead-id required' }; break }
|
||||
if (!value) { result = { error: '--value required (in cents)' }; break }
|
||||
const body = { lead_id: leadId, value: parseInt(value) }
|
||||
if (args.status) body.status_type = args.status
|
||||
result = await api('POST', '/opportunity/', body)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown opportunities subcommand. Use: list, get, create' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'activities':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
const params = new URLSearchParams()
|
||||
if (args['lead-id']) params.set('lead_id', args['lead-id'])
|
||||
if (args.type) params.set('_type__type', args.type)
|
||||
const qs = params.toString()
|
||||
result = await api('GET', `/activity/${qs ? '?' + qs : ''}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown activities subcommand. Use: list' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'tasks':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
const params = new URLSearchParams()
|
||||
if (args['assigned-to']) params.set('assigned_to', args['assigned-to'])
|
||||
if (args['is-complete']) params.set('is_complete', args['is-complete'])
|
||||
const qs = params.toString()
|
||||
result = await api('GET', `/task/${qs ? '?' + qs : ''}`)
|
||||
break
|
||||
}
|
||||
case 'create': {
|
||||
const leadId = args['lead-id']
|
||||
const text = args.text
|
||||
if (!leadId) { result = { error: '--lead-id required' }; break }
|
||||
if (!text) { result = { error: '--text required' }; break }
|
||||
const body = { lead_id: leadId, text, _type: 'lead' }
|
||||
if (args['assigned-to']) body.assigned_to = args['assigned-to']
|
||||
if (args.date) body.date = args.date
|
||||
result = await api('POST', '/task/', body)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown tasks subcommand. Use: list, create' }
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
result = {
|
||||
error: 'Unknown command',
|
||||
usage: {
|
||||
leads: {
|
||||
list: 'leads list [--query <q>] [--page <n>]',
|
||||
get: 'leads get --id <id>',
|
||||
create: 'leads create --name <name> [--url <url>] [--description <desc>]',
|
||||
},
|
||||
contacts: {
|
||||
list: 'contacts list [--lead-id <id>]',
|
||||
get: 'contacts get --id <id>',
|
||||
create: 'contacts create --lead-id <id> --name <name> [--email <email>] [--phone <phone>]',
|
||||
},
|
||||
opportunities: {
|
||||
list: 'opportunities list [--status <status>]',
|
||||
get: 'opportunities get --id <id>',
|
||||
create: 'opportunities create --lead-id <id> --value <cents> [--status <status>]',
|
||||
},
|
||||
activities: {
|
||||
list: 'activities list [--lead-id <id>] [--type <type>]',
|
||||
},
|
||||
tasks: {
|
||||
list: 'tasks list [--assigned-to <user-id>] [--is-complete <bool>]',
|
||||
create: 'tasks create --lead-id <id> --text <text> [--assigned-to <user-id>] [--date <date>]',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(result, null, 2))
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(JSON.stringify({ error: err.message }))
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -1,173 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const API_KEY = process.env.COUPLER_API_KEY
|
||||
const BASE_URL = 'https://api.coupler.io/v1'
|
||||
|
||||
if (!API_KEY) {
|
||||
console.error(JSON.stringify({ error: 'COUPLER_API_KEY environment variable required' }))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function api(method, path, body) {
|
||||
if (args['dry-run']) {
|
||||
return { _dry_run: true, method, url: `${BASE_URL}${path}`, headers: { 'Authorization': 'Bearer ***', 'Content-Type': 'application/json' }, body: body || undefined }
|
||||
}
|
||||
const res = await fetch(`${BASE_URL}${path}`, {
|
||||
method,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${API_KEY}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
const text = await res.text()
|
||||
try {
|
||||
return JSON.parse(text)
|
||||
} catch {
|
||||
return { status: res.status, body: text }
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgs(args) {
|
||||
const result = { _: [] }
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg.startsWith('--')) {
|
||||
const key = arg.slice(2)
|
||||
const next = args[i + 1]
|
||||
if (next && !next.startsWith('--')) {
|
||||
result[key] = next
|
||||
i++
|
||||
} else {
|
||||
result[key] = true
|
||||
}
|
||||
} else {
|
||||
result._.push(arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const args = parseArgs(process.argv.slice(2))
|
||||
const [cmd, sub, ...rest] = args._
|
||||
|
||||
async function main() {
|
||||
let result
|
||||
|
||||
switch (cmd) {
|
||||
case 'importers':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
const params = new URLSearchParams()
|
||||
if (args.limit) params.set('limit', args.limit)
|
||||
if (args.offset) params.set('offset', args.offset)
|
||||
const qs = params.toString()
|
||||
result = await api('GET', `/importers${qs ? '?' + qs : ''}`)
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/importers/${id}`)
|
||||
break
|
||||
}
|
||||
case 'run': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('POST', `/importers/${id}/run`)
|
||||
break
|
||||
}
|
||||
case 'create': {
|
||||
const source = args.source
|
||||
const destination = args.destination
|
||||
const name = args.name
|
||||
if (!source) { result = { error: '--source required' }; break }
|
||||
if (!destination) { result = { error: '--destination required' }; break }
|
||||
if (!name) { result = { error: '--name required' }; break }
|
||||
const body = { source_type: source, destination_type: destination, name }
|
||||
if (args.schedule) body.schedule = args.schedule
|
||||
result = await api('POST', '/importers', body)
|
||||
break
|
||||
}
|
||||
case 'delete': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('DELETE', `/importers/${id}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown importers subcommand. Use: list, get, run, create, delete' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'runs':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
const importerId = args['importer-id']
|
||||
if (!importerId) { result = { error: '--importer-id required' }; break }
|
||||
const params = new URLSearchParams()
|
||||
if (args.limit) params.set('limit', args.limit)
|
||||
if (args.offset) params.set('offset', args.offset)
|
||||
const qs = params.toString()
|
||||
result = await api('GET', `/importers/${importerId}/runs${qs ? '?' + qs : ''}`)
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/runs/${id}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown runs subcommand. Use: list, get' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'sources':
|
||||
switch (sub) {
|
||||
case 'list':
|
||||
result = await api('GET', '/sources')
|
||||
break
|
||||
default:
|
||||
result = { error: 'Unknown sources subcommand. Use: list' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'destinations':
|
||||
switch (sub) {
|
||||
case 'list':
|
||||
result = await api('GET', '/destinations')
|
||||
break
|
||||
default:
|
||||
result = { error: 'Unknown destinations subcommand. Use: list' }
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
result = {
|
||||
error: 'Unknown command',
|
||||
usage: {
|
||||
importers: {
|
||||
list: 'importers list [--limit <n>] [--offset <n>]',
|
||||
get: 'importers get --id <id>',
|
||||
run: 'importers run --id <id>',
|
||||
create: 'importers create --source <source-type> --destination <dest-type> --name <name> [--schedule <schedule>]',
|
||||
delete: 'importers delete --id <id>',
|
||||
},
|
||||
runs: {
|
||||
list: 'runs list --importer-id <id> [--limit <n>] [--offset <n>]',
|
||||
get: 'runs get --id <id>',
|
||||
},
|
||||
sources: 'sources list',
|
||||
destinations: 'destinations list',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(result, null, 2))
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(JSON.stringify({ error: err.message }))
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -1,193 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const API_KEY = process.env.CROSSBEAM_API_KEY
|
||||
const BASE_URL = 'https://api.crossbeam.com/v1'
|
||||
|
||||
if (!API_KEY) {
|
||||
console.error(JSON.stringify({ error: 'CROSSBEAM_API_KEY environment variable required' }))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function api(method, path, body) {
|
||||
const url = `${BASE_URL}${path}`
|
||||
if (args['dry-run']) {
|
||||
return { _dry_run: true, method, url, headers: { 'Authorization': 'Bearer ***', 'Content-Type': 'application/json' }, body: body || undefined }
|
||||
}
|
||||
const res = await fetch(url, {
|
||||
method,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${API_KEY}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
const text = await res.text()
|
||||
try {
|
||||
return JSON.parse(text)
|
||||
} catch {
|
||||
return { status: res.status, body: text }
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgs(args) {
|
||||
const result = { _: [] }
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg.startsWith('--')) {
|
||||
const key = arg.slice(2)
|
||||
const next = args[i + 1]
|
||||
if (next && !next.startsWith('--')) {
|
||||
result[key] = next
|
||||
i++
|
||||
} else {
|
||||
result[key] = true
|
||||
}
|
||||
} else {
|
||||
result._.push(arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const args = parseArgs(process.argv.slice(2))
|
||||
const [cmd, sub, ...rest] = args._
|
||||
|
||||
async function main() {
|
||||
let result
|
||||
|
||||
switch (cmd) {
|
||||
case 'partners':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
result = await api('GET', '/partners')
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/partners/${id}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown partners subcommand. Use: list, get' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'populations':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
result = await api('GET', '/populations')
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/populations/${id}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown populations subcommand. Use: list, get' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'overlaps':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
const params = new URLSearchParams()
|
||||
if (args['partner-id']) params.set('partner_id', args['partner-id'])
|
||||
if (args['population-id']) params.set('population_id', args['population-id'])
|
||||
const qs = params.toString()
|
||||
result = await api('GET', `/overlaps${qs ? '?' + qs : ''}`)
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/overlaps/${id}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown overlaps subcommand. Use: list, get' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'reports':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
result = await api('GET', '/reports')
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/reports/${id}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown reports subcommand. Use: list, get' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'threads':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
result = await api('GET', '/threads')
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown threads subcommand. Use: list' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'accounts':
|
||||
switch (sub) {
|
||||
case 'search': {
|
||||
const domain = args.domain
|
||||
if (!domain) { result = { error: '--domain required' }; break }
|
||||
const params = new URLSearchParams({ domain })
|
||||
result = await api('GET', `/accounts/search?${params.toString()}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown accounts subcommand. Use: search' }
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
result = {
|
||||
error: 'Unknown command',
|
||||
usage: {
|
||||
partners: {
|
||||
list: 'partners list',
|
||||
get: 'partners get --id <id>',
|
||||
},
|
||||
populations: {
|
||||
list: 'populations list',
|
||||
get: 'populations get --id <id>',
|
||||
},
|
||||
overlaps: {
|
||||
list: 'overlaps list [--partner-id <id>] [--population-id <id>]',
|
||||
get: 'overlaps get --id <id>',
|
||||
},
|
||||
reports: {
|
||||
list: 'reports list',
|
||||
get: 'reports get --id <id>',
|
||||
},
|
||||
threads: {
|
||||
list: 'threads list',
|
||||
},
|
||||
accounts: {
|
||||
search: 'accounts search --domain <domain>',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(result, null, 2))
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(JSON.stringify({ error: err.message }))
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -1,213 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const ACCESS_TOKEN = process.env.OUTREACH_ACCESS_TOKEN
|
||||
const BASE_URL = 'https://api.outreach.io/api/v2'
|
||||
|
||||
if (!ACCESS_TOKEN) {
|
||||
console.error(JSON.stringify({ error: 'OUTREACH_ACCESS_TOKEN environment variable required' }))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function api(method, path, body) {
|
||||
const url = `${BASE_URL}${path}`
|
||||
if (args['dry-run']) {
|
||||
return { _dry_run: true, method, url, headers: { 'Authorization': 'Bearer ***', 'Content-Type': 'application/vnd.api+json', 'Accept': 'application/vnd.api+json' }, body: body || undefined }
|
||||
}
|
||||
const res = await fetch(url, {
|
||||
method,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${ACCESS_TOKEN}`,
|
||||
'Content-Type': 'application/vnd.api+json',
|
||||
'Accept': 'application/vnd.api+json',
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
const text = await res.text()
|
||||
try {
|
||||
return JSON.parse(text)
|
||||
} catch {
|
||||
return { status: res.status, body: text }
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgs(args) {
|
||||
const result = { _: [] }
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg.startsWith('--')) {
|
||||
const key = arg.slice(2)
|
||||
const next = args[i + 1]
|
||||
if (next && !next.startsWith('--')) {
|
||||
result[key] = next
|
||||
i++
|
||||
} else {
|
||||
result[key] = true
|
||||
}
|
||||
} else {
|
||||
result._.push(arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const args = parseArgs(process.argv.slice(2))
|
||||
const [cmd, sub, ...rest] = args._
|
||||
|
||||
async function main() {
|
||||
let result
|
||||
|
||||
switch (cmd) {
|
||||
case 'prospects':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
const params = new URLSearchParams()
|
||||
if (args.page) params.set('page[number]', args.page)
|
||||
if (args['per-page']) params.set('page[size]', args['per-page'])
|
||||
const qs = params.toString()
|
||||
result = await api('GET', `/prospects${qs ? '?' + qs : ''}`)
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/prospects/${id}`)
|
||||
break
|
||||
}
|
||||
case 'create': {
|
||||
const email = args.email
|
||||
if (!email) { result = { error: '--email required' }; break }
|
||||
const attributes = { emails: [email] }
|
||||
if (args['first-name']) attributes.firstName = args['first-name']
|
||||
if (args['last-name']) attributes.lastName = args['last-name']
|
||||
const body = { data: { type: 'prospect', attributes } }
|
||||
result = await api('POST', '/prospects', body)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown prospects subcommand. Use: list, get, create' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'sequences':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
result = await api('GET', '/sequences')
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/sequences/${id}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown sequences subcommand. Use: list, get' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'sequence-states':
|
||||
switch (sub) {
|
||||
case 'create': {
|
||||
const sequenceId = args['sequence-id']
|
||||
const prospectId = args['prospect-id']
|
||||
if (!sequenceId) { result = { error: '--sequence-id required' }; break }
|
||||
if (!prospectId) { result = { error: '--prospect-id required' }; break }
|
||||
const body = {
|
||||
data: {
|
||||
type: 'sequenceState',
|
||||
relationships: {
|
||||
prospect: { data: { type: 'prospect', id: prospectId } },
|
||||
sequence: { data: { type: 'sequence', id: sequenceId } },
|
||||
},
|
||||
},
|
||||
}
|
||||
result = await api('POST', '/sequenceStates', body)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown sequence-states subcommand. Use: create' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'mailings':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
const params = new URLSearchParams()
|
||||
if (args['sequence-id']) params.set('filter[sequence][id]', args['sequence-id'])
|
||||
const qs = params.toString()
|
||||
result = await api('GET', `/mailings${qs ? '?' + qs : ''}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown mailings subcommand. Use: list' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'accounts':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
result = await api('GET', '/accounts')
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/accounts/${id}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown accounts subcommand. Use: list, get' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'tasks':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
const params = new URLSearchParams()
|
||||
if (args.status) params.set('filter[status]', args.status)
|
||||
const qs = params.toString()
|
||||
result = await api('GET', `/tasks${qs ? '?' + qs : ''}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown tasks subcommand. Use: list' }
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
result = {
|
||||
error: 'Unknown command',
|
||||
usage: {
|
||||
prospects: {
|
||||
list: 'prospects list [--page <n>] [--per-page <n>]',
|
||||
get: 'prospects get --id <id>',
|
||||
create: 'prospects create --email <email> [--first-name <name>] [--last-name <name>]',
|
||||
},
|
||||
sequences: {
|
||||
list: 'sequences list',
|
||||
get: 'sequences get --id <id>',
|
||||
},
|
||||
'sequence-states': {
|
||||
create: 'sequence-states create --sequence-id <id> --prospect-id <id>',
|
||||
},
|
||||
mailings: {
|
||||
list: 'mailings list [--sequence-id <id>]',
|
||||
},
|
||||
accounts: {
|
||||
list: 'accounts list',
|
||||
get: 'accounts get --id <id>',
|
||||
},
|
||||
tasks: {
|
||||
list: 'tasks list [--status <status>]',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(result, null, 2))
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(JSON.stringify({ error: err.message }))
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -1,221 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const API_KEY = process.env.PENDO_INTEGRATION_KEY
|
||||
const BASE_URL = 'https://app.pendo.io/api/v1'
|
||||
|
||||
if (!API_KEY) {
|
||||
console.error(JSON.stringify({ error: 'PENDO_INTEGRATION_KEY environment variable required' }))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function api(method, path, body) {
|
||||
const url = `${BASE_URL}${path}`
|
||||
if (args['dry-run']) {
|
||||
return { _dry_run: true, method, url, headers: { 'Content-Type': 'application/json', 'x-pendo-integration-key': '***' }, body: body || undefined }
|
||||
}
|
||||
const res = await fetch(url, {
|
||||
method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'x-pendo-integration-key': API_KEY,
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
const text = await res.text()
|
||||
try {
|
||||
return JSON.parse(text)
|
||||
} catch {
|
||||
return { status: res.status, body: text }
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgs(args) {
|
||||
const result = { _: [] }
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg.startsWith('--')) {
|
||||
const key = arg.slice(2)
|
||||
const next = args[i + 1]
|
||||
if (next && !next.startsWith('--')) {
|
||||
result[key] = next
|
||||
i++
|
||||
} else {
|
||||
result[key] = true
|
||||
}
|
||||
} else {
|
||||
result._.push(arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const args = parseArgs(process.argv.slice(2))
|
||||
const [cmd, sub, ...rest] = args._
|
||||
|
||||
async function main() {
|
||||
let result
|
||||
|
||||
switch (cmd) {
|
||||
case 'features':
|
||||
switch (sub) {
|
||||
case 'list':
|
||||
result = await api('GET', '/feature')
|
||||
break
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/feature/${id}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown features subcommand. Use: list, get' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'pages':
|
||||
switch (sub) {
|
||||
case 'list':
|
||||
result = await api('GET', '/page')
|
||||
break
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/page/${id}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown pages subcommand. Use: list, get' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'guides':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
const params = new URLSearchParams()
|
||||
if (args.state) params.set('state', args.state)
|
||||
const qs = params.toString()
|
||||
result = await api('GET', `/guide${qs ? '?' + qs : ''}`)
|
||||
break
|
||||
}
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/guide/${id}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown guides subcommand. Use: list, get' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'visitors':
|
||||
switch (sub) {
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/visitor/${id}`)
|
||||
break
|
||||
}
|
||||
case 'search': {
|
||||
const query = args.query
|
||||
if (!query) { result = { error: '--query <json> required' }; break }
|
||||
let body
|
||||
try { body = JSON.parse(query) } catch { result = { error: 'Invalid JSON in --query' }; break }
|
||||
result = await api('POST', '/aggregation', body)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown visitors subcommand. Use: get, search' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'accounts':
|
||||
switch (sub) {
|
||||
case 'get': {
|
||||
const id = args.id
|
||||
if (!id) { result = { error: '--id required' }; break }
|
||||
result = await api('GET', `/account/${id}`)
|
||||
break
|
||||
}
|
||||
case 'search': {
|
||||
const query = args.query
|
||||
if (!query) { result = { error: '--query <json> required' }; break }
|
||||
let body
|
||||
try { body = JSON.parse(query) } catch { result = { error: 'Invalid JSON in --query' }; break }
|
||||
result = await api('POST', '/aggregation', body)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown accounts subcommand. Use: get, search' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'reports':
|
||||
switch (sub) {
|
||||
case 'funnel': {
|
||||
const pipeline = args.pipeline
|
||||
if (!pipeline) { result = { error: '--pipeline <json> required' }; break }
|
||||
let body
|
||||
try { body = JSON.parse(pipeline) } catch { result = { error: 'Invalid JSON in --pipeline' }; break }
|
||||
result = await api('POST', '/aggregation', body)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown reports subcommand. Use: funnel' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'metadata':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
const kind = args.kind
|
||||
if (!kind) { result = { error: '--kind <visitor|account|parentAccount> required' }; break }
|
||||
result = await api('GET', `/metadata/schema/${kind}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown metadata subcommand. Use: list' }
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
result = {
|
||||
error: 'Unknown command',
|
||||
usage: {
|
||||
features: {
|
||||
list: 'features list',
|
||||
get: 'features get --id <id>',
|
||||
},
|
||||
pages: {
|
||||
list: 'pages list',
|
||||
get: 'pages get --id <id>',
|
||||
},
|
||||
guides: {
|
||||
list: 'guides list [--state <state>]',
|
||||
get: 'guides get --id <id>',
|
||||
},
|
||||
visitors: {
|
||||
get: 'visitors get --id <id>',
|
||||
search: 'visitors search --query <json>',
|
||||
},
|
||||
accounts: {
|
||||
get: 'accounts get --id <id>',
|
||||
search: 'accounts search --query <json>',
|
||||
},
|
||||
reports: {
|
||||
funnel: 'reports funnel --pipeline <json>',
|
||||
},
|
||||
metadata: {
|
||||
list: 'metadata list --kind <visitor|account|parentAccount>',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(result, null, 2))
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(JSON.stringify({ error: err.message }))
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -1,214 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const API_KEY = process.env.SIMILARWEB_API_KEY
|
||||
const BASE_URL = 'https://api.similarweb.com/v1'
|
||||
|
||||
if (!API_KEY) {
|
||||
console.error(JSON.stringify({ error: 'SIMILARWEB_API_KEY environment variable required' }))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function api(method, path, body) {
|
||||
const separator = path.includes('?') ? '&' : '?'
|
||||
const url = `${BASE_URL}${path}${separator}api_key=${API_KEY}`
|
||||
if (args['dry-run']) {
|
||||
return { _dry_run: true, method, url: url.replace(API_KEY, '***'), headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: body || undefined }
|
||||
}
|
||||
const res = await fetch(url, {
|
||||
method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
const text = await res.text()
|
||||
try {
|
||||
return JSON.parse(text)
|
||||
} catch {
|
||||
return { status: res.status, body: text }
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgs(args) {
|
||||
const result = { _: [] }
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg.startsWith('--')) {
|
||||
const key = arg.slice(2)
|
||||
const next = args[i + 1]
|
||||
if (next && !next.startsWith('--')) {
|
||||
result[key] = next
|
||||
i++
|
||||
} else {
|
||||
result[key] = true
|
||||
}
|
||||
} else {
|
||||
result._.push(arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const args = parseArgs(process.argv.slice(2))
|
||||
const [cmd, sub, ...rest] = args._
|
||||
|
||||
async function main() {
|
||||
let result
|
||||
|
||||
switch (cmd) {
|
||||
case 'traffic':
|
||||
switch (sub) {
|
||||
case 'visits': {
|
||||
const domain = args.domain
|
||||
if (!domain) { result = { error: '--domain required' }; break }
|
||||
if (!args.start) { result = { error: '--start required (YYYY-MM)' }; break }
|
||||
if (!args.end) { result = { error: '--end required (YYYY-MM)' }; break }
|
||||
const params = new URLSearchParams({ start_date: args.start, end_date: args.end })
|
||||
if (args.country) params.set('country', args.country)
|
||||
if (args.granularity) params.set('granularity', args.granularity)
|
||||
result = await api('GET', `/website/${encodeURIComponent(domain)}/total-traffic-and-engagement/visits?${params.toString()}`)
|
||||
break
|
||||
}
|
||||
case 'pages-per-visit': {
|
||||
const domain = args.domain
|
||||
if (!domain) { result = { error: '--domain required' }; break }
|
||||
if (!args.start) { result = { error: '--start required (YYYY-MM)' }; break }
|
||||
if (!args.end) { result = { error: '--end required (YYYY-MM)' }; break }
|
||||
const params = new URLSearchParams({ start_date: args.start, end_date: args.end })
|
||||
if (args.country) params.set('country', args.country)
|
||||
if (args.granularity) params.set('granularity', args.granularity)
|
||||
result = await api('GET', `/website/${encodeURIComponent(domain)}/total-traffic-and-engagement/pages-per-visit?${params.toString()}`)
|
||||
break
|
||||
}
|
||||
case 'avg-duration': {
|
||||
const domain = args.domain
|
||||
if (!domain) { result = { error: '--domain required' }; break }
|
||||
if (!args.start) { result = { error: '--start required (YYYY-MM)' }; break }
|
||||
if (!args.end) { result = { error: '--end required (YYYY-MM)' }; break }
|
||||
const params = new URLSearchParams({ start_date: args.start, end_date: args.end })
|
||||
if (args.country) params.set('country', args.country)
|
||||
if (args.granularity) params.set('granularity', args.granularity)
|
||||
result = await api('GET', `/website/${encodeURIComponent(domain)}/total-traffic-and-engagement/average-visit-duration?${params.toString()}`)
|
||||
break
|
||||
}
|
||||
case 'bounce-rate': {
|
||||
const domain = args.domain
|
||||
if (!domain) { result = { error: '--domain required' }; break }
|
||||
if (!args.start) { result = { error: '--start required (YYYY-MM)' }; break }
|
||||
if (!args.end) { result = { error: '--end required (YYYY-MM)' }; break }
|
||||
const params = new URLSearchParams({ start_date: args.start, end_date: args.end })
|
||||
if (args.country) params.set('country', args.country)
|
||||
if (args.granularity) params.set('granularity', args.granularity)
|
||||
result = await api('GET', `/website/${encodeURIComponent(domain)}/total-traffic-and-engagement/bounce-rate?${params.toString()}`)
|
||||
break
|
||||
}
|
||||
case 'sources': {
|
||||
const domain = args.domain
|
||||
if (!domain) { result = { error: '--domain required' }; break }
|
||||
if (!args.start) { result = { error: '--start required (YYYY-MM)' }; break }
|
||||
if (!args.end) { result = { error: '--end required (YYYY-MM)' }; break }
|
||||
const params = new URLSearchParams({ start_date: args.start, end_date: args.end })
|
||||
if (args.country) params.set('country', args.country)
|
||||
result = await api('GET', `/website/${encodeURIComponent(domain)}/traffic-sources/overview?${params.toString()}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown traffic subcommand. Use: visits, pages-per-visit, avg-duration, bounce-rate, sources' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'referrals': {
|
||||
const domain = args.domain
|
||||
if (!domain) { result = { error: '--domain required' }; break }
|
||||
if (!args.start) { result = { error: '--start required (YYYY-MM)' }; break }
|
||||
if (!args.end) { result = { error: '--end required (YYYY-MM)' }; break }
|
||||
const params = new URLSearchParams({ start_date: args.start, end_date: args.end })
|
||||
if (args.country) params.set('country', args.country)
|
||||
result = await api('GET', `/website/${encodeURIComponent(domain)}/traffic-sources/referrals?${params.toString()}`)
|
||||
break
|
||||
}
|
||||
|
||||
case 'search':
|
||||
switch (sub) {
|
||||
case 'keywords-organic': {
|
||||
const domain = args.domain
|
||||
if (!domain) { result = { error: '--domain required' }; break }
|
||||
if (!args.start) { result = { error: '--start required (YYYY-MM)' }; break }
|
||||
if (!args.end) { result = { error: '--end required (YYYY-MM)' }; break }
|
||||
const params = new URLSearchParams({ start_date: args.start, end_date: args.end })
|
||||
if (args.country) params.set('country', args.country)
|
||||
if (args.limit) params.set('limit', args.limit)
|
||||
result = await api('GET', `/website/${encodeURIComponent(domain)}/search/organic-search-keywords?${params.toString()}`)
|
||||
break
|
||||
}
|
||||
case 'keywords-paid': {
|
||||
const domain = args.domain
|
||||
if (!domain) { result = { error: '--domain required' }; break }
|
||||
if (!args.start) { result = { error: '--start required (YYYY-MM)' }; break }
|
||||
if (!args.end) { result = { error: '--end required (YYYY-MM)' }; break }
|
||||
const params = new URLSearchParams({ start_date: args.start, end_date: args.end })
|
||||
if (args.country) params.set('country', args.country)
|
||||
if (args.limit) params.set('limit', args.limit)
|
||||
result = await api('GET', `/website/${encodeURIComponent(domain)}/search/paid-search-keywords?${params.toString()}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown search subcommand. Use: keywords-organic, keywords-paid' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'competitors': {
|
||||
const domain = args.domain
|
||||
if (!domain) { result = { error: '--domain required' }; break }
|
||||
result = await api('GET', `/website/${encodeURIComponent(domain)}/similar-sites/similarsites`)
|
||||
break
|
||||
}
|
||||
|
||||
case 'category-rank': {
|
||||
const domain = args.domain
|
||||
if (!domain) { result = { error: '--domain required' }; break }
|
||||
result = await api('GET', `/website/${encodeURIComponent(domain)}/category-rank/category-rank`)
|
||||
break
|
||||
}
|
||||
|
||||
case 'geography': {
|
||||
const domain = args.domain
|
||||
if (!domain) { result = { error: '--domain required' }; break }
|
||||
if (!args.start) { result = { error: '--start required (YYYY-MM)' }; break }
|
||||
if (!args.end) { result = { error: '--end required (YYYY-MM)' }; break }
|
||||
const params = new URLSearchParams({ start_date: args.start, end_date: args.end })
|
||||
result = await api('GET', `/website/${encodeURIComponent(domain)}/geo/traffic-by-country?${params.toString()}`)
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
result = {
|
||||
error: 'Unknown command',
|
||||
usage: {
|
||||
traffic: {
|
||||
visits: 'traffic visits --domain <domain> --start <YYYY-MM> --end <YYYY-MM> [--country <cc>] [--granularity <monthly|weekly|daily>]',
|
||||
'pages-per-visit': 'traffic pages-per-visit --domain <domain> --start <YYYY-MM> --end <YYYY-MM>',
|
||||
'avg-duration': 'traffic avg-duration --domain <domain> --start <YYYY-MM> --end <YYYY-MM>',
|
||||
'bounce-rate': 'traffic bounce-rate --domain <domain> --start <YYYY-MM> --end <YYYY-MM>',
|
||||
sources: 'traffic sources --domain <domain> --start <YYYY-MM> --end <YYYY-MM>',
|
||||
},
|
||||
referrals: 'referrals --domain <domain> --start <YYYY-MM> --end <YYYY-MM>',
|
||||
search: {
|
||||
'keywords-organic': 'search keywords-organic --domain <domain> --start <YYYY-MM> --end <YYYY-MM>',
|
||||
'keywords-paid': 'search keywords-paid --domain <domain> --start <YYYY-MM> --end <YYYY-MM>',
|
||||
},
|
||||
competitors: 'competitors --domain <domain>',
|
||||
'category-rank': 'category-rank --domain <domain>',
|
||||
geography: 'geography --domain <domain> --start <YYYY-MM> --end <YYYY-MM>',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(result, null, 2))
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(JSON.stringify({ error: err.message }))
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -1,168 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const API_KEY = process.env.SUPERMETRICS_API_KEY
|
||||
const BASE_URL = 'https://api.supermetrics.com/enterprise/v2'
|
||||
|
||||
if (!API_KEY) {
|
||||
console.error(JSON.stringify({ error: 'SUPERMETRICS_API_KEY environment variable required' }))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function api(method, path, body) {
|
||||
const separator = path.includes('?') ? '&' : '?'
|
||||
const url = `${BASE_URL}${path}${separator}api_key=${API_KEY}`
|
||||
if (args['dry-run']) {
|
||||
return { _dry_run: true, method, url: url.replace(API_KEY, '***'), headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: body || undefined }
|
||||
}
|
||||
const res = await fetch(url, {
|
||||
method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
const text = await res.text()
|
||||
try {
|
||||
return JSON.parse(text)
|
||||
} catch {
|
||||
return { status: res.status, body: text }
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgs(args) {
|
||||
const result = { _: [] }
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg.startsWith('--')) {
|
||||
const key = arg.slice(2)
|
||||
const next = args[i + 1]
|
||||
if (next && !next.startsWith('--')) {
|
||||
result[key] = next
|
||||
i++
|
||||
} else {
|
||||
result[key] = true
|
||||
}
|
||||
} else {
|
||||
result._.push(arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const args = parseArgs(process.argv.slice(2))
|
||||
const [cmd, sub, ...rest] = args._
|
||||
|
||||
async function main() {
|
||||
let result
|
||||
|
||||
switch (cmd) {
|
||||
case 'query': {
|
||||
const dsId = args['ds-id']
|
||||
const dsAccounts = args['ds-accounts']
|
||||
const dateRange = args['date-range']
|
||||
const fields = args.fields
|
||||
if (!dsId) { result = { error: '--ds-id required (e.g., GA4, AW, FB, LI, GSC)' }; break }
|
||||
if (!dsAccounts) { result = { error: '--ds-accounts required' }; break }
|
||||
if (!dateRange) { result = { error: '--date-range required (e.g., last_28_days, last_month, this_month, custom)' }; break }
|
||||
if (!fields) { result = { error: '--fields required (comma-separated field names)' }; break }
|
||||
const body = {
|
||||
ds_id: dsId,
|
||||
ds_accounts: dsAccounts,
|
||||
date_range_type: dateRange,
|
||||
fields: fields.split(',').map(f => ({ name: f.trim() })),
|
||||
}
|
||||
if (args.filter) body.filter = args.filter
|
||||
if (args['max-rows']) body.max_rows = parseInt(args['max-rows'], 10)
|
||||
if (args['start-date']) body.start_date = args['start-date']
|
||||
if (args['end-date']) body.end_date = args['end-date']
|
||||
result = await api('POST', '/query/data/json', body)
|
||||
break
|
||||
}
|
||||
|
||||
case 'sources':
|
||||
switch (sub) {
|
||||
case 'list':
|
||||
result = await api('GET', '/datasources')
|
||||
break
|
||||
default:
|
||||
result = { error: 'Unknown sources subcommand. Use: list' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'accounts':
|
||||
switch (sub) {
|
||||
case 'list': {
|
||||
const dsId = args['ds-id']
|
||||
if (!dsId) { result = { error: '--ds-id required (e.g., GA4, AW, FB)' }; break }
|
||||
const params = new URLSearchParams({ ds_id: dsId })
|
||||
result = await api('GET', `/datasources/accounts?${params.toString()}`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown accounts subcommand. Use: list' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'teams':
|
||||
switch (sub) {
|
||||
case 'list':
|
||||
result = await api('GET', '/teams')
|
||||
break
|
||||
default:
|
||||
result = { error: 'Unknown teams subcommand. Use: list' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'users':
|
||||
switch (sub) {
|
||||
case 'list':
|
||||
result = await api('GET', '/users')
|
||||
break
|
||||
default:
|
||||
result = { error: 'Unknown users subcommand. Use: list' }
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
result = {
|
||||
error: 'Unknown command',
|
||||
usage: {
|
||||
query: 'query --ds-id <data-source> --ds-accounts <account-id> --date-range <range> --fields <f1,f2> [--filter <filter>] [--max-rows <n>] [--start-date <date>] [--end-date <date>]',
|
||||
sources: {
|
||||
list: 'sources list',
|
||||
},
|
||||
accounts: {
|
||||
list: 'accounts list --ds-id <data-source>',
|
||||
},
|
||||
teams: {
|
||||
list: 'teams list',
|
||||
},
|
||||
users: {
|
||||
list: 'users list',
|
||||
},
|
||||
'data-source-ids': {
|
||||
'GA4': 'Google Analytics 4',
|
||||
'GA4_PAID': 'Google Analytics (paid)',
|
||||
'AW': 'Google Ads',
|
||||
'FB': 'Facebook Ads',
|
||||
'LI': 'LinkedIn Ads',
|
||||
'TW_ADS': 'Twitter Ads',
|
||||
'IG_IA': 'Instagram',
|
||||
'FB_IA': 'Facebook Pages',
|
||||
'GSC': 'Google Search Console',
|
||||
'SE': 'Semrush',
|
||||
'MC': 'Mailchimp',
|
||||
},
|
||||
'date-ranges': ['last_28_days', 'last_month', 'this_month', 'custom'],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(result, null, 2))
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(JSON.stringify({ error: err.message }))
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -1,216 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const BASE_URL = 'https://api.zoominfo.com'
|
||||
|
||||
let ACCESS_TOKEN = process.env.ZOOMINFO_ACCESS_TOKEN
|
||||
|
||||
if (!ACCESS_TOKEN && !process.env.ZOOMINFO_USERNAME) {
|
||||
console.error(JSON.stringify({ error: 'ZOOMINFO_ACCESS_TOKEN or ZOOMINFO_USERNAME + ZOOMINFO_PRIVATE_KEY environment variables required' }))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function authenticate() {
|
||||
if (ACCESS_TOKEN) return ACCESS_TOKEN
|
||||
const username = process.env.ZOOMINFO_USERNAME
|
||||
const password = process.env.ZOOMINFO_PRIVATE_KEY
|
||||
if (!username || !password) {
|
||||
throw new Error('ZOOMINFO_USERNAME and ZOOMINFO_PRIVATE_KEY required for authentication')
|
||||
}
|
||||
const res = await fetch(`${BASE_URL}/authenticate`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ username, password }),
|
||||
})
|
||||
const text = await res.text()
|
||||
if (!res.ok) {
|
||||
throw new Error(`Authentication failed (${res.status}): ${text}`)
|
||||
}
|
||||
try {
|
||||
const data = JSON.parse(text)
|
||||
if (!data.jwt) throw new Error('No JWT in response')
|
||||
ACCESS_TOKEN = data.jwt
|
||||
return ACCESS_TOKEN
|
||||
} catch (e) {
|
||||
if (e.message === 'No JWT in response') throw e
|
||||
throw new Error(`Authentication failed: ${text}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function api(method, path, body) {
|
||||
if (args['dry-run']) {
|
||||
return { _dry_run: true, method, url: `${BASE_URL}${path}`, headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ***' }, body }
|
||||
}
|
||||
const token = await authenticate()
|
||||
const res = await fetch(`${BASE_URL}${path}`, {
|
||||
method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
const text = await res.text()
|
||||
try {
|
||||
return JSON.parse(text)
|
||||
} catch {
|
||||
return { status: res.status, body: text }
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgs(args) {
|
||||
const result = { _: [] }
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg.startsWith('--')) {
|
||||
const key = arg.slice(2)
|
||||
const next = args[i + 1]
|
||||
if (next && !next.startsWith('--')) {
|
||||
result[key] = next
|
||||
i++
|
||||
} else {
|
||||
result[key] = true
|
||||
}
|
||||
} else {
|
||||
result._.push(arg)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const args = parseArgs(process.argv.slice(2))
|
||||
const [cmd, sub, ...rest] = args._
|
||||
|
||||
async function main() {
|
||||
let result
|
||||
const page = args.page ? Number(args.page) : 1
|
||||
const perPage = args['per-page'] ? Number(args['per-page']) : 25
|
||||
|
||||
switch (cmd) {
|
||||
case 'auth': {
|
||||
if (args['dry-run']) {
|
||||
result = { _dry_run: true, action: 'authenticate', url: `${BASE_URL}/authenticate`, jwt: '***' }
|
||||
break
|
||||
}
|
||||
const token = await authenticate()
|
||||
result = { jwt: token }
|
||||
break
|
||||
}
|
||||
|
||||
case 'contacts':
|
||||
switch (sub) {
|
||||
case 'search': {
|
||||
const body = { rpp: perPage, page }
|
||||
if (args['job-title']) body.jobTitle = [args['job-title']]
|
||||
if (args.company) body.companyName = [args.company]
|
||||
if (args.location) body.locationSearchType = 'PersonLocation', body.personLocationCity = [args.location]
|
||||
if (args.seniority) body.managementLevel = [args.seniority]
|
||||
if (args.department) body.department = [args.department]
|
||||
result = await api('POST', '/search/contact', body)
|
||||
break
|
||||
}
|
||||
case 'enrich': {
|
||||
const body = {}
|
||||
if (args.email) body.matchEmail = [args.email]
|
||||
if (args['person-id']) body.personId = [args['person-id']]
|
||||
if (!args.email && !args['person-id']) {
|
||||
result = { error: '--email or --person-id required' }
|
||||
break
|
||||
}
|
||||
result = await api('POST', '/enrich/contact', body)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown contacts subcommand. Use: search, enrich' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'companies':
|
||||
switch (sub) {
|
||||
case 'search': {
|
||||
const body = { rpp: perPage, page }
|
||||
if (args.name) body.companyName = [args.name]
|
||||
if (args.industry) body.industry = [args.industry]
|
||||
if (args['revenue-min']) body.revenueMin = Number(args['revenue-min'])
|
||||
if (args['revenue-max']) body.revenueMax = Number(args['revenue-max'])
|
||||
if (args['employees-min']) body.employeeCountMin = Number(args['employees-min'])
|
||||
if (args['employees-max']) body.employeeCountMax = Number(args['employees-max'])
|
||||
result = await api('POST', '/search/company', body)
|
||||
break
|
||||
}
|
||||
case 'enrich': {
|
||||
const body = {}
|
||||
if (args.domain) body.matchCompanyWebsite = [args.domain]
|
||||
if (args['company-id']) body.companyId = [args['company-id']]
|
||||
if (!args.domain && !args['company-id']) {
|
||||
result = { error: '--domain or --company-id required' }
|
||||
break
|
||||
}
|
||||
result = await api('POST', '/enrich/company', body)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown companies subcommand. Use: search, enrich' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'intent':
|
||||
switch (sub) {
|
||||
case 'search': {
|
||||
if (!args.topic) {
|
||||
result = { error: '--topic required' }
|
||||
break
|
||||
}
|
||||
const body = { topicId: [args.topic] }
|
||||
if (args['company-id']) body.companyId = [args['company-id']]
|
||||
result = await api('POST', '/lookup/intent', body)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown intent subcommand. Use: search' }
|
||||
}
|
||||
break
|
||||
|
||||
case 'scoops':
|
||||
switch (sub) {
|
||||
case 'search': {
|
||||
const body = { rpp: perPage, page }
|
||||
if (args['company-id']) body.companyId = [args['company-id']]
|
||||
if (args.topic) body.topicId = [args.topic]
|
||||
result = await api('POST', '/lookup/scoops', body)
|
||||
break
|
||||
}
|
||||
default:
|
||||
result = { error: 'Unknown scoops subcommand. Use: search' }
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
result = {
|
||||
error: 'Unknown command',
|
||||
usage: {
|
||||
auth: 'auth — authenticate and get JWT token',
|
||||
contacts: {
|
||||
search: 'contacts search [--job-title <t>] [--company <c>] [--location <l>] [--seniority <s>] [--department <d>] [--page <n>]',
|
||||
enrich: 'contacts enrich --email <email> | --person-id <id>',
|
||||
},
|
||||
companies: {
|
||||
search: 'companies search [--name <n>] [--industry <i>] [--revenue-min <n>] [--employees-min <n>] [--page <n>]',
|
||||
enrich: 'companies enrich --domain <domain> | --company-id <id>',
|
||||
},
|
||||
intent: {
|
||||
search: 'intent search --topic <topic> [--company-id <id>]',
|
||||
},
|
||||
scoops: {
|
||||
search: 'scoops search [--company-id <id>] [--topic <topic>] [--page <n>]',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(result, null, 2))
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(JSON.stringify({ error: err.message }))
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -1,128 +0,0 @@
|
||||
# AirOps
|
||||
|
||||
AI content platform for crafting content that wins AI search. Build and execute AI workflows (flows) for SEO content generation, data enrichment, and automation.
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Integration | Available | Notes |
|
||||
|-------------|-----------|-------|
|
||||
| API | ✓ | Flows, Workflows, Runs |
|
||||
| MCP | - | Not available |
|
||||
| CLI | ✓ | [airops.js](../clis/airops.js) |
|
||||
| SDK | - | REST API only |
|
||||
|
||||
## Authentication
|
||||
|
||||
- **Type**: API Key + Workspace ID
|
||||
- **Header**: `Authorization: Bearer {api_key}`
|
||||
- **Env vars**: `AIROPS_API_KEY`, `AIROPS_WORKSPACE_ID`
|
||||
- **Get key**: Settings > API Keys at https://app.airops.com
|
||||
|
||||
## Common Agent Operations
|
||||
|
||||
### List Flows
|
||||
|
||||
```bash
|
||||
GET https://api.airops.com/public_api/v1/workspaces/{workspace_id}/flows
|
||||
```
|
||||
|
||||
### Get Flow Details
|
||||
|
||||
```bash
|
||||
GET https://api.airops.com/public_api/v1/workspaces/{workspace_id}/flows/{flow_id}
|
||||
```
|
||||
|
||||
### Execute a Flow
|
||||
|
||||
```bash
|
||||
POST https://api.airops.com/public_api/v1/workspaces/{workspace_id}/flows/{flow_id}/execute
|
||||
|
||||
{
|
||||
"inputs": {
|
||||
"keyword": "best project management tools",
|
||||
"target_audience": "startup founders"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### List Runs for a Flow
|
||||
|
||||
```bash
|
||||
GET https://api.airops.com/public_api/v1/workspaces/{workspace_id}/flows/{flow_id}/runs
|
||||
```
|
||||
|
||||
### Get Run Status
|
||||
|
||||
```bash
|
||||
GET https://api.airops.com/public_api/v1/workspaces/{workspace_id}/runs/{run_id}
|
||||
```
|
||||
|
||||
### List Workflows
|
||||
|
||||
```bash
|
||||
GET https://api.airops.com/public_api/v1/workspaces/{workspace_id}/workflows
|
||||
```
|
||||
|
||||
### Execute a Workflow
|
||||
|
||||
```bash
|
||||
POST https://api.airops.com/public_api/v1/workspaces/{workspace_id}/workflows/{workflow_id}/execute
|
||||
|
||||
{
|
||||
"inputs": {
|
||||
"topic": "email marketing best practices",
|
||||
"content_type": "blog_post"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Key Metrics
|
||||
|
||||
### Flow Data
|
||||
- `id` - Flow identifier
|
||||
- `name` - Flow name
|
||||
- `description` - Flow description
|
||||
- `status` - Active/inactive status
|
||||
- `created_at` - Creation timestamp
|
||||
- `updated_at` - Last modified timestamp
|
||||
|
||||
### Run Data
|
||||
- `id` - Run identifier
|
||||
- `flow_id` - Parent flow ID
|
||||
- `status` - pending, running, completed, failed
|
||||
- `inputs` - Input parameters used
|
||||
- `outputs` - Generated results
|
||||
- `started_at` - Run start time
|
||||
- `completed_at` - Run completion time
|
||||
|
||||
## Parameters
|
||||
|
||||
### Flow Execution
|
||||
- `inputs` - JSON object of key-value pairs matching the flow's expected inputs
|
||||
- Input keys vary per flow (e.g., `keyword`, `topic`, `url`, `target_audience`)
|
||||
|
||||
### Workflow Execution
|
||||
- `inputs` - JSON object of key-value pairs matching the workflow's expected inputs
|
||||
|
||||
## When to Use
|
||||
|
||||
- Bulk content generation for SEO at scale
|
||||
- SEO-optimized article creation with AI workflows
|
||||
- Data enrichment pipelines for marketing lists
|
||||
- Keyword research automation
|
||||
- Content optimization and rewriting
|
||||
- Programmatic SEO page generation
|
||||
- AI-powered content briefs and outlines
|
||||
|
||||
## Rate Limits
|
||||
|
||||
- Rate limits vary by plan
|
||||
- Concurrent execution limits depend on workspace tier
|
||||
- Check AirOps dashboard for current usage and limits
|
||||
|
||||
## Relevant Skills
|
||||
|
||||
- ai-seo
|
||||
- content-strategy
|
||||
- programmatic-seo
|
||||
- copywriting
|
||||
@@ -1,149 +0,0 @@
|
||||
# Clay
|
||||
|
||||
Data enrichment and outbound automation platform for building lead lists with waterfall enrichment across 75+ data providers.
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Integration | Available | Notes |
|
||||
|-------------|-----------|-------|
|
||||
| API | ✓ | Tables, People Enrichment, Company Enrichment |
|
||||
| MCP | ✓ | [Claude connector](https://claude.com/connectors/clay) |
|
||||
| CLI | ✓ | [clay.js](../clis/clay.js) |
|
||||
| SDK | - | REST API only |
|
||||
|
||||
## Authentication
|
||||
|
||||
- **Type**: API Key (Bearer token)
|
||||
- **Header**: `Authorization: Bearer {api_key}`
|
||||
- **Get key**: Settings > API at https://app.clay.com
|
||||
|
||||
## Common Agent Operations
|
||||
|
||||
### List Tables
|
||||
|
||||
```bash
|
||||
GET https://api.clay.com/v3/tables
|
||||
|
||||
Authorization: Bearer {api_key}
|
||||
```
|
||||
|
||||
### Get Table Details
|
||||
|
||||
```bash
|
||||
GET https://api.clay.com/v3/tables/{table_id}
|
||||
|
||||
Authorization: Bearer {api_key}
|
||||
```
|
||||
|
||||
### Get Table Rows
|
||||
|
||||
```bash
|
||||
GET https://api.clay.com/v3/tables/{table_id}/rows?page=1&per_page=25
|
||||
|
||||
Authorization: Bearer {api_key}
|
||||
```
|
||||
|
||||
### Add Row to Table
|
||||
|
||||
```bash
|
||||
POST https://api.clay.com/v3/tables/{table_id}/rows
|
||||
|
||||
{
|
||||
"first_name": "Jane",
|
||||
"last_name": "Doe",
|
||||
"company": "Acme Inc",
|
||||
"email": "jane@acme.com"
|
||||
}
|
||||
```
|
||||
|
||||
### People Enrichment
|
||||
|
||||
```bash
|
||||
POST https://api.clay.com/v3/people/enrich
|
||||
|
||||
{
|
||||
"email": "jane@acme.com"
|
||||
}
|
||||
```
|
||||
|
||||
### Company Enrichment
|
||||
|
||||
```bash
|
||||
POST https://api.clay.com/v3/companies/enrich
|
||||
|
||||
{
|
||||
"domain": "acme.com"
|
||||
}
|
||||
```
|
||||
|
||||
## Key Metrics
|
||||
|
||||
### Person Data
|
||||
- `first_name`, `last_name` - Name
|
||||
- `email` - Email address
|
||||
- `title` - Job title
|
||||
- `linkedin_url` - LinkedIn profile
|
||||
- `company` - Company name
|
||||
- `location` - Location
|
||||
- `seniority` - Seniority level
|
||||
|
||||
### Company Data
|
||||
- `name` - Company name
|
||||
- `domain` - Website domain
|
||||
- `industry` - Industry
|
||||
- `employee_count` - Number of employees
|
||||
- `revenue` - Estimated revenue
|
||||
- `location` - Headquarters location
|
||||
- `technologies` - Tech stack
|
||||
- `description` - Company description
|
||||
|
||||
### Table Data
|
||||
- `id` - Table ID
|
||||
- `name` - Table name
|
||||
- `row_count` - Number of rows
|
||||
- `columns` - Column definitions
|
||||
- `created_at` - Creation timestamp
|
||||
- `updated_at` - Last update timestamp
|
||||
|
||||
## Parameters
|
||||
|
||||
### Tables
|
||||
- `page` - Page number (default: 1)
|
||||
- `per_page` - Results per page (default: 25)
|
||||
|
||||
### People Enrichment
|
||||
- `email` - Email address
|
||||
- `linkedin_url` - LinkedIn profile URL
|
||||
- `first_name` + `last_name` - Name-based lookup
|
||||
|
||||
### Company Enrichment
|
||||
- `domain` - Company domain (e.g., "acme.com")
|
||||
|
||||
### Add Row
|
||||
- Fields are dynamic and match the table's column definitions
|
||||
- Pass data as key-value pairs matching column names
|
||||
|
||||
## When to Use
|
||||
|
||||
- Building enriched prospect lists with waterfall enrichment across multiple providers
|
||||
- Enriching leads with person and company data from 75+ sources
|
||||
- Automating outbound workflows with enriched data
|
||||
- Finding verified contact info (emails, phone numbers, social profiles)
|
||||
- Company research and firmographic analysis
|
||||
- Triggering enrichment workflows via webhooks
|
||||
- Syncing enriched data back to CRM or outbound tools
|
||||
|
||||
## Rate Limits
|
||||
|
||||
- Rate limits vary by plan
|
||||
- Standard: 100 requests/minute
|
||||
- Enterprise plans have higher limits
|
||||
- Enrichment credits consumed per lookup vary by data provider
|
||||
- Webhook endpoints accept data continuously
|
||||
|
||||
## Relevant Skills
|
||||
|
||||
- cold-email
|
||||
- revops
|
||||
- sales-enablement
|
||||
- competitor-alternatives
|
||||
@@ -1,191 +0,0 @@
|
||||
# Close
|
||||
|
||||
Sales CRM for SMBs with built-in calling, email, and pipeline management designed for high-velocity sales teams.
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Integration | Available | Notes |
|
||||
|-------------|-----------|-------|
|
||||
| API | ✓ | Leads, Contacts, Opportunities, Activities, Tasks |
|
||||
| MCP | - | Not available |
|
||||
| CLI | ✓ | [close.js](../clis/close.js) |
|
||||
| SDK | - | REST API only |
|
||||
|
||||
## Authentication
|
||||
|
||||
- **Type**: Basic Auth
|
||||
- **Header**: `Authorization: Basic {base64(api_key + ':')}`
|
||||
- **Get key**: Settings > API Keys at https://app.close.com
|
||||
|
||||
## Common Agent Operations
|
||||
|
||||
### List Leads
|
||||
|
||||
```bash
|
||||
GET https://api.close.com/api/v1/lead/
|
||||
|
||||
Authorization: Basic {base64(api_key + ':')}
|
||||
```
|
||||
|
||||
### Search Leads
|
||||
|
||||
```bash
|
||||
GET https://api.close.com/api/v1/lead/?query=company_name
|
||||
|
||||
Authorization: Basic {base64(api_key + ':')}
|
||||
```
|
||||
|
||||
### Create Lead
|
||||
|
||||
```bash
|
||||
POST https://api.close.com/api/v1/lead/
|
||||
|
||||
{
|
||||
"name": "Acme Corp",
|
||||
"url": "https://acme.com",
|
||||
"description": "Enterprise prospect"
|
||||
}
|
||||
```
|
||||
|
||||
### Get Contact
|
||||
|
||||
```bash
|
||||
GET https://api.close.com/api/v1/contact/{contact_id}/
|
||||
|
||||
Authorization: Basic {base64(api_key + ':')}
|
||||
```
|
||||
|
||||
### Create Contact
|
||||
|
||||
```bash
|
||||
POST https://api.close.com/api/v1/contact/
|
||||
|
||||
{
|
||||
"lead_id": "lead_xxx",
|
||||
"name": "Jane Smith",
|
||||
"emails": [{ "email": "jane@acme.com", "type": "office" }],
|
||||
"phones": [{ "phone": "+15551234567", "type": "office" }]
|
||||
}
|
||||
```
|
||||
|
||||
### Create Opportunity
|
||||
|
||||
```bash
|
||||
POST https://api.close.com/api/v1/opportunity/
|
||||
|
||||
{
|
||||
"lead_id": "lead_xxx",
|
||||
"value": 50000,
|
||||
"status_type": "active"
|
||||
}
|
||||
```
|
||||
|
||||
### List Activities
|
||||
|
||||
```bash
|
||||
GET https://api.close.com/api/v1/activity/?lead_id=lead_xxx
|
||||
|
||||
Authorization: Basic {base64(api_key + ':')}
|
||||
```
|
||||
|
||||
### Create Task
|
||||
|
||||
```bash
|
||||
POST https://api.close.com/api/v1/task/
|
||||
|
||||
{
|
||||
"lead_id": "lead_xxx",
|
||||
"text": "Follow up on demo request",
|
||||
"_type": "lead",
|
||||
"date": "2026-03-10"
|
||||
}
|
||||
```
|
||||
|
||||
## Key Metrics
|
||||
|
||||
### Lead Data
|
||||
- `id` - Lead ID
|
||||
- `display_name` - Lead name
|
||||
- `url` - Website URL
|
||||
- `description` - Lead description
|
||||
- `status_id` - Pipeline status
|
||||
- `contacts` - Associated contacts
|
||||
- `opportunities` - Associated opportunities
|
||||
- `tasks` - Associated tasks
|
||||
|
||||
### Contact Data
|
||||
- `id` - Contact ID
|
||||
- `lead_id` - Parent lead
|
||||
- `name` - Full name
|
||||
- `title` - Job title
|
||||
- `emails` - Email addresses array
|
||||
- `phones` - Phone numbers array
|
||||
|
||||
### Opportunity Data
|
||||
- `id` - Opportunity ID
|
||||
- `lead_id` - Parent lead
|
||||
- `value` - Value in cents
|
||||
- `status_type` - active, won, or lost
|
||||
- `confidence` - Win probability (0-100)
|
||||
- `date_won` - Close date
|
||||
|
||||
### Task Data
|
||||
- `id` - Task ID
|
||||
- `lead_id` - Parent lead
|
||||
- `text` - Task description
|
||||
- `assigned_to` - Assigned user ID
|
||||
- `date` - Due date
|
||||
- `is_complete` - Completion status
|
||||
|
||||
## Parameters
|
||||
|
||||
### Leads
|
||||
- `query` - Search query string
|
||||
- `_skip` - Number of results to skip (pagination)
|
||||
- `_limit` - Max results to return (default: 100)
|
||||
- `_fields` - Comma-separated fields to return
|
||||
|
||||
### Contacts
|
||||
- `lead_id` - Filter by parent lead
|
||||
- `_skip` - Pagination offset
|
||||
- `_limit` - Max results
|
||||
|
||||
### Opportunities
|
||||
- `lead_id` - Filter by parent lead
|
||||
- `status` - Filter by status type (active, won, lost)
|
||||
- `_skip` - Pagination offset
|
||||
- `_limit` - Max results
|
||||
|
||||
### Activities
|
||||
- `lead_id` - Filter by lead
|
||||
- `_type__type` - Filter by type (Email, Call, Note, SMS, Meeting)
|
||||
- `date_created__gt` - After date
|
||||
- `date_created__lt` - Before date
|
||||
|
||||
### Tasks
|
||||
- `assigned_to` - Filter by user ID
|
||||
- `is_complete` - Filter by completion (true/false)
|
||||
- `lead_id` - Filter by lead
|
||||
- `_type` - Task type (lead)
|
||||
|
||||
## When to Use
|
||||
|
||||
- Managing SMB sales pipelines with high-touch outreach
|
||||
- Tracking sales activities (calls, emails, meetings) per lead
|
||||
- Creating and managing tasks for sales follow-ups
|
||||
- Opportunity tracking and revenue forecasting
|
||||
- Building automated outreach workflows
|
||||
- Sales team performance reporting
|
||||
|
||||
## Rate Limits
|
||||
|
||||
- Rate limits based on organization plan
|
||||
- Standard: ~100 requests/minute
|
||||
- Responses include `ratelimit-limit` and `ratelimit-remaining` headers
|
||||
- 429 responses include `Retry-After` header
|
||||
|
||||
## Relevant Skills
|
||||
|
||||
- revops
|
||||
- sales-enablement
|
||||
- cold-email
|
||||
@@ -1,142 +0,0 @@
|
||||
# Coupler.io
|
||||
|
||||
Data integration platform that connects marketing, sales, analytics, and e-commerce data sources to destinations like spreadsheets, BI tools, and data warehouses with automated scheduling.
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Integration | Available | Notes |
|
||||
|-------------|-----------|-------|
|
||||
| API | ✓ | Importers, Runs, Sources, Destinations |
|
||||
| MCP | ✓ | [Claude connector](https://claude.com/connectors/coupler-io) |
|
||||
| CLI | ✓ | [coupler.js](../clis/coupler.js) |
|
||||
| SDK | - | REST API only |
|
||||
|
||||
## Authentication
|
||||
|
||||
- **Type**: API Key
|
||||
- **Header**: `Authorization: Bearer {api_key}`
|
||||
- **Get key**: Settings > API at https://app.coupler.io
|
||||
|
||||
## Common Agent Operations
|
||||
|
||||
### List Importers
|
||||
|
||||
```bash
|
||||
GET https://api.coupler.io/v1/importers
|
||||
```
|
||||
|
||||
### Get Importer Details
|
||||
|
||||
```bash
|
||||
GET https://api.coupler.io/v1/importers/{id}
|
||||
```
|
||||
|
||||
### Trigger an Importer Run
|
||||
|
||||
```bash
|
||||
POST https://api.coupler.io/v1/importers/{id}/run
|
||||
```
|
||||
|
||||
### Create an Importer
|
||||
|
||||
```bash
|
||||
POST https://api.coupler.io/v1/importers
|
||||
|
||||
{
|
||||
"source_type": "google_analytics",
|
||||
"destination_type": "google_sheets",
|
||||
"name": "GA4 to Sheets Daily"
|
||||
}
|
||||
```
|
||||
|
||||
### Delete an Importer
|
||||
|
||||
```bash
|
||||
DELETE https://api.coupler.io/v1/importers/{id}
|
||||
```
|
||||
|
||||
### List Runs for an Importer
|
||||
|
||||
```bash
|
||||
GET https://api.coupler.io/v1/importers/{id}/runs
|
||||
```
|
||||
|
||||
### Get Run Details
|
||||
|
||||
```bash
|
||||
GET https://api.coupler.io/v1/runs/{id}
|
||||
```
|
||||
|
||||
### List Available Sources
|
||||
|
||||
```bash
|
||||
GET https://api.coupler.io/v1/sources
|
||||
```
|
||||
|
||||
### List Available Destinations
|
||||
|
||||
```bash
|
||||
GET https://api.coupler.io/v1/destinations
|
||||
```
|
||||
|
||||
## Key Metrics
|
||||
|
||||
### Importer Data
|
||||
- `id` - Importer ID
|
||||
- `name` - Importer name
|
||||
- `source_type` - Source connector type
|
||||
- `destination_type` - Destination connector type
|
||||
- `schedule` - Automation schedule
|
||||
- `status` - Current status
|
||||
- `last_run_at` - Last run timestamp
|
||||
|
||||
### Run Data
|
||||
- `id` - Run ID
|
||||
- `importer_id` - Parent importer
|
||||
- `status` - Run status (pending, running, completed, failed)
|
||||
- `started_at` - Start timestamp
|
||||
- `finished_at` - Finish timestamp
|
||||
- `rows_imported` - Number of rows processed
|
||||
- `error` - Error message if failed
|
||||
|
||||
## Parameters
|
||||
|
||||
### Importer Creation
|
||||
- `source_type` - Source connector (e.g., google_analytics, google_ads, facebook_ads, hubspot, shopify, stripe, airtable)
|
||||
- `destination_type` - Destination connector (e.g., google_sheets, bigquery, snowflake, postgresql)
|
||||
- `name` - Importer name
|
||||
- `schedule` - Automation schedule (e.g., hourly, daily, weekly)
|
||||
|
||||
### Supported Sources
|
||||
- **Analytics**: Google Analytics, Adobe Analytics
|
||||
- **Ads**: Google Ads, Facebook Ads, LinkedIn Ads, TikTok Ads
|
||||
- **CRM**: HubSpot, Salesforce, Pipedrive
|
||||
- **E-commerce**: Shopify, Stripe, WooCommerce
|
||||
- **Other**: Airtable, Google Sheets, BigQuery, MySQL, PostgreSQL
|
||||
|
||||
### Supported Destinations
|
||||
- **Spreadsheets**: Google Sheets, Excel Online
|
||||
- **BI Tools**: Looker Studio, Power BI, Tableau
|
||||
- **Data Warehouses**: BigQuery, Snowflake, Redshift
|
||||
- **Databases**: PostgreSQL, MySQL
|
||||
|
||||
## When to Use
|
||||
|
||||
- Automating marketing data pipelines from ads and analytics platforms
|
||||
- Consolidating multi-channel campaign data into a single destination
|
||||
- Scheduling recurring data syncs from CRM to spreadsheets or BI tools
|
||||
- Building marketing dashboards with fresh data from multiple sources
|
||||
- Exporting e-commerce data for reporting and analysis
|
||||
- Connecting data sources without writing custom ETL code
|
||||
|
||||
## Rate Limits
|
||||
|
||||
- Rate limits vary by plan
|
||||
- Standard: API access available on Professional and higher plans
|
||||
- Importer run frequency depends on plan tier
|
||||
|
||||
## Relevant Skills
|
||||
|
||||
- analytics-tracking
|
||||
- paid-ads
|
||||
- revops
|
||||
@@ -1,137 +0,0 @@
|
||||
# Crossbeam
|
||||
|
||||
Partner ecosystem platform (now part of Reveal) for sharing account data with partners to identify co-sell opportunities, overlapping customers, and partner-sourced pipeline.
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Integration | Available | Notes |
|
||||
|-------------|-----------|-------|
|
||||
| API | ✓ | Partners, Populations, Overlaps, Reports, Threads |
|
||||
| MCP | ✓ | [Claude connector](https://claude.com/connectors/crossbeam) |
|
||||
| CLI | ✓ | [crossbeam.js](../clis/crossbeam.js) |
|
||||
| SDK | - | REST API only |
|
||||
|
||||
## Authentication
|
||||
|
||||
- **Type**: API Key
|
||||
- **Header**: `Authorization: Bearer {api_key}`
|
||||
- **Get key**: Settings > API at https://app.crossbeam.com
|
||||
|
||||
## Common Agent Operations
|
||||
|
||||
### List Partners
|
||||
|
||||
```bash
|
||||
GET https://api.crossbeam.com/v1/partners
|
||||
Authorization: Bearer {api_key}
|
||||
```
|
||||
|
||||
### Get Partner Details
|
||||
|
||||
```bash
|
||||
GET https://api.crossbeam.com/v1/partners/{id}
|
||||
Authorization: Bearer {api_key}
|
||||
```
|
||||
|
||||
### List Populations
|
||||
|
||||
```bash
|
||||
GET https://api.crossbeam.com/v1/populations
|
||||
Authorization: Bearer {api_key}
|
||||
```
|
||||
|
||||
### List Overlaps
|
||||
|
||||
```bash
|
||||
GET https://api.crossbeam.com/v1/overlaps?partner_id={partner_id}&population_id={population_id}
|
||||
Authorization: Bearer {api_key}
|
||||
```
|
||||
|
||||
### Get Overlap Details
|
||||
|
||||
```bash
|
||||
GET https://api.crossbeam.com/v1/overlaps/{id}
|
||||
Authorization: Bearer {api_key}
|
||||
```
|
||||
|
||||
### Search Accounts
|
||||
|
||||
```bash
|
||||
GET https://api.crossbeam.com/v1/accounts/search?domain={domain}
|
||||
Authorization: Bearer {api_key}
|
||||
```
|
||||
|
||||
### List Reports
|
||||
|
||||
```bash
|
||||
GET https://api.crossbeam.com/v1/reports
|
||||
Authorization: Bearer {api_key}
|
||||
```
|
||||
|
||||
### List Collaboration Threads
|
||||
|
||||
```bash
|
||||
GET https://api.crossbeam.com/v1/threads
|
||||
Authorization: Bearer {api_key}
|
||||
```
|
||||
|
||||
## Key Metrics
|
||||
|
||||
### Partner Data
|
||||
- `id` - Partner ID
|
||||
- `name` - Partner company name
|
||||
- `status` - Partnership status (active, pending, etc.)
|
||||
- `created_at` - When the partnership was established
|
||||
- `populations_shared` - Number of shared populations
|
||||
|
||||
### Population Data
|
||||
- `id` - Population ID
|
||||
- `name` - Population name (e.g., "Customers", "Open Opportunities")
|
||||
- `record_count` - Number of records in population
|
||||
- `partner_visibility` - What partners can see
|
||||
|
||||
### Overlap Data
|
||||
- `id` - Overlap ID
|
||||
- `partner_id` - Partner involved
|
||||
- `population_id` - Population matched
|
||||
- `account_name` - Overlapping account name
|
||||
- `overlap_type` - Type of overlap (customer, prospect, etc.)
|
||||
- `match_confidence` - Match confidence score
|
||||
|
||||
### Report Data
|
||||
- `id` - Report ID
|
||||
- `name` - Report name
|
||||
- `type` - Report type
|
||||
- `created_at` - Creation date
|
||||
- `results` - Report results data
|
||||
|
||||
## Parameters
|
||||
|
||||
### Overlaps List
|
||||
- `partner_id` - Filter by specific partner
|
||||
- `population_id` - Filter by specific population
|
||||
|
||||
### Accounts Search
|
||||
- `domain` - Company domain to search for
|
||||
|
||||
## When to Use
|
||||
|
||||
- Identifying co-sell opportunities with channel partners
|
||||
- Finding overlapping customers and prospects across partner ecosystems
|
||||
- Building partner-sourced pipeline by matching accounts
|
||||
- Tracking partner influence on deals
|
||||
- Creating account mapping reports for partner meetings
|
||||
- Prioritizing which partners to engage based on overlap data
|
||||
|
||||
## Rate Limits
|
||||
|
||||
- Rate limits vary by plan
|
||||
- Standard: 100 requests/minute
|
||||
- Pagination supported on list endpoints
|
||||
|
||||
## Relevant Skills
|
||||
|
||||
- revops
|
||||
- sales-enablement
|
||||
- referral-program
|
||||
- competitor-alternatives
|
||||
@@ -1,172 +0,0 @@
|
||||
# Outreach
|
||||
|
||||
Sales engagement platform for managing prospects, sequences, and outbound campaigns at scale.
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Integration | Available | Notes |
|
||||
|-------------|-----------|-------|
|
||||
| API | ✓ | Prospects, Sequences, Mailings, Accounts, Tasks |
|
||||
| MCP | ✓ | [Claude connector](https://claude.com/connectors/outreach) |
|
||||
| CLI | ✓ | [outreach.js](../clis/outreach.js) |
|
||||
| SDK | - | REST API only (JSON:API format) |
|
||||
|
||||
## Authentication
|
||||
|
||||
- **Type**: OAuth2 Bearer Token
|
||||
- **Header**: `Authorization: Bearer {access_token}`
|
||||
- **Content-Type**: `application/vnd.api+json`
|
||||
- **Get token**: Settings > API at https://app.outreach.io or via OAuth2 flow
|
||||
|
||||
## Common Agent Operations
|
||||
|
||||
### List Prospects
|
||||
|
||||
```bash
|
||||
curl -s https://api.outreach.io/api/v2/prospects \
|
||||
-H "Authorization: Bearer $OUTREACH_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/vnd.api+json"
|
||||
```
|
||||
|
||||
### Get a Prospect
|
||||
|
||||
```bash
|
||||
curl -s https://api.outreach.io/api/v2/prospects/42 \
|
||||
-H "Authorization: Bearer $OUTREACH_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/vnd.api+json"
|
||||
```
|
||||
|
||||
### Create a Prospect
|
||||
|
||||
```bash
|
||||
curl -s -X POST https://api.outreach.io/api/v2/prospects \
|
||||
-H "Authorization: Bearer $OUTREACH_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/vnd.api+json" \
|
||||
-d '{
|
||||
"data": {
|
||||
"type": "prospect",
|
||||
"attributes": {
|
||||
"emails": ["jane@example.com"],
|
||||
"firstName": "Jane",
|
||||
"lastName": "Doe"
|
||||
}
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
### List Sequences
|
||||
|
||||
```bash
|
||||
curl -s https://api.outreach.io/api/v2/sequences \
|
||||
-H "Authorization: Bearer $OUTREACH_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/vnd.api+json"
|
||||
```
|
||||
|
||||
### Add Prospect to Sequence
|
||||
|
||||
```bash
|
||||
curl -s -X POST https://api.outreach.io/api/v2/sequenceStates \
|
||||
-H "Authorization: Bearer $OUTREACH_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/vnd.api+json" \
|
||||
-d '{
|
||||
"data": {
|
||||
"type": "sequenceState",
|
||||
"relationships": {
|
||||
"prospect": { "data": { "type": "prospect", "id": 42 } },
|
||||
"sequence": { "data": { "type": "sequence", "id": 7 } }
|
||||
}
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
### List Mailings for a Sequence
|
||||
|
||||
```bash
|
||||
curl -s "https://api.outreach.io/api/v2/mailings?filter[sequence][id]=7" \
|
||||
-H "Authorization: Bearer $OUTREACH_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/vnd.api+json"
|
||||
```
|
||||
|
||||
### List Accounts
|
||||
|
||||
```bash
|
||||
curl -s https://api.outreach.io/api/v2/accounts \
|
||||
-H "Authorization: Bearer $OUTREACH_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/vnd.api+json"
|
||||
```
|
||||
|
||||
### List Tasks
|
||||
|
||||
```bash
|
||||
curl -s "https://api.outreach.io/api/v2/tasks?filter[status]=incomplete" \
|
||||
-H "Authorization: Bearer $OUTREACH_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/vnd.api+json"
|
||||
```
|
||||
|
||||
## Key Metrics
|
||||
|
||||
### Prospect Data
|
||||
- `firstName`, `lastName` - Name
|
||||
- `emails` - Email addresses
|
||||
- `title` - Job title
|
||||
- `company` - Company name
|
||||
- `tags` - Prospect tags
|
||||
- `engagedAt` - Last engagement timestamp
|
||||
|
||||
### Sequence Data
|
||||
- `name` - Sequence name
|
||||
- `enabled` - Whether sequence is active
|
||||
- `sequenceType` - Type (e.g., interval, date-based)
|
||||
- `stepCount` - Number of steps
|
||||
- `openCount`, `clickCount`, `replyCount` - Engagement metrics
|
||||
|
||||
### Mailing Data
|
||||
- `mailingType` - Type of mailing
|
||||
- `state` - Delivery state
|
||||
- `openCount`, `clickCount` - Engagement
|
||||
- `deliveredAt`, `openedAt`, `clickedAt` - Timestamps
|
||||
|
||||
## Parameters
|
||||
|
||||
### Prospects
|
||||
- `page[number]` - Page number (default: 1)
|
||||
- `page[size]` - Results per page (default: 25, max: 1000)
|
||||
- `filter[emails]` - Filter by email
|
||||
- `filter[firstName]` - Filter by first name
|
||||
- `filter[lastName]` - Filter by last name
|
||||
- `sort` - Sort field (e.g., `createdAt`, `-updatedAt`)
|
||||
|
||||
### Sequences
|
||||
- `filter[name]` - Filter by sequence name
|
||||
- `filter[enabled]` - Filter by active status
|
||||
|
||||
### Mailings
|
||||
- `filter[sequence][id]` - Filter by sequence ID
|
||||
- `filter[prospect][id]` - Filter by prospect ID
|
||||
|
||||
### Tasks
|
||||
- `filter[status]` - Filter by status (e.g., `incomplete`, `complete`)
|
||||
- `filter[taskType]` - Filter by type (e.g., `call`, `email`, `action_item`)
|
||||
|
||||
## When to Use
|
||||
|
||||
- Managing outbound sales sequences and cadences
|
||||
- Adding prospects to automated email sequences
|
||||
- Tracking prospect engagement across touchpoints
|
||||
- Managing sales tasks and follow-ups
|
||||
- Coordinating multi-channel outreach campaigns
|
||||
- Monitoring sequence performance and reply rates
|
||||
|
||||
## Rate Limits
|
||||
|
||||
- 10,000 requests per hour per user
|
||||
- Burst limit: 100 requests per 10 seconds
|
||||
- Rate limit headers returned: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`
|
||||
- 429 responses when limits exceeded
|
||||
|
||||
## Relevant Skills
|
||||
|
||||
- cold-email
|
||||
- revops
|
||||
- sales-enablement
|
||||
- email-sequence
|
||||
@@ -1,208 +0,0 @@
|
||||
# Pendo
|
||||
|
||||
Product analytics and in-app guidance platform for tracking user behavior, measuring feature adoption, and delivering targeted in-app messages.
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Integration | Available | Notes |
|
||||
|-------------|-----------|-------|
|
||||
| API | ✓ | Features, Pages, Guides, Visitors, Accounts, Reports, Metadata |
|
||||
| MCP | - | Not available |
|
||||
| CLI | ✓ | [pendo.js](../clis/pendo.js) |
|
||||
| SDK | - | REST API only |
|
||||
|
||||
## Authentication
|
||||
|
||||
- **Type**: Integration Key
|
||||
- **Header**: `x-pendo-integration-key: {key}`
|
||||
- **Get key**: Settings > Integrations at https://app.pendo.io
|
||||
|
||||
## Common Agent Operations
|
||||
|
||||
### List Features
|
||||
|
||||
```bash
|
||||
GET https://app.pendo.io/api/v1/feature
|
||||
```
|
||||
|
||||
### Get Feature Details
|
||||
|
||||
```bash
|
||||
GET https://app.pendo.io/api/v1/feature/{featureId}
|
||||
```
|
||||
|
||||
### List Pages
|
||||
|
||||
```bash
|
||||
GET https://app.pendo.io/api/v1/page
|
||||
```
|
||||
|
||||
### Get Page Details
|
||||
|
||||
```bash
|
||||
GET https://app.pendo.io/api/v1/page/{pageId}
|
||||
```
|
||||
|
||||
### List Guides
|
||||
|
||||
```bash
|
||||
GET https://app.pendo.io/api/v1/guide?state=public
|
||||
```
|
||||
|
||||
### Get Guide Details
|
||||
|
||||
```bash
|
||||
GET https://app.pendo.io/api/v1/guide/{guideId}
|
||||
```
|
||||
|
||||
### Get Visitor Data
|
||||
|
||||
```bash
|
||||
GET https://app.pendo.io/api/v1/visitor/{visitorId}
|
||||
```
|
||||
|
||||
### Search Visitors
|
||||
|
||||
```bash
|
||||
POST https://app.pendo.io/api/v1/aggregation
|
||||
|
||||
{
|
||||
"response": { "mimeType": "application/json" },
|
||||
"request": {
|
||||
"pipeline": [
|
||||
{ "source": { "visitors": null } },
|
||||
{ "filter": "lastVisitedAt > 1700000000000" }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Get Account Data
|
||||
|
||||
```bash
|
||||
GET https://app.pendo.io/api/v1/account/{accountId}
|
||||
```
|
||||
|
||||
### Search Accounts
|
||||
|
||||
```bash
|
||||
POST https://app.pendo.io/api/v1/aggregation
|
||||
|
||||
{
|
||||
"response": { "mimeType": "application/json" },
|
||||
"request": {
|
||||
"pipeline": [
|
||||
{ "source": { "accounts": null } },
|
||||
{ "filter": "metadata.auto.lastupdated > 1700000000000" }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Run Funnel Report
|
||||
|
||||
```bash
|
||||
POST https://app.pendo.io/api/v1/aggregation
|
||||
|
||||
{
|
||||
"response": { "mimeType": "application/json" },
|
||||
"request": {
|
||||
"pipeline": [
|
||||
{ "source": { "visitors": null, "timeSeries": { "period": "dayRange", "first": 1700000000000, "last": 1700600000000 } } },
|
||||
{ "identified": "visitorId" },
|
||||
{ "filter": "pageId == \"page-id-1\"" },
|
||||
{ "filter": "pageId == \"page-id-2\"" }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### List Metadata Fields
|
||||
|
||||
```bash
|
||||
GET https://app.pendo.io/api/v1/metadata/schema/visitor
|
||||
GET https://app.pendo.io/api/v1/metadata/schema/account
|
||||
GET https://app.pendo.io/api/v1/metadata/schema/parentAccount
|
||||
```
|
||||
|
||||
## Key Metrics
|
||||
|
||||
### Feature Data
|
||||
- `id` - Feature ID
|
||||
- `name` - Feature name
|
||||
- `kind` - Feature type
|
||||
- `elementPath` - CSS selector for the tracked element
|
||||
- `pageId` - Associated page ID
|
||||
- `numEvents` - Event count
|
||||
- `numVisitors` - Unique visitor count
|
||||
|
||||
### Page Data
|
||||
- `id` - Page ID
|
||||
- `name` - Page name
|
||||
- `rules` - URL matching rules
|
||||
- `numEvents` - Pageview count
|
||||
- `numVisitors` - Unique visitor count
|
||||
|
||||
### Guide Data
|
||||
- `id` - Guide ID
|
||||
- `name` - Guide name
|
||||
- `state` - Guide state (draft, staged, public, disabled)
|
||||
- `launchMethod` - How the guide is triggered
|
||||
- `steps` - Guide step definitions
|
||||
- `numSteps` - Number of steps
|
||||
- `numViews` - Total views
|
||||
- `numVisitors` - Unique visitors who saw the guide
|
||||
|
||||
### Visitor Data
|
||||
- `visitorId` - Unique visitor identifier
|
||||
- `lastVisitedAt` - Last visit timestamp
|
||||
- `firstVisit` - First visit timestamp
|
||||
- `numEvents` - Total event count
|
||||
- `metadata` - Custom visitor metadata
|
||||
|
||||
### Account Data
|
||||
- `accountId` - Unique account identifier
|
||||
- `lastVisitedAt` - Last visit from any account member
|
||||
- `numVisitors` - Number of visitors in the account
|
||||
- `metadata` - Custom account metadata
|
||||
|
||||
## Parameters
|
||||
|
||||
### Guide Filtering
|
||||
- `state` - Filter by state: draft, staged, public, disabled
|
||||
|
||||
### Aggregation Queries
|
||||
- `source` - Data source: visitors, accounts, features, pages, guides
|
||||
- `filter` - Expression-based filtering
|
||||
- `sort` - Sort results
|
||||
- `limit` - Max results to return
|
||||
- `timeSeries` - Time range with period, first, last
|
||||
|
||||
### Metadata Kinds
|
||||
- `visitor` - Visitor metadata schema
|
||||
- `account` - Account metadata schema
|
||||
- `parentAccount` - Parent account metadata schema
|
||||
|
||||
## When to Use
|
||||
|
||||
- Tracking feature adoption and usage patterns
|
||||
- Building and managing in-app onboarding guides
|
||||
- Analyzing user behavior across pages and features
|
||||
- Segmenting users by engagement level
|
||||
- Running funnel analysis on user journeys
|
||||
- Identifying at-risk accounts based on usage decline
|
||||
- A/B testing in-app messages and tooltips
|
||||
|
||||
## Rate Limits
|
||||
|
||||
- Rate limits vary by plan
|
||||
- Standard: 500 requests per minute
|
||||
- Aggregation queries: may take longer for large datasets
|
||||
- Use pagination for large result sets
|
||||
|
||||
## Relevant Skills
|
||||
|
||||
- analytics-tracking
|
||||
- onboarding-cro
|
||||
- churn-prevention
|
||||
- ab-test-setup
|
||||
@@ -1,150 +0,0 @@
|
||||
# Similarweb
|
||||
|
||||
Competitive traffic intelligence platform providing website analytics, traffic sources, keyword data, and competitor insights.
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Integration | Available | Notes |
|
||||
|-------------|-----------|-------|
|
||||
| API | ✓ | Traffic, Search, Referrals, Competitors, Geography |
|
||||
| MCP | - | Not available |
|
||||
| CLI | ✓ | [similarweb.js](../clis/similarweb.js) |
|
||||
| SDK | - | REST API only |
|
||||
|
||||
## Authentication
|
||||
|
||||
- **Type**: API Key
|
||||
- **Query param**: `?api_key={key}`
|
||||
- **Get key**: Account Settings > API at https://account.similarweb.com
|
||||
|
||||
## Common Agent Operations
|
||||
|
||||
### Total Visits
|
||||
|
||||
```bash
|
||||
GET https://api.similarweb.com/v1/website/example.com/total-traffic-and-engagement/visits?api_key={key}&start_date=2024-01&end_date=2024-03&country=us&granularity=monthly
|
||||
```
|
||||
|
||||
### Pages Per Visit
|
||||
|
||||
```bash
|
||||
GET https://api.similarweb.com/v1/website/example.com/total-traffic-and-engagement/pages-per-visit?api_key={key}&start_date=2024-01&end_date=2024-03
|
||||
```
|
||||
|
||||
### Average Visit Duration
|
||||
|
||||
```bash
|
||||
GET https://api.similarweb.com/v1/website/example.com/total-traffic-and-engagement/average-visit-duration?api_key={key}&start_date=2024-01&end_date=2024-03
|
||||
```
|
||||
|
||||
### Bounce Rate
|
||||
|
||||
```bash
|
||||
GET https://api.similarweb.com/v1/website/example.com/total-traffic-and-engagement/bounce-rate?api_key={key}&start_date=2024-01&end_date=2024-03
|
||||
```
|
||||
|
||||
### Traffic Sources Breakdown
|
||||
|
||||
```bash
|
||||
GET https://api.similarweb.com/v1/website/example.com/traffic-sources/overview?api_key={key}&start_date=2024-01&end_date=2024-03
|
||||
```
|
||||
|
||||
### Top Referral Sites
|
||||
|
||||
```bash
|
||||
GET https://api.similarweb.com/v1/website/example.com/traffic-sources/referrals?api_key={key}&start_date=2024-01&end_date=2024-03
|
||||
```
|
||||
|
||||
### Organic Keywords
|
||||
|
||||
```bash
|
||||
GET https://api.similarweb.com/v1/website/example.com/search/organic-search-keywords?api_key={key}&start_date=2024-01&end_date=2024-03
|
||||
```
|
||||
|
||||
### Paid Keywords
|
||||
|
||||
```bash
|
||||
GET https://api.similarweb.com/v1/website/example.com/search/paid-search-keywords?api_key={key}&start_date=2024-01&end_date=2024-03
|
||||
```
|
||||
|
||||
### Similar Sites / Competitors
|
||||
|
||||
```bash
|
||||
GET https://api.similarweb.com/v1/website/example.com/similar-sites/similarsites?api_key={key}
|
||||
```
|
||||
|
||||
### Category Ranking
|
||||
|
||||
```bash
|
||||
GET https://api.similarweb.com/v1/website/example.com/category-rank/category-rank?api_key={key}
|
||||
```
|
||||
|
||||
### Traffic by Country
|
||||
|
||||
```bash
|
||||
GET https://api.similarweb.com/v1/website/example.com/geo/traffic-by-country?api_key={key}&start_date=2024-01&end_date=2024-03
|
||||
```
|
||||
|
||||
## Key Metrics
|
||||
|
||||
### Traffic & Engagement
|
||||
- `visits` - Total visits for the period
|
||||
- `pages_per_visit` - Average pages viewed per visit
|
||||
- `average_visit_duration` - Average session duration in seconds
|
||||
- `bounce_rate` - Percentage of single-page visits
|
||||
|
||||
### Traffic Sources
|
||||
- `search` - Organic + paid search percentage
|
||||
- `social` - Social media traffic percentage
|
||||
- `direct` - Direct traffic percentage
|
||||
- `referrals` - Referral traffic percentage
|
||||
- `mail` - Email traffic percentage
|
||||
- `display_ads` - Display advertising percentage
|
||||
|
||||
### Search Keywords
|
||||
- `search_term` - Keyword text
|
||||
- `share` - Traffic share percentage
|
||||
- `volume` - Search volume
|
||||
- `cpc` - Cost per click
|
||||
- `position` - Average ranking position
|
||||
|
||||
### Geography
|
||||
- `country` - Country code
|
||||
- `share` - Traffic share from that country
|
||||
|
||||
## Parameters
|
||||
|
||||
### Common Parameters
|
||||
- `start_date` - Start month (YYYY-MM format)
|
||||
- `end_date` - End month (YYYY-MM format)
|
||||
- `country` - Two-letter country code (e.g., us, gb, de)
|
||||
- `granularity` - Data granularity: monthly, weekly, daily
|
||||
|
||||
### Search Parameters
|
||||
- `limit` - Number of keywords to return
|
||||
- `country` - Filter by country
|
||||
|
||||
## When to Use
|
||||
|
||||
- Analyzing competitor website traffic and engagement metrics
|
||||
- Benchmarking your site against competitors
|
||||
- Identifying top traffic sources for any website
|
||||
- Discovering competitor organic and paid keywords
|
||||
- Finding similar sites and competitive landscape
|
||||
- Understanding geographic traffic distribution
|
||||
- Auditing SEO performance relative to competitors
|
||||
- Researching market share by traffic volume
|
||||
|
||||
## Rate Limits
|
||||
|
||||
- Rate limits vary by plan tier
|
||||
- Standard: 10 requests/second
|
||||
- Data availability depends on plan (3 months to 36 months historical)
|
||||
- Some endpoints require Premium or Enterprise plans
|
||||
|
||||
## Relevant Skills
|
||||
|
||||
- seo-audit
|
||||
- competitor-alternatives
|
||||
- paid-ads
|
||||
- content-strategy
|
||||
@@ -1,145 +0,0 @@
|
||||
# Supermetrics
|
||||
|
||||
Marketing data pipeline that connects 200+ marketing platforms. Pulls data from ad platforms, analytics, social, SEO, email, and more into a single query interface.
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Integration | Available | Notes |
|
||||
|-------------|-----------|-------|
|
||||
| API | ✓ | Query any connected data source, manage accounts |
|
||||
| MCP | ✓ | [Claude connector](https://claude.com/connectors/supermetrics) |
|
||||
| CLI | ✓ | [supermetrics.js](../clis/supermetrics.js) |
|
||||
| SDK | - | REST API only |
|
||||
|
||||
## Authentication
|
||||
|
||||
- **Type**: API Key
|
||||
- **Query param**: `api_key={api_key}` or **Header**: `x-api-key: {api_key}`
|
||||
- **Get key**: Supermetrics Hub > API settings at https://hub.supermetrics.com
|
||||
|
||||
## Common Agent Operations
|
||||
|
||||
### Query a Data Source
|
||||
|
||||
```bash
|
||||
POST https://api.supermetrics.com/enterprise/v2/query/data/json
|
||||
|
||||
{
|
||||
"ds_id": "GA4",
|
||||
"ds_accounts": "123456789",
|
||||
"date_range_type": "last_28_days",
|
||||
"fields": [
|
||||
{ "name": "sessions" },
|
||||
{ "name": "pageviews" },
|
||||
{ "name": "date" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Query with Filters
|
||||
|
||||
```bash
|
||||
POST https://api.supermetrics.com/enterprise/v2/query/data/json
|
||||
|
||||
{
|
||||
"ds_id": "AW",
|
||||
"ds_accounts": "123-456-7890",
|
||||
"date_range_type": "last_month",
|
||||
"fields": [
|
||||
{ "name": "campaign_name" },
|
||||
{ "name": "clicks" },
|
||||
{ "name": "impressions" },
|
||||
{ "name": "cost" }
|
||||
],
|
||||
"max_rows": 100
|
||||
}
|
||||
```
|
||||
|
||||
### List Available Data Sources
|
||||
|
||||
```bash
|
||||
GET https://api.supermetrics.com/enterprise/v2/datasources
|
||||
```
|
||||
|
||||
### List Connected Accounts
|
||||
|
||||
```bash
|
||||
GET https://api.supermetrics.com/enterprise/v2/datasources/accounts?ds_id=GA4
|
||||
```
|
||||
|
||||
### List Teams
|
||||
|
||||
```bash
|
||||
GET https://api.supermetrics.com/enterprise/v2/teams
|
||||
```
|
||||
|
||||
### List Users
|
||||
|
||||
```bash
|
||||
GET https://api.supermetrics.com/enterprise/v2/users
|
||||
```
|
||||
|
||||
## Key Metrics
|
||||
|
||||
### Data Source IDs
|
||||
- `GA4` - Google Analytics 4
|
||||
- `GA4_PAID` - Google Analytics (paid)
|
||||
- `AW` - Google Ads
|
||||
- `FB` - Facebook Ads
|
||||
- `LI` - LinkedIn Ads
|
||||
- `TW_ADS` - Twitter Ads
|
||||
- `IG_IA` - Instagram
|
||||
- `FB_IA` - Facebook Pages
|
||||
- `GSC` - Google Search Console
|
||||
- `SE` - Semrush
|
||||
- `MC` - Mailchimp
|
||||
- `HubSpot` - HubSpot
|
||||
|
||||
### Date Range Values
|
||||
- `last_28_days` - Last 28 days
|
||||
- `last_month` - Previous calendar month
|
||||
- `this_month` - Current month to date
|
||||
- `custom` - Custom range (requires `start_date` and `end_date`)
|
||||
|
||||
## Parameters
|
||||
|
||||
### Query
|
||||
- `ds_id` - Data source identifier (required)
|
||||
- `ds_accounts` - Account ID for the data source (required)
|
||||
- `date_range_type` - Date range preset or "custom" (required)
|
||||
- `fields` - Array of field objects with `name` property (required)
|
||||
- `filter` - Filter expression for narrowing results
|
||||
- `max_rows` - Maximum number of rows to return
|
||||
- `start_date` - Start date for custom range (YYYY-MM-DD)
|
||||
- `end_date` - End date for custom range (YYYY-MM-DD)
|
||||
|
||||
### Common Fields by Source
|
||||
- **GA4**: `sessions`, `pageviews`, `users`, `bounce_rate`, `date`, `source`, `medium`, `page_path`
|
||||
- **Google Ads**: `campaign_name`, `clicks`, `impressions`, `cost`, `conversions`, `ctr`, `cpc`
|
||||
- **Facebook Ads**: `campaign_name`, `impressions`, `clicks`, `spend`, `reach`, `cpm`, `cpc`
|
||||
- **LinkedIn Ads**: `campaign_name`, `impressions`, `clicks`, `cost`, `conversions`
|
||||
- **GSC**: `query`, `clicks`, `impressions`, `ctr`, `position`, `page`
|
||||
|
||||
## When to Use
|
||||
|
||||
- Pulling cross-platform marketing data into a single report
|
||||
- Comparing performance across ad platforms (Google, Meta, LinkedIn, TikTok)
|
||||
- Aggregating analytics data from multiple sources
|
||||
- Automating marketing reporting workflows
|
||||
- Building unified dashboards across marketing channels
|
||||
- Extracting SEO data alongside paid media metrics
|
||||
|
||||
## Rate Limits
|
||||
|
||||
- Rate limits vary by plan
|
||||
- Enterprise API: typically 100 requests/minute
|
||||
- Query results may be paginated for large datasets
|
||||
- Recommended: use `max_rows` to control response size
|
||||
|
||||
## Relevant Skills
|
||||
|
||||
- analytics-tracking
|
||||
- paid-ads
|
||||
- seo-audit
|
||||
- content-strategy
|
||||
- social-content
|
||||
@@ -1,191 +0,0 @@
|
||||
# ZoomInfo
|
||||
|
||||
B2B contact database and intent data platform with 100M+ business contacts and company intelligence for sales and marketing teams.
|
||||
|
||||
## Capabilities
|
||||
|
||||
| Integration | Available | Notes |
|
||||
|-------------|-----------|-------|
|
||||
| API | ✓ | Contact Search, Company Search, Enrichment, Intent Data, Scoops |
|
||||
| MCP | ✓ | [Claude connector](https://claude.com/connectors/zoominfo) |
|
||||
| CLI | ✓ | [zoominfo.js](../clis/zoominfo.js) |
|
||||
| SDK | - | REST API only |
|
||||
|
||||
## Authentication
|
||||
|
||||
- **Type**: JWT Token (Bearer)
|
||||
- **Flow**: POST `/authenticate` with username + password, receive JWT token
|
||||
- **Header**: `Authorization: Bearer {jwt_token}`
|
||||
- **Env vars**: `ZOOMINFO_USERNAME` + `ZOOMINFO_PRIVATE_KEY` or `ZOOMINFO_ACCESS_TOKEN`
|
||||
- **Get credentials**: Contact ZoomInfo sales or admin portal at https://app.zoominfo.com
|
||||
|
||||
## Common Agent Operations
|
||||
|
||||
### Authenticate
|
||||
|
||||
```bash
|
||||
POST https://api.zoominfo.com/authenticate
|
||||
|
||||
{
|
||||
"username": "user@company.com",
|
||||
"password": "private-key-here"
|
||||
}
|
||||
```
|
||||
|
||||
### Contact Search
|
||||
|
||||
```bash
|
||||
POST https://api.zoominfo.com/search/contact
|
||||
|
||||
{
|
||||
"jobTitle": ["VP Marketing"],
|
||||
"companyName": ["Acme Corp"],
|
||||
"managementLevel": ["VP"],
|
||||
"rpp": 25,
|
||||
"page": 1
|
||||
}
|
||||
```
|
||||
|
||||
### Contact Enrichment
|
||||
|
||||
```bash
|
||||
POST https://api.zoominfo.com/enrich/contact
|
||||
|
||||
{
|
||||
"matchEmail": ["jane@acme.com"]
|
||||
}
|
||||
```
|
||||
|
||||
### Company Search
|
||||
|
||||
```bash
|
||||
POST https://api.zoominfo.com/search/company
|
||||
|
||||
{
|
||||
"companyName": ["Acme"],
|
||||
"industry": ["Software"],
|
||||
"employeeCountMin": 50,
|
||||
"revenueMin": 10000000,
|
||||
"rpp": 25,
|
||||
"page": 1
|
||||
}
|
||||
```
|
||||
|
||||
### Company Enrichment
|
||||
|
||||
```bash
|
||||
POST https://api.zoominfo.com/enrich/company
|
||||
|
||||
{
|
||||
"matchCompanyWebsite": ["acme.com"]
|
||||
}
|
||||
```
|
||||
|
||||
### Intent Data Lookup
|
||||
|
||||
```bash
|
||||
POST https://api.zoominfo.com/lookup/intent
|
||||
|
||||
{
|
||||
"topicId": ["marketing-automation"],
|
||||
"companyId": ["123456"]
|
||||
}
|
||||
```
|
||||
|
||||
### Scoops Lookup
|
||||
|
||||
```bash
|
||||
POST https://api.zoominfo.com/lookup/scoops
|
||||
|
||||
{
|
||||
"companyId": ["123456"],
|
||||
"rpp": 25,
|
||||
"page": 1
|
||||
}
|
||||
```
|
||||
|
||||
## Key Metrics
|
||||
|
||||
### Contact Data
|
||||
- `firstName`, `lastName` - Name
|
||||
- `jobTitle` - Job title
|
||||
- `email` - Verified email
|
||||
- `phone` - Direct phone
|
||||
- `linkedinUrl` - LinkedIn profile
|
||||
- `companyName` - Company name
|
||||
- `managementLevel` - Seniority level
|
||||
- `department` - Department
|
||||
|
||||
### Company Data
|
||||
- `companyName` - Company name
|
||||
- `website` - Website URL
|
||||
- `employeeCount` - Employee count
|
||||
- `industry` - Industry
|
||||
- `revenue` - Annual revenue
|
||||
- `techStack` - Technologies used
|
||||
- `fundingAmount` - Total funding
|
||||
- `companyCity`, `companyState`, `companyCountry` - Location
|
||||
|
||||
### Intent Data
|
||||
- `topicName` - Intent topic
|
||||
- `signalScore` - Signal strength
|
||||
- `audienceStrength` - Audience engagement level
|
||||
- `firstSeenDate`, `lastSeenDate` - Signal timeframe
|
||||
|
||||
## Parameters
|
||||
|
||||
### Contact Search
|
||||
- `jobTitle` - Array of job titles
|
||||
- `companyName` - Array of company names
|
||||
- `managementLevel` - Array: C-Level, VP, Director, Manager, Staff
|
||||
- `department` - Array: Marketing, Sales, Engineering, Finance, etc.
|
||||
- `personLocationCity` - Array of cities
|
||||
- `personLocationState` - Array of states
|
||||
- `personLocationCountry` - Array of countries
|
||||
- `rpp` - Results per page (default: 25, max: 100)
|
||||
- `page` - Page number (default: 1)
|
||||
|
||||
### Contact Enrichment
|
||||
- `matchEmail` - Array of email addresses
|
||||
- `personId` - Array of ZoomInfo person IDs
|
||||
- `matchFirstName` + `matchLastName` + `matchCompanyName` - Alternative lookup
|
||||
|
||||
### Company Search
|
||||
- `companyName` - Array of company names
|
||||
- `industry` - Array of industries
|
||||
- `employeeCountMin` / `employeeCountMax` - Employee count range
|
||||
- `revenueMin` / `revenueMax` - Revenue range
|
||||
- `companyLocationCity` - Array of cities
|
||||
- `rpp` - Results per page
|
||||
- `page` - Page number
|
||||
|
||||
### Company Enrichment
|
||||
- `matchCompanyWebsite` - Array of domains
|
||||
- `companyId` - Array of ZoomInfo company IDs
|
||||
|
||||
### Intent Data
|
||||
- `topicId` - Array of intent topic IDs
|
||||
- `companyId` - Array of company IDs
|
||||
|
||||
## When to Use
|
||||
|
||||
- Identifying in-market accounts with intent signals
|
||||
- Building targeted contact lists by role, seniority, and company
|
||||
- Enriching leads with verified contact data and firmographics
|
||||
- Finding decision-makers at target accounts for ABM
|
||||
- Tracking company news and leadership changes via scoops
|
||||
- Prioritizing outreach based on buyer intent signals
|
||||
|
||||
## Rate Limits
|
||||
|
||||
- Rate limits vary by plan and endpoint
|
||||
- Standard: ~200 requests/minute
|
||||
- Bulk endpoints: batched requests recommended
|
||||
- Authentication tokens expire after ~12 hours
|
||||
|
||||
## Relevant Skills
|
||||
|
||||
- cold-email
|
||||
- revops
|
||||
- sales-enablement
|
||||
- competitor-alternatives
|
||||
Reference in New Issue
Block a user