RekomiRekomiBlogPricing
Rekomi Docs
Rekomi Docs
Welcome to Rekomi
API overviewAuthenticationOAuth 2.0Server-to-server trackingTracking script & window.RekomiTrack leads and signupsNo-code & non-Stripe checkoutsCustom domainConversion currencyCoupon code trackingSub-affiliate recruiting APIWebhooksZapierWhite-label embedMCP serverAPI reference
For developers
|Developers|

MCP server

Connect AI assistants (Claude, Cursor, Continue, Zed, ChatGPT, Windsurf) to your Rekomi account through Model Context Protocol.

Rekomi runs a hosted MCP server at https://mcp.rekomi.com/api/mcp. Pick your AI client below, paste two values, restart. That's it.

Claude

Claude Desktop

Paste two lines into claude_desktop_config.json. Restart.

Claude Code

Claude Code

One claude mcp add command. CLI persists the config.

ChatGPT

ChatGPT

Settings → Connectors → Add custom connector. UI only.

Cursor

Cursor

Add to ~/.cursor/mcp.json. Same JSON shape as Claude.

Windsurf

Windsurf

Cascade panel → MCP servers → Add. Streamable-HTTP.

Continue

Continue

Add to ~/.continue/config.json. Restart the extension.

Zed

Zed

Add to ~/.config/zed/settings.json under context_servers.

Generate a connection token

Every connection needs an rk_mcp_* token. It's the only credential your AI client uses.

  1. Sign in to app.rekomi.com.
  2. Open Settings → AI assistant.
  3. Click Generate connection token, give it a name (e.g. Claude Desktop laptop), and copy the rk_mcp_* value. It is shown exactly once.

Owner-only to create. Up to 10 active per organization. Revoke at any time; the change propagates within ~10 seconds. Free and Trial plans included.

Connect Claude Desktop

Edit your claude_desktop_config.json:

claude_desktop_config.json
{
  "mcpServers": {
    "rekomi": {
      "url": "https://mcp.rekomi.com/api/mcp",
      "headers": {
        "Authorization": "Bearer rk_mcp_YOUR_TOKEN_HERE"
      }
    }
  }
}

Restart Claude Desktop. Ask it "what's in my Rekomi account?" to confirm.

Connect Claude Code

claude mcp add --transport http rekomi https://mcp.rekomi.com/api/mcp \
  --header "Authorization: Bearer rk_mcp_YOUR_TOKEN_HERE"

The URL must come before --header. The --header flag is variadic, so any positional argument after it gets eaten as another header. If you see error: missing required argument 'commandOrUrl', that's the cause.

The CLI persists the config to ~/.claude.json and subsequent sessions auto-connect.

Connect ChatGPT

ChatGPT supports MCP via the Connectors UI on chatgpt.com (Plus, Pro, Team, Enterprise — 2026 Apps SDK rollout). There's no JSON config to paste; the setup is in the UI.

  1. Open chatgpt.com → profile menu (bottom-left) → Settings → Connectors → Add custom connector.
  2. Name: Rekomi.
  3. MCP server URL: https://mcp.rekomi.com/api/mcp
  4. Authentication: Custom header.
    • Header name: Authorization
    • Header value: Bearer rk_mcp_YOUR_TOKEN_HERE
  5. Save. Start a new chat, enable the Rekomi connector, ask "list my pending Rekomi affiliates".

Connect Cursor

Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json in your project root:

~/.cursor/mcp.json
{
  "mcpServers": {
    "rekomi": {
      "url": "https://mcp.rekomi.com/api/mcp",
      "headers": {
        "Authorization": "Bearer rk_mcp_YOUR_TOKEN_HERE"
      }
    }
  }
}

Connect Windsurf

Open the Cascade panel and click the hammer/plug icon → MCP servers → Add server. Pick Streamable-HTTP transport and paste:

~/.codeium/windsurf/mcp_config.json
{
  "mcpServers": {
    "rekomi": {
      "serverUrl": "https://mcp.rekomi.com/api/mcp",
      "headers": {
        "Authorization": "Bearer rk_mcp_YOUR_TOKEN_HERE"
      }
    }
  }
}

Restart Windsurf. The Rekomi tools appear under Available tools in the Cascade panel.

Connect Continue

Add to ~/.continue/config.json under experimental.modelContextProtocolServers, then restart the Continue extension:

~/.continue/config.json
{
  "experimental": {
    "modelContextProtocolServers": [
      {
        "transport": {
          "type": "streamable-http",
          "url": "https://mcp.rekomi.com/api/mcp"
        },
        "headers": {
          "Authorization": "Bearer rk_mcp_YOUR_TOKEN_HERE"
        }
      }
    ]
  }
}

Connect Zed

Add to ~/.config/zed/settings.json under context_servers:

~/.config/zed/settings.json
{
  "context_servers": {
    "rekomi": {
      "source": "custom",
      "command": null,
      "settings": {
        "url": "https://mcp.rekomi.com/api/mcp",
        "headers": {
          "Authorization": "Bearer rk_mcp_YOUR_TOKEN_HERE"
        }
      }
    }
  }
}

How it works

AI assistants speak MCP to read your affiliate program, approve applications, draft outreach, mint embed tokens, and more, all on behalf of the human asking. Every tool call lands in your audit log with actor_type = mcp. MCP works on every plan, including Trial and Free; feature-tier gates (e.g. embed tokens are Growth+) still apply regardless of how the call arrives.

Machine-readable docs for LLM-driven IDEs and agents: https://rekomi.com/llms/mcp.txt.

AI client  ──Bearer rk_mcp_xxx──►  mcp.rekomi.com/api/mcp
                                        │
                                        │ Forwards + co-signs:
                                        │   Authorization: Bearer rk_mcp_xxx
                                        │   X-Rekomi-MCP-Identity: t=<unix>,v1=<hmac>
                                        ▼
                                   api.rekomi.com/api/v1/*
                                        │
                                        │ Validates the HMAC, validates the token,
                                        │ checks role + scope, runs the action,
                                        │ logs to audit log with actor_type=mcp.
                                        ▼
                                   Your data

The token alone is useless. The backend rejects any direct call to api.rekomi.com with an rk_mcp_* token (returns mcp_relay_required). The trusted relay at mcp.rekomi.com is the only path that produces the HMAC the backend requires.

Transport is MCP Streamable-HTTP in stateless mode: each tool call is a self-contained JSON-RPC request/response over HTTPS. No long-lived sessions, no SSE upgrade. A GET https://mcp.rekomi.com/api/mcp returns a small JSON identity blob you can use as a health check.

Available tools

There are 39 tools (23 reads and 16 safe writes). Each tool maps 1:1 to one Rekomi V1 API endpoint (or, for the install-recipe tools, to an MCP-local content registry). Composition (e.g. "approve every pending affiliate") happens in your AI client's reasoning loop, not inside a tool, so every individual action is surfaced to you for approval and lands in the audit log on its own row.

ToolInputsWhat it does
list_affiliatescursor?, take? (1–200, default 50), campaignId?List affiliates across your account. Cursor-paginated. Filter by campaign.
get_affiliateidFetch one affiliate's full detail (totals, recent conversions, notes).
list_conversionscursor?, take?, affiliateId?, campaignId?, status? (Pending/Approved/Paid/Refunded/Denied), since? (ISO8601)List sales. Cursor-paginated.
record_leadaffiliateSlug, email, name?, campaignId?Record a free signup as a lead (an email tied to the referral, before payment), so a later sale is still credited even if the click cookie is gone. For Stripe and Paddle, leads are captured automatically; use this tool for other processors or free-account signups. See Track leads and signups.
list_campaignscursor?, take?List referral campaigns with commission/payout rules and affiliate count.
get_campaignidFetch one campaign with commission/payout rules and recent stats.
list_payoutscursor?, take?, status? (Pending/Processing/Paid/Failed), affiliateId?, since?List payout batches.
get_payoutidFetch one payout batch's per-affiliate line items.
dashboard_summaryrange? (7d/30d/90d/ytd/all, default 30d)At-a-glance KPIs (revenue, conversions, leads, active affiliates, pending approvals).
dashboard_timeseriesmetric (revenue/conversions/leads/clicks), range? (7d/30d/90d/ytd, default 30d)Daily timeseries for charting (revenue, conversions, leads, or clicks). ≤ ~365 points.
list_audit_logpage? (1-based, default 1), pageSize? (max 100, default 50), action?, entityType?, since?, until?Audit entries. Offset-paginated (not cursor). Returns actorType (user/api_key/mcp/system/admin), action, entityType, entityId, before, after, createdAt.
approve_affiliateidApprove a pending application. Sends the magic-link welcome email.
reject_affiliateid, reason? (max 1000 chars), notify? (default true)Reject a pending application. Optionally notifies the applicant.
preview_payoutcampaignId?, since?Compute a payout batch's per-affiliate breakdown without running it. Safe to call repeatedly.
mint_embed_tokenaffiliateId, expiresInHours? (1–720, default 24), allowedOrigins? (string or array of URLs), rotate?Issue a short-lived affiliate-dashboard embed token. Growth+ only; Starter/Trial receive plan_tier_required (402).
get_home_currency(no inputs)Read the org's HomeCurrency setting plus the supported ISO 4217 allowlist + whether the caller's plan permits changing it.
set_home_currencyhomeCurrency (3-letter ISO 4217)Change the org's HomeCurrency. Pro only; lower tiers receive plan_tier_required (402). Idempotent on identical before/after; audit-logged. Historical conversions keep their native currency.
get_program_sub_affiliate_configprogramIdRead a campaign's sub-affiliate (single-tier override) settings: { enabled, percent }.
set_program_sub_affiliate_configprogramId, enabled, percent (0–100)Enable / disable sub-affiliate recruiting on a campaign and set the override percent. Pro only; lower tiers receive plan_tier_required (402). Owner role + verified email required. Audit-logged.
list_affiliate_sub_affiliatesaffiliateIdBrand-side drilldown: list the sub-affiliates recruited by a specific affiliate, with each recruit's status, total commission generated, and override earned. Flat array (no pagination).
list_campaign_couponsprogramId, cursor?, take?List all coupon codes assigned at the campaign level.
create_campaign_couponprogramId, name, percentOff?, amountOffCents?, currency?, duration?, durationInMonths?, maxRedemptions?, expiresAt?, metadata?Create a campaign-level coupon code.
list_affiliate_couponsaffiliateId, cursor?, take?List per-affiliate coupon codes for an affiliate.
list_my_couponscursor?, take?Affiliate-side: list the calling affiliate's self-mintable campaigns and existing per-affiliate coupon codes.
generate_affiliate_couponaffiliateId, programId, vanity?Mint a per-affiliate coupon code for an affiliate on a self-mint-enabled campaign.
revoke_affiliate_couponcouponIdRevoke (deactivate) a per-affiliate coupon code.
get_org_profile(no inputs)Read the calling org's profile: name, slug, brand color, logo, description, plan tier, subscription status, trial end, payout grace days. Useful as a "who am I?" check at the start of any assistant conversation.
get_billing_state(no inputs)Read the org's billing state. Returns planTier, subscriptionStatus, trialEndsAt, stripeCustomerLinked, stripeConnectLinked, plus a plan-limits snapshot. The stripeConnectLinked boolean is the deciding factor for install path (Stripe-webhook vs pixel vs S2S).
list_install_platforms(no inputs)List every platform with a Rekomi install recipe (29 today). Returns platformKey, displayName, category, conversionFire, requiresStripeConnect, requiresApiKey. Use this to map the user's "I use Webflow" to a platform key.
get_install_recipeplatformKeyFetch the full structured install recipe for one platform: ordered steps, common gotchas, conversion-fire path, and the canonical docs URL. Unknown keys return a generic 3-path fallback recipe instead of failing.
create_campaignname, slug, description?, termsUrl?, defaultCommissionType? (Percentage/Fixed), defaultCommissionValue?, defaultCommissionModel? (Cps/Cpc/Cpl; legacy Cpa/RevShare/Hybrid still accepted), cookieWindowDays?, attributionModel?, autoApprove?, networkVisibility?Create a new campaign (referral program). Backend enforces commission type/model pairing (RevShare requires Percentage type, Cpc/Cpl require Fixed). Audit-logged.
create_affiliate_invitecampaignId, email, fullName?, slug?, personalNoteHtml?, customCommissionType?, customCommissionValue?, autoApprove? (default true)Send a branded invite email to one affiliate for a campaign. Available on every plan including Trial. Personal note HTML is server-sanitized to a strict allowlist. MIGRATION: pass slug to preserve the affiliate's existing slug from a prior platform so their existing public referral URL keeps working. Returns 409 slug_already_taken on collision.
bulk_invite_affiliatescampaignId, recipients[]? (preferred) OR emails[]? (legacy, 1-50), personalNoteHtml?, autoApprove?Bulk-invite up to 50 affiliates at once. Requires Starter tier or higher with an active paid subscription (Trial users receive paid_plan_required HTTP 402). The recipients shape carries per-row email, slug?, fullName? so migration imports preserve every affiliate's existing slug. Response includes slugConflicts[] for rows where the requested slug was rejected; those still get an invite with a fresh random slug.
import_affiliatescampaignId, affiliates[] (1-1000; per row email, fullName?, status?, paypalEmail?, slug?), includeStatuses?, notifyAffiliates?, notificationMessageHtml?Bulk-import an affiliate roster from canonical JSON rows (platform-agnostic; you map any export into Rekomi fields). Dedupes by email within the campaign and the batch (idempotent). status defaults to approved. Starter+ tier for direct API-key callers (402 plan_tier_required); MCP-relayed calls bypass the plan gate. notifyAffiliates additionally needs Growth+ with an active subscription. Returns a revertible jobId + { imported, skipped, errored, reasons }. A write tool: confirm before running.
preview_conversion_importcampaignId, conversions[] (1-1000; canonical rows)Dry-run a historical conversion/commission import. Writes nothing. Returns { rowsTotal, wouldImport, wouldSkip, wouldError, skipReasons, paidBalance, unpaidBalance }. Always run this before import_conversions and show the user unpaidBalance (how much would become payable).
import_conversionscampaignId, conversions[] (1-1000; per row affiliateEmail?/affiliateSlug? [one required], customerEmail?, customerName?, amountCents, commissionCents, currency, occurredAt, paid, type?, stripeCustomerId?, stripeSubscriptionId?, externalId?), confirmUnpaidPayout? (default false), excludePaid?Import historical conversions/commissions. Idempotent (re-running never double-pays). Money safety: paid rows lock as settled history; unpaid rows become payable only when confirmUnpaidPayout=true (defaults false). Starter+ tier for direct API-key callers (402 plan_tier_required); MCP-relayed calls bypass the plan gate. A write tool that can create payable balances: always preview first, then confirm with the user before setting confirmUnpaidPayout=true. Returns a revertible jobId + unpaidConfirmedCents.
get_attribution_params(no inputs)Read the org's custom attribution params + the 16 canonical defaults + the effective priority order the loader uses. Useful for confirming whether a migrating brand needs custom-param config or whether their source platform is already covered by the defaults.
update_attribution_paramscustom? (comma-separated string, max 10 entries)Set the brand's custom attribution params. Each entry [a-z0-9_-]{2,32}, max 10 entries, max 256 chars total. Empty / omit clears the override. Owner-level write (audit-logged).
get_install_snippetcampaignId?, withPixel?Get the ready-to-paste install snippet for the brand with program id + custom attribution params + optional pixel public key already embedded. Single source of truth for snippet generation; agent hands the response verbatim to the user. Defaults to the newest active campaign + click-tracking-only (no pixel). Returns 409 when withPixel=true and the org hasn't provisioned a pixel public key.

Cursor-paginated list responses always look like { "items": [...], "nextCursor": "…", "hasMore": true }. list_audit_log returns { "page", "pageSize", "total", "items" } instead.

The assistant calls each tool individually and surfaces its result back to you in chat. Destructive or money-affecting tools (approve_affiliate, reject_affiliate, import_affiliates, import_conversions) should be confirmed by the user before the assistant runs them. For a conversion import, always run preview_conversion_import first and review the unpaid balance before authorizing payment with confirmUnpaidPayout.

Install Rekomi with the assistant

The most common use of the MCP server is what it sounds like: "help me install Rekomi on my site." A typical session looks like this.

  1. You start a chat with Claude (or Cursor, or any MCP-capable client) and say "Help me install Rekomi on my Shopify store."
  2. The assistant calls get_org_profile to confirm who you are and what plan you're on.
  3. It calls get_billing_state to see whether you've connected Stripe yet. If stripeConnectLinked is true, it recommends the stripe-webhook path; if false, it nudges you to coupon codes or browser-pixel.
  4. It calls list_install_platforms and matches "Shopify" to shopify.
  5. It calls get_install_recipe with platformKey: shopify and walks you through the steps in chat. It surfaces the gotchas inline (Shopify Payments hides your Stripe; Custom Pixel sandbox cannot load external scripts; Shopify Collabs is a separate product).
  6. If you haven't created a campaign yet, the assistant offers to call create_campaign and asks you to confirm the name, slug, commission type, and value before doing so.
  7. If you're migrating from Rewardful / Tapfiliate / FirstPromoter / PartnerStack / Dub Partners, paste your existing affiliate emails into the chat. The assistant uses bulk_invite_affiliates to send branded onboarding emails to all of them at once. (Requires Starter tier or higher with an active paid subscription.)

What the assistant cannot do (security)

For the install flow to be safe, the MCP server intentionally does not expose certain operations as tools:

  • The assistant cannot mint API keys. If your install needs a rk_live_* bearer + rks_* signing secret (Gumroad / Rails / Django / any S2S path), the assistant will deep-link you to Settings → API keys to mint one yourself, then ask you to paste the key back. The MCP token cannot escalate into a long-lived API key that outlives the MCP token itself.
  • The assistant cannot create new MCP tokens. Token minting is owner-only and JWT-only.
  • The assistant cannot change billing or open Stripe Checkout sessions. Billing decisions stay with the human owner; the assistant can only read billing state via get_billing_state.

If a tool seems missing, that's the reason. The capability is intentionally not exposed.

Plan-gate semantics

There are two different plan gates in the Rekomi backend:

  • Public-API gate ([RequiresPlanForApiKey]): blocks Starter/Trial from calling /api/v1/* with a direct rk_live_* key. MCP-relayed traffic bypasses this — that's why MCP works on every plan.
  • Feature-tier gate ([RequiresPlan]): blocks Starter/Trial from a specific feature regardless of how it's called. MCP does not bypass this. Today this applies to mint_embed_token (Growth+) and a handful of other surfaces; a Starter user calling mint_embed_token over MCP gets plan_tier_required (HTTP 402).

If a tool returns plan_tier_required, the answer is to upgrade the plan, not to change tokens.

Security model

  • Token shape: rk_mcp_*, 256-bit random body, base64url-encoded. Stored as SHA-256 hash; plaintext never persisted.
  • One-time reveal: the full token is shown only at creation or rotation. Rotate to invalidate the old value.
  • Owner-only minting: only an organization owner can create, rotate, or revoke MCP tokens.
  • Per-org cap: 10 active tokens per organization.
  • Read+write scope: every MCP token is granted the read_write scope; the per-tool user-consent loop in your AI client is the user-facing approval gate.
  • Direct use blocked: a stolen rk_mcp_* is useless without the trusted relay. Direct hits to api.rekomi.com return mcp_relay_required.
  • Relay binding: the relay HMAC is computed over {t}.{METHOD}.{path}.{body_sha256_hex} with a shared secret. ±300 s timestamp window, constant-time compare. Replays, body tampering, and method/path swaps all fail validation.
  • Revoke propagation: revoked tokens stop authenticating within ~10 s across all instances (bounded by the auth cache TTL).
  • Audit trail: every tool call lands in your audit log with actor_type = mcp, the calling token id, action, entity, and timestamps. Filter by actor_type = mcp under Settings → Audit Log.
  • Suspension gate: a suspended account stops every MCP call within seconds.
  • PII scrubbing: tokens and the relay-identity header are scrubbed from MCP-server-side error reporting before they leave the host.

Best practices

  • Use a separate token per device or per AI client. If a laptop is lost, revoke just that token.
  • Set up read-only assistant agents by instructing the assistant not to call write tools (the sixteen writes are approve_affiliate, reject_affiliate, preview_payout, mint_embed_token, set_home_currency, set_program_sub_affiliate_config, create_campaign_coupon, generate_affiliate_coupon, revoke_affiliate_coupon, create_campaign, create_affiliate_invite, bulk_invite_affiliates, update_attribution_params, import_affiliates, import_conversions, record_lead). The audit log still records the actor as the assistant.
  • Watch your audit log under Settings → Audit Log during the first few days. Filter by actor_type = mcp to see exactly what the assistant has done.
  • Don't paste the same token into multiple clients you can't independently revoke later — one token per surface keeps blast radius bounded.

Troubleshooting

  • mcp_relay_required error — your AI client is hitting api.rekomi.com directly with an MCP token. Point it at https://mcp.rekomi.com/api/mcp instead.
  • plan_tier_required (HTTP 402) on a specific tool — the tool is feature-gated to a higher plan (e.g. mint_embed_token is Growth+). Upgrade the plan or switch to a tool that's available on your tier. Switching tokens will not help — feature gates apply to MCP traffic too.
  • unauthorized (HTTP 401) on every call — the token is wrong, revoked, or rotated. Mint a fresh one under Settings → AI assistant.
  • Tools list works but every tool returns 401 — the backend cannot validate the relay header. Most often a stale relay secret on one side; contact support.
  • Claude Code still sends the old token after I rotated — Claude Code stores the bearer header statically in ~/.claude.json. Rotating the token in the Rekomi dashboard does not propagate. Run claude mcp remove rekomi and then claude mcp add … again with the new token.
  • Claude Code logs SDK auth failed: JSON Parse error — harmless. Some MCP clients probe /.well-known/oauth-protected-resource; the server returns a clean JSON 404 and continues with bearer auth.
  • /mcp "Re-authenticate" doesn't do anything — that menu item handles OAuth-flow servers; Rekomi uses a static bearer header. Use claude mcp remove + claude mcp add to swap credentials.

See also

  • Public API reference
  • Audit log
  • Machine-readable manifest: rekomi.com/llms/mcp.txt

White-label embed

Host an affiliate's earnings dashboard on your own domain via iframe.

API reference

Every v1 endpoint with request schema, response JSON example, scope, and notes, verified against the live code.

On this page

Generate a connection tokenHow it worksAvailable toolsInstall Rekomi with the assistantWhat the assistant cannot do (security)Plan-gate semanticsSecurity modelBest practicesTroubleshootingSee also