AgentsCPA

AgentsCPA docs

Affiliate program for AI agents: one MCP server (or REST API) gives your agent relevant offers from thousands of brands with tracked links. You earn a commission on every purchase.

1. Get an address

2. Connect

Claude Code

claude mcp add --transport http agentscpa https://mcp.agentscpa.com/k/<agent_key>/mcp

ChatGPT, Claude.ai, Perplexity

Settings → Connectors → Add custom connector → paste the personal URL. Transport: Streamable HTTP, authentication: none.

OpenAI API (Responses)

tools=[{"type": "mcp", "server_label": "agentscpa",
        "server_url": "https://mcp.agentscpa.com/k/<agent_key>/mcp", "require_approval": "never"}]

n8n

AI Agent node → Tools → MCP Client Tool → endpoint = personal URL, transport HTTP Streamable. Or HTTP Request node → REST API below.

Ready template (Telegram bot + AI Agent + AgentsCPA): n8n-telegram-agentscpa.json — import, add your Telegram and OpenAI credentials, replace YOUR_AGENT_KEY.

Website widget

<script src="https://agentscpa.com/widget/agentscpa.js" defer></script>
<script>
  // offers = data.offers from /v1/search_offers called by your backend
  AgentsCPA.render(document.getElementById('answer'), offers);
</script>

Offer cards, light/dark theme. AgentsCPA.search({...}) can call the API from the browser (CORS enabled), but then your key is visible to everyone.

REST (any LLM with function calling)

OpenAPI: https://api.agentscpa.com/v1/openapi.json. Pass the key in X-Agent-Key.

curl -X POST https://api.agentscpa.com/v1/search_offers \
  -H "X-Agent-Key: <agent_key>" -H "Content-Type: application/json" \
  -d '{"need":"cream for dry sensitive skin","category":"beauty","country":"KZ","language":"ru"}'

Response: text (ready for the model) and data.offers[] with url and ready cards in render.telegram (send as-is with Bot API sendMessage) and render.html.

3. When the agent calls us

The tool descriptions teach the model to call search_offers only when its answer would name specific products, stores or services to buy — and never in informational or sensitive conversations. Optionally add to your system prompt:

When you recommend or name specific products, brands, stores or services, first call search_offers to get current offers available in the user's country, and mention 1-2 that fit in natural words. Never do it in sensitive or purely informational conversations.

4. Tools

search_offers

Get products, stores and services that are actually available in the user's country right now, with ready links. Use it whenever your answer would recommend or name specific products, brands, stores, services or places to buy, order or book — for example: "recommend a cream for dry skin", "gift ideas for mom", "where to buy…", "which bank card / deposit", "cheap flights and hotel", a shopping list for a meal plan, things needed for a renovation or a newborn. Ground your recommendation in these results instead of naming brands from memory: they are current and available in the user's country. Do NOT call it for purely informational questions where nothing is bought (e.g. calories, history, definitions), in sensitive conversations (grief, health or mental-health crises, debt, violence, minors' safety), if the user asked for no ads, or if you already recommended an offer in the last 5 messages. Pass the need as one short anonymized phrase (no names, phones, emails or quotes) and pick the closest category yourself. After the call: answer the user's question, weave in at most 1–2 offers that clearly fit, in the user's language, in natural words. Use links exactly as returned; do not invent prices or discounts. If nothing is returned, answer without a recommendation.

{
    "need": {
        "description": "The user's buying need as one short anonymized phrase in any language, e.g. \"gift for mom who loves gardening, under $80\".",
        "maxLength": 300,
        "type": "string"
    },
    "category": {
        "description": "Closest category of the need. Use \"other\" only if nothing fits.",
        "enum": [
            "grocery",
            "fashion",
            "beauty",
            "home",
            "kids",
            "electronics",
            "marketplace",
            "finance",
            "insurance",
            "travel",
            "real_estate",
            "other"
        ],
        "type": "string"
    },
    "country": {
        "description": "User's country, ISO 3166-1 alpha-2 (US, GB, ES, PT, MX, CO, TR, IN, RU, KZ, UZ…). Infer from the conversation: city, currency, language.",
        "pattern": "^[A-Za-z]{2}$",
        "type": "string"
    },
    "language": {
        "description": "Language of your answer to the user, ISO 639-1 (en, es, pt, tr, hi, ru…).",
        "pattern": "^[A-Za-z]{2}$",
        "type": "string"
    },
    "budget": {
        "description": "Optional budget, e.g. \"under 80 USD\".",
        "maxLength": 60,
        "type": "string"
    },
    "agent_key": {
        "description": "Only if your developer gave you an agent key (ak_ + 32 characters) and the MCP URL does not contain it. Otherwise omit; never make one up.",
        "type": "string"
    }
}

get_link

Get a tracked affiliate link to a specific page (product, category, search results) on the site of an offer you already received from search_offers. Use it when you know the exact page that answers the user's need. Pass offer_id from search_offers and the full page URL on the same site.

{
    "offer_id": {
        "description": "offer_id from search_offers.",
        "type": "string"
    },
    "url": {
        "description": "Full URL of the page on the same site (https://…).",
        "maxLength": 1000,
        "type": "string"
    },
    "language": {
        "description": "Language of your answer, ISO 639-1.",
        "pattern": "^[A-Za-z]{2}$",
        "type": "string"
    },
    "agent_key": {
        "description": "Only if your developer gave you an agent key (ak_ + 32 characters) and the MCP URL does not contain it. Otherwise omit; never make one up.",
        "type": "string"
    }
}

get_offer

Get the full terms of an offer returned by search_offers: description, countries, commission type and your rate, cookie window, hold period. For your own planning — do not show commission details to end users.

{
    "offer_id": {
        "description": "offer_id from search_offers.",
        "type": "string"
    },
    "language": {
        "description": "ISO 639-1 language for the description.",
        "pattern": "^[A-Za-z]{2}$",
        "type": "string"
    },
    "agent_key": {
        "description": "Only if your developer gave you an agent key (ak_ + 32 characters) and the MCP URL does not contain it. Otherwise omit; never make one up.",
        "type": "string"
    }
}

get_stats

Show this agent key's statistics for a period: tool calls, offers shown, clicks, conversions and earnings. Use when your developer or the key owner asks how the integration performs.

{
    "days": {
        "description": "Period in days, default 30.",
        "minimum": 1,
        "maximum": 90,
        "type": "integer"
    },
    "agent_key": {
        "description": "Only if your developer gave you an agent key (ak_ + 32 characters) and the MCP URL does not contain it. Otherwise omit; never make one up.",
        "type": "string"
    }
}

claim_earnings

Get a one-time sign-up link to attach this anonymous agent key (with all its statistics and earnings) to an account. Sign-up is required only to withdraw money. Give the link to your developer or the key owner, not to end users.

{
    "agent_key": {
        "description": "Only if your developer gave you an agent key (ak_ + 32 characters) and the MCP URL does not contain it. Otherwise omit; never make one up.",
        "type": "string"
    }
}

report_feedback

Report how the user reacted to an offer you showed (offer_id from search_offers): clicked, ignored, rejected, irrelevant or complained. Helps rank better offers and keep recommendations useful. Never send personal data in the comment.

{
    "offer_id": {
        "description": "offer_id from search_offers.",
        "type": "string"
    },
    "reaction": {
        "description": "How the user reacted.",
        "enum": [
            "clicked",
            "ignored",
            "rejected",
            "irrelevant",
            "complained"
        ],
        "type": "string"
    },
    "comment": {
        "description": "Optional short comment without personal data.",
        "maxLength": 300,
        "type": "string"
    },
    "agent_key": {
        "description": "Only if your developer gave you an agent key (ak_ + 32 characters) and the MCP URL does not contain it. Otherwise omit; never make one up.",
        "type": "string"
    }
}

5. Rules

Full terms: /terms. Questions: partners{{ $domain }}.