Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 148 additions & 8 deletions app/api/v1/paid/[product]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,152 @@ function paymentRequired(req: NextRequest, product: NonNullable<ReturnType<typeo
);
}

function payload(productId: string, req: NextRequest, proof: string) {
type GitHubRepository = {
full_name: string;
html_url: string;
description: string | null;
stargazers_count: number;
updated_at: string;
topics?: string[];
language: string | null;
};

const GITHUB_LEAD_QUERIES: Record<string, string> = {
mcp: '"model context protocol" "server" in:readme stars:>10',
x402: 'x402 USDC Base in:readme stars:>1',
'agent-frameworks': '"AI agent" framework marketplace in:readme stars:>50',
'api-tools': '"API" "pay per use" in:readme stars:>10',
};

function scoreLead(repo: GitHubRepository, segment: string) {
const text = `${repo.full_name} ${repo.description || ''} ${(repo.topics || []).join(' ')}`.toLowerCase();
let score = 35;

if (text.includes('mcp') || text.includes('model context protocol')) score += 20;
if (text.includes('x402') || text.includes('usdc') || text.includes('base')) score += 20;
if (text.includes('api') || text.includes('server') || text.includes('tool')) score += 10;
if (segment && text.includes(segment.toLowerCase())) score += 10;
if (repo.stargazers_count > 1000) score += 15;
else if (repo.stargazers_count > 100) score += 10;
else if (repo.stargazers_count > 10) score += 5;

return Math.min(score, 100);
}

function fallbackLeads(segment: string) {
return [
{
source: 'fallback',
target: 'MCP servers with paid or data-heavy tools',
url: 'https://github.com/search?q=%22model+context+protocol%22+server&type=repositories',
score: segment === 'mcp' ? 82 : 68,
reason: 'MCP tools already have agent-facing schemas, so a paid preview/buy split is straightforward.',
recommended_pitch: 'Add a free preview tool and one x402-gated paid endpoint, then list it in Pyrimid.',
suggested_first_product: 'premium_search',
},
{
source: 'fallback',
target: 'AI API wrappers with per-call compute or data cost',
url: 'https://github.com/search?q=AI+API+wrapper+server&type=repositories',
score: 74,
reason: 'Usage-based APIs map cleanly to USDC per-call pricing and affiliate distribution.',
recommended_pitch: 'Turn the highest-cost endpoint into a low-price paid product with clear JSON output.',
suggested_first_product: 'deep_analysis',
},
{
source: 'fallback',
target: 'Agent frameworks with plugin or marketplace systems',
url: 'https://github.com/search?q=AI+agent+framework+plugins&type=repositories',
score: 69,
reason: 'Framework integrations can route many downstream agents through Pyrimid by default.',
recommended_pitch: 'Embed Pyrimid discovery as an optional resolver for paid external tools.',
suggested_first_product: 'paid_tool_resolver',
},
];
}

async function fetchGitHubLeads(segment: string) {
const query = GITHUB_LEAD_QUERIES[segment] || GITHUB_LEAD_QUERIES.mcp;
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 3500);

try {
const response = await fetch(
`https://api.github.com/search/repositories?q=${encodeURIComponent(query)}&sort=updated&order=desc&per_page=5`,
{
headers: {
Accept: 'application/vnd.github+json',
'User-Agent': 'pyrimid-vendor-lead-discovery',
},
signal: controller.signal,
}
);

if (!response.ok) throw new Error(`github_search_${response.status}`);
const data = await response.json();
const repos = (data.items || []) as GitHubRepository[];

return repos.map((repo) => ({
source: 'github',
target: repo.full_name,
url: repo.html_url,
score: scoreLead(repo, segment),
stars: repo.stargazers_count,
language: repo.language,
updated_at: repo.updated_at,
reason: repo.description || 'Repository matched the live discovery query.',
recommended_pitch: 'Offer a low-friction x402 paid endpoint and Pyrimid catalog listing for agent buyers.',
suggested_first_product: repo.full_name.toLowerCase().includes('mcp') ? 'premium_mcp_tool' : 'paid_api_call',
}));
} catch {
return fallbackLeads(segment);
} finally {
clearTimeout(timeout);
}
}

async function buildVendorLeadDiscovery(segment: string) {
const leads = await fetchGitHubLeads(segment);
const sorted = leads.sort((a, b) => b.score - a.score);

return {
segment,
generated_at: new Date().toISOString(),
discovery_sources: [
{
name: 'GitHub repository search',
query: GITHUB_LEAD_QUERIES[segment] || GITHUB_LEAD_QUERIES.mcp,
},
{
name: 'Fallback segment heuristics',
query: 'Used if live GitHub search is rate-limited or unavailable.',
},
],
scoring_model: {
max_score: 100,
signals: [
'MCP or Model Context Protocol language',
'x402, USDC, or Base payment language',
'API/server/tool surface fit',
'Segment keyword match',
'GitHub stars as rough adoption signal',
],
},
leads: sorted,
outreach_template: {
subject: 'Add agent-payable x402 access with Pyrimid',
body: 'Your tool already has agent-facing value. Pyrimid can add a free preview, a paid x402 endpoint on Base USDC, and affiliate distribution without replacing your existing API.',
},
next_actions: [
'Review the top 3 leads manually before outreach.',
'Check whether each project already has a paid API or MCP listing.',
'Propose one concrete paid endpoint and starting price for each target.',
'Submit accepted vendors to the Pyrimid catalog with product_id, endpoint, price_usdc, and affiliate_bps.',
],
};
}

async function payload(productId: string, req: NextRequest, proof: string) {
const query = Object.fromEntries(req.nextUrl.searchParams.entries());

switch (productId) {
Expand Down Expand Up @@ -54,12 +199,7 @@ function payload(productId: string, req: NextRequest, proof: string) {
case 'vendor-lead-discovery': {
const segment = query.segment || 'mcp';
return {
segment,
leads: [
{ segment: 'mcp', target: 'MCP servers with paid/data-heavy tools', pitch: 'Add optional x402 payment gate + Pyrimid catalog listing.' },
{ segment: 'agent-frameworks', target: 'Agent frameworks with marketplace/plugin systems', pitch: 'Let builders sell tools to agents with Base USDC settlement.' },
{ segment: 'api-tools', target: 'AI API services with per-call cost', pitch: 'Turn API calls into agent-purchasable products.' },
],
vendor_lead_discovery: await buildVendorLeadDiscovery(segment),
};
}
case 'mcp-server-audit': {
Expand Down Expand Up @@ -128,7 +268,7 @@ export async function GET(req: NextRequest, context: { params: Promise<{ product
payment_tx: verification.txHash,
payment_amount: verification.amount?.toString(),
buyer: verification.buyer,
...payload(product.product_id, req, proof),
...(await payload(product.product_id, req, proof)),
routed_by: 'pyrimid',
links: {
docs: 'https://pyrimid.ai/quickstart',
Expand Down