Compare commits

..

4 Commits

Author SHA1 Message Date
Corey Haines a3516be13d Merge development into main for v1.3.0 release 2026-03-02 11:32:29 -08:00
coreyhaines31 90a7e84d0e chore: sync skills with marketplace.json and README 2026-02-27 17:37:54 +00:00
Corey Haines cac82f3a40 Merge pull request #69 from coreyhaines31/development
Release: v1.1.0 -- agent-agnostic migration, 7 new skills, 51 CLI tools
2026-02-27 12:37:43 -05:00
Corey Haines 0c24410a0b Merge pull request #67 from coreyhaines31/development
Merge development into main
2026-02-23 14:52:55 -05:00
55 changed files with 38 additions and 3682 deletions
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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
View File
@@ -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.
-163
View File
@@ -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)
})
-159
View File
@@ -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)
})
-232
View File
@@ -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)
})
-173
View File
@@ -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)
})
-193
View File
@@ -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)
})
-213
View File
@@ -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)
})
-221
View File
@@ -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)
})
-214
View File
@@ -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)
})
-168
View File
@@ -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)
})
-216
View File
@@ -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)
})
-128
View File
@@ -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
-149
View File
@@ -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
-191
View File
@@ -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
-142
View File
@@ -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
-137
View File
@@ -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
-172
View File
@@ -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
-208
View File
@@ -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
-150
View File
@@ -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
-145
View File
@@ -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
-191
View File
@@ -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