Skip to main content
Glama
growsurf

GrowSurf MCP Server

Official

GrowSurf MCP Server

npm version npm downloads license node

The official GrowSurf command-line interface (CLI) and open-source Model Context Protocol (MCP) server for implementing GrowSurf referral and affiliate programs with guided steps and safe REST API wrappers.

Connect it to an AI agent and, in plain language, the agent can create a referral or affiliate program, configure rewards, install tracking, add and manage participants, and read analytics, all backed by the GrowSurf REST API.

MCP is optional. Any action-capable agent that can send HTTPS requests can start with GrowSurf's client-neutral REST workflow at https://growsurf.com/agent-start.md.

Who is this for

This MCP server is for:

  • Developers using MCP-compatible tools (Claude Code, Codex, Cursor, Copilot, and other MCP clients)

  • Teams that want guided, AI-assisted GrowSurf integrations

This MCP server is NOT for:

  • Browser-only users who want a local stdio install. ChatGPT web and Claude.ai use the hosted remote connector at https://mcp.growsurf.com. Claude Desktop can use either the local stdio server or the hosted connector. See the full client list and setup at https://docs.growsurf.com/build-with-ai#optional-connect-mcp.

Related MCP server: agentfuse-mcp

What you get

  • Guided Integration:

    • Universal Code install

    • Native iOS/Android SDK implementation guidance

    • Native GrowSurf Window guidance

    • Signup flow

    • Qualifying action flow

    • Affiliate sale / transaction tracking

    • Webhooks

  • Agent Recipes:

    • MCP prompts for creating referral programs, creating affiliate programs, advising on program design, troubleshooting referral tracking, embedding the widget, listing and fetching programs and participants, configuring rewards, wiring webhooks, and reading analytics

    • Installable Agent Skill bundle at skills/growsurf-agent-toolkit

    • Steering to review starter Design, Emails, Options, Installation, rewards, and GrowSurf Window content before patching

    • One-shot program-creation eval prompts and acceptance checks for starter content and configuration review

  • Happy‑Path REST API Wrappers:

    • Create an account and get an API key with no existing credentials

    • Read and rename the bound team, request team verification, and resend the team owner's verification email

    • List and get campaigns

    • Get campaign analytics (totals, time series, email metrics, participant engagement activity, and activation cohorts)

    • Create, update, and clone programs (campaigns)

    • List, create, update, and delete campaign rewards

    • List, create, update, and delete Program Resources, including a safe one-time FILE preparation flow

    • Get/update Design, Emails, Options, and Installation config

    • Capture temporary GrowSurf preview screenshots when the user explicitly asks for visual proof

    • List, create, update, delete, and test program webhooks

    • List, get, and add participants

    • Update a participant, email a participant, and get a participant's analytics and activity logs

    • Trigger referral credit (for referral programs), with optional delayed award (1-90 days)

    • Cancel a pending delayed referral trigger (for referral programs)

    • Record affiliate sale/transaction (for affiliate programs)

    • Create mobile participant tokens for signed-in native app users

  • Official API Library Snippets:

    • TypeScript

    • Python

    • PHP

    • Ruby

    • Java

  • Helpers:

    • Compute participant auto-auth HMAC hash

    • Normalize webhook payloads

    • Generate best‑effort idempotency keys for webhook deduplication

Requirements

  • Node.js 22+

  • A GrowSurf account for hosted OAuth

  • A GrowSurf API key for local stdio setup or manual API-key remote setup. A scoped key works as long as it has access to the tools and programs you want the agent to use.

  • A campaign (program) ID for campaign-scoped tools. Set GROWSURF_CAMPAIGN_ID as the default, pass a campaignId argument to target a specific program, or call growsurf_list_campaigns to find available programs. For a newly created program, pass the id returned by growsurf_create_campaign to the other tools.

  • Static guidance/snippet tools can run without credentials

  • Exception: growsurf_create_account needs no API key. Call it only after the authorized owner approves account creation and accepts GrowSurf's Terms of Service and Privacy Policy. The account starts a 14-day Business trial without a credit card and returns its API key once. A lost key cannot be recovered through the API, so use this only if you can store a secret past the current conversation; otherwise have the owner connect https://mcp.growsurf.com and sign in. Pause for owner email verification before protected calls. Unverified accounts are deleted after 7 days. Team-level tools do not need a campaign ID.

  • Every listed tool publishes standard MCP read-only, destructive, idempotent, and open-world safety hints. Scoped business actions stay available; API-key rotation is intentionally not an MCP tool. Rotate keys in GrowSurf Settings or through a direct REST/SDK client.

Official CLI

The npm package installs the growsurf-mcp command. Run it without a global install:

npx -y @growsurfteam/growsurf-mcp

The CLI starts GrowSurf's local stdio MCP server. Set GROWSURF_API_KEY for API-backed actions and GROWSURF_CAMPAIGN_ID for a default program. Public developer resources and static integration guidance work without credentials.

Inspect the installed command without starting the stdio server:

npx -y @growsurfteam/growsurf-mcp --help
npx -y @growsurfteam/growsurf-mcp --version

Supported MCP Hosts

For an MCP-compatible host, use GrowSurf's hosted OAuth endpoint at https://mcp.growsurf.com when the host supports remote Streamable HTTP with OAuth. Use the local npx server when the host needs a stdio process or manual API-key setup. No GrowSurf account yet? After owner approval, an agent can connect to https://mcp.growsurf.com/onboard with no credentials and call growsurf_create_account.

The GrowSurf MCP server works with any MCP-compatible host. The examples below cover a few config-based and CLI hosts. For the complete, current list of supported clients (including ChatGPT web, Claude.ai, Claude Desktop, GitHub Copilot, Gemini CLI, Devin Desktop, and Cline) with step-by-step setup, see https://docs.growsurf.com/build-with-ai#optional-connect-mcp.

  • Cursor

  • Claude Code (CLI-based)

  • Antigravity

  • Codex (CLI-based)

Cursor

  1. Open or create Cursor's global MCP configuration at ~/.cursor/mcp.json.

  2. Add a server named growsurf with the hosted OAuth endpoint:

{
  "mcpServers": {
    "growsurf": {
      "type": "http",
      "url": "https://mcp.growsurf.com"
    }
  }
}

For local stdio instead, use:

{
  "mcpServers": {
    "growsurf": {
      "command": "npx",
      "args": ["-y", "@growsurfteam/growsurf-mcp"],
      "env": {
        "GROWSURF_API_KEY": "YOUR_API_KEY",
        "GROWSURF_CAMPAIGN_ID": "YOUR_CAMPAIGN_ID"
      }
    }
  }
}

Claude Code (CLI-based)

Open your terminal and connect Claude Code to the hosted OAuth endpoint:

claude mcp add --transport http --scope user growsurf https://mcp.growsurf.com
claude mcp login growsurf

For local stdio instead, install the server directly into Claude Code:

claude mcp add growsurf \
  -e GROWSURF_API_KEY=your_api_key \
  -e GROWSURF_CAMPAIGN_ID=your_campaign_id \
  -- npx -y @growsurfteam/growsurf-mcp

Antigravity

  1. Open Antigravity.

  2. Click the menu in the panel to the right and select MCP Servers.

  3. Click Manage MCP Servers > View raw config.

  4. Recommended: in the mcp_config.json file, add the hosted OAuth endpoint:

{
  "mcpServers": {
    "growsurf": {
      "serverUrl": "https://mcp.growsurf.com"
    }
  }
}
  1. Save the config, open Settings > Customizations, and select Authenticate for GrowSurf.

For local stdio instead, use:

{
  "mcpServers": {
    "growsurf": {
      "command": "npx",
      "args": ["-y", "@growsurfteam/growsurf-mcp"],
      "env": {
        "GROWSURF_API_KEY": "YOUR_API_KEY",
        "GROWSURF_CAMPAIGN_ID": "YOUR_CAMPAIGN_ID"
      }
    }
  }
}

Codex

Recommended: connect Codex to the hosted OAuth endpoint:

codex mcp add growsurf --url https://mcp.growsurf.com
codex mcp login growsurf

Or create or edit ~/.codex/config.toml:

[mcp_servers.growsurf]
url = "https://mcp.growsurf.com"

For local stdio instead, add the following:

[mcp_servers.growsurf]
command = "npx"
args = ["-y", "@growsurfteam/growsurf-mcp"]

[mcp_servers.growsurf.env]
GROWSURF_API_KEY = "YOUR_API_KEY"
GROWSURF_CAMPAIGN_ID = "YOUR_CAMPAIGN_ID"

Or configure local stdio from the CLI:

codex mcp add growsurf \
  --env GROWSURF_API_KEY=YOUR_API_KEY \
  --env GROWSURF_CAMPAIGN_ID=YOUR_CAMPAIGN_ID \
  -- npx -y @growsurfteam/growsurf-mcp

Configuration

Set the following environment variables when running the MCP server:

  • GROWSURF_API_KEY (optional for startup; required for API-calling tools. Use a key with the scopes and program access those tools need)

  • GROWSURF_CAMPAIGN_ID (optional; the default program for campaign-scoped tools. A tool's campaignId argument overrides it, so a single server can operate on any of your programs)

  • GROWSURF_API_BASE_URL (optional; defaults to https://api.growsurf.com/v2. Useful for local or hosted MCP gateways that should call a different GrowSurf API origin)

  • GROWSURF_UPLOAD_ALLOWED_ORIGINS (required only for FILE Resource uploads; a comma-separated private allowlist of exact HTTPS origins accepted from GrowSurf upload tickets. Wildcards and URL paths are rejected)

  • GROWSURF_PARTICIPANT_AUTH_SECRET (optional; used by the hash helper)

  • GROWSURF_WEBHOOK_TOKEN (optional; used for your own webhook URL token scheme)

Run with npx

After publishing this package, customers can run:

npx @growsurfteam/growsurf-mcp

For local development in this repo:

npm install
npm run build
node dist/cli.js

MCP tools

Every tool declares an MCP output schema and returns structuredContent, so hosts know each tool's result shape. REST tools return the API response (plus a JSON text block for older clients); the guidance and snippet tools return their markdown document under markdown.

Program, reward-configuration, options, and participant reads also include a rewardEvidence object in structuredContent. It records what this response establishes about approval policy and automatic fulfillment marking. Delivery remains unknown without the relevant fulfillment records. This assessment applies to this response only; combine it with other evidence. The API fields and original JSON text remain unchanged.

Guided Integration

  • growsurf_integration_guide Step-by-step guidance for implementing a GrowSurf referral or affiliate program.

  • growsurf_mobile_sdk_guide Native iOS/Android SDK guidance for attribution, shareUrl, trackShare, and the native GrowSurf Window.

  • growsurf_api_library_snippets Official REST API library snippets for TypeScript, Python, PHP, Ruby, and Java.

  • growsurf_list_integrations List every integration the program can connect, each with connected, enabled, autoDisabled, and the dashboard connectUrl. Check this before acting on an integration.

  • growsurf_get_integration_connect_link Get a dashboard link that opens a specific integration's connect panel (Stripe, PayPal, Tango Card, Mailchimp, and many more). Hand it to the user when they want to connect one. The program is checked first, and the result reports whether the integration is already connected. Connecting happens in the dashboard, not through the API.

Program design and troubleshooting

  • growsurf_program_design_advisor Returns a short first draft by default. Set detail: "full" for the complete report, including reward, sharing, and integration figures. benchmarkFacts carries complete statements with each ratio's unit, median, quartiles, sample, and source. Quote these statements together so a referral ratio cannot be mistaken for the percentage of people who refer.

    Recommend a qualifying action, reward structure, fulfillment path, safeguards, share channels, and integrations. The result includes markdown, a configurationPlan with exact tool arguments, and decisions with the qualifying action and unresolved customer choices. Call it before proposing rewards. Preserve the returned call shapes; the advisor and program-creation tools use different goal enums. Replace each <new-program-id> with the id returned by program creation. Drafts leave reward amounts and commission terms open until the customer chooses them; a budget is a limit, not an incentive. Set salesMotion to sales_led for demos or negotiated contracts, or self_service for direct purchases. When the host supplies insights, advice includes aggregate figures; without insights it uses documentation. Non-USD advice and budget comparisons omit dollar reward bands because the data mixes dollar currencies.

  • growsurf_troubleshoot_referral_tracking Symptom-first diagnosis: referrals not credited, participant emails not sending, rewards not issued, participants not added, Universal Code not detected, integrations not syncing, Zapier errors, fraud flags, dashboard numbers that look wrong, and more. Returns the checks to run in order (with the read tool and field for each), the likely causes most common first, fixes, and doc links. Pass a symptom key, or a description that names the symptom.

Client & UI Snippets

  • growsurf_client_snippets JavaScript SDK, GrowSurf Window, and embeddable examples. Includes a reminder to use a frontend design workflow when placing or styling embeddable UI.

  • growsurf_embeddable_element_snippet HTML snippet for a specific GrowSurf embeddable element.

  • growsurf_grsf_config_snippet <head> snippet for configuring window.grsfConfig and participant auto-auth.

Account onboarding

  • growsurf_create_account Create a GrowSurf account and get an API key. This is the only tool that does not require GROWSURF_API_KEY. The returned key is shown once and locked (403 EMAIL_NOT_VERIFIED_ERROR) until the owner verifies their email; verification unlocks that same key, so keep it and retry. It is replaced only on the owner's first dashboard sign-in. Creating an account agrees, on the account holder's behalf, to GrowSurf's Terms of Service and Privacy Policy.

Team

  • growsurf_get_team Fetch the team bound to the API key or OAuth connection, including its GrowSurf verification state.

  • growsurf_update_team Update the bound team's display name.

  • growsurf_request_team_verification Ask GrowSurf to verify the bound team, which is required before a program can email participants.

  • growsurf_resend_team_owner_verification_email Resend the verification email to the bound team's owner without revealing their email address.

API & Tracking

  • growsurf_get_campaign Fetch campaign configuration.

  • growsurf_list_campaigns List programs available to the credential. Use this to find a campaignId before calling campaign-scoped tools.

  • growsurf_get_campaign_analytics Fetch program analytics, with optional per-period series, comparison, status, rate, email metrics via include=email, and participant activity-period engagement via include=engagement.

  • growsurf_get_campaign_activation_analytics Fetch eligible-participant activation cohorts with a fixed 7- or 30-day observation window. Referral programs group by enrolledAsAdvocateAt; affiliate programs group by approvedAsAffiliateAt. Read coverageStartAt, state, and reason before interpreting zeroes or nulls.

  • growsurf_create_campaign Create a new program (campaign) with type-appropriate starter content and optional inline rewards (only needs GROWSURF_API_KEY, not GROWSURF_CAMPAIGN_ID). Review the seeded Design, Emails, Options, Installation, rewards, and GrowSurf Window content before patching.

  • growsurf_agent_program_creation_eval Generate one-shot program-creation eval prompts and acceptance checks for starter content, conservative rewards, configuration review, frontend install proof, and clean public copy.

  • growsurf_update_campaign Update the program's identity and lifecycle: name, company branding, and status (only the fields you send are changed).

  • growsurf_clone_campaign Clone the program into a new DRAFT program (integrations and credentials are not copied).

  • growsurf_list_campaign_rewards List the program's configured rewards.

  • growsurf_create_campaign_reward Create a campaign reward.

  • growsurf_update_campaign_reward Update a campaign reward by its reward key.

  • growsurf_delete_campaign_reward Delete a campaign reward by its reward key.

  • growsurf_list_program_resources / growsurf_create_program_resource / growsurf_update_program_resource / growsurf_delete_program_resource Manage ordered participant resources. LINK uses HTTPS and TEXT uses plain text.

  • growsurf_prepare_program_resource_file Request a one-time ticket and upload an allowed file up to 10 MB to the exact host-allowlisted destination selected by GrowSurf. Pass the returned ticket and signed result unchanged to create/update. The tool accepts no upload URL or credential and never retries an upload.

  • growsurf_get_campaign_design / growsurf_update_campaign_design Read or patch design configuration, including the Program Editor Design tab and payout-destination confirmation page copy.

  • growsurf_get_campaign_emails / growsurf_update_campaign_emails Read or patch the Program Editor Emails tab config.

  • growsurf_get_campaign_options / growsurf_update_campaign_options Read or patch the Program Editor Options tab config.

  • growsurf_get_campaign_installation / growsurf_update_campaign_installation Read or patch the Program Editor Installation tab config.

  • growsurf_capture_referral_flow_screenshots Capture temporary GrowSurf preview screenshots for the current program after the user explicitly asks for visual proof. This returns the controlled referrer Window and referred-friend experience; use browser automation instead to prove the user's installed site.

  • growsurf_list_campaign_webhooks List the program's webhooks (secrets are never returned).

  • growsurf_create_campaign_webhook Add a webhook to the program (with events and a write-only signing secret).

  • growsurf_update_campaign_webhook Update a webhook by id (primary for the program's primary webhook).

  • growsurf_delete_campaign_webhook Remove a webhook by id.

  • growsurf_test_campaign_webhook Send a live test event to a webhook using its stored URL and secret.

  • growsurf_add_participant Add a participant (or referred participant) during signup.

  • growsurf_list_participants List participants in the current program, paginated by nextId. Use this to find a participant ID before calling participant-scoped tools.

  • growsurf_get_participant Fetch one participant by GrowSurf participant ID or email address.

  • growsurf_update_participant Update a participant by ID or email (including internal notes).

  • growsurf_bulk_delete_participants Permanently delete up to 200 participants (by ID and/or email, mixed lists allowed) in one request, with per-row DELETED/NOT_FOUND/DUPLICATE/ERROR results. Irreversible — removes the participants' referrals, rewards, commissions, and payout records.

  • growsurf_email_participant Email a participant using a configured template or a free-form subject/body.

  • growsurf_get_participant_analytics Fetch one participant's engagement, rank, share, affiliate revenue, commission, payout, optional email metrics, and covered first milestones. Use include=activation for milestones such as firstPortalViewedAt and firstShareChannel; add series for covered portalViews and shareActions. An unavailable null is unknown, not proof that the action never happened.

  • growsurf_get_participant_activity_logs List a participant's activity logs (offset/limit paginated).

  • growsurf_trigger_referral Trigger referral (for referral programs only). Optionally pass delayInDays (1-90) to hold the credit for N days before awarding it (e.g. to cover a refund window).

  • growsurf_cancel_delayed_referral Cancel a pending delayed referral trigger before the delay elapses (e.g. on refund/cancellation).

  • growsurf_get_participant_payout_destination Get a participant's payout-destination status across every provider enabled for the program (PayPal and/or Wise): per-provider status, confirmed payout email, legal recipient type, and repair reason.

  • growsurf_request_participant_payout_destination_confirmation Ask a participant to confirm their payout destination for a provider — sends them a one-time confirmation link (only the participant can confirm).

  • growsurf_record_sale Record affiliate sales or transactions (for affiliate programs only).

  • growsurf_refund_transaction Record an amendment (refund, partial refund, or chargeback) against a recorded transaction; reverses or adjusts the referrer's commission (for affiliate programs only). The inverse of growsurf_record_sale.

  • growsurf_create_mobile_participant_token Create or fetch a participant, then create a participant-scoped mobile SDK token for a signed-in mobile user.

Helpers

  • growsurf_participant_auth_hash Generate participant auto-auth HMAC hashes (to authenicate participants automatically).

  • growsurf_webhook_normalize Normalize webhook payloads and generate idempotency keys (to deduplicate webhook deliveries).

Webhooks

GrowSurf webhooks notify your server when important referral or affiliate events occur, such as when new objects like participants, referrals, rewards, or transactions are created. Here are common use-cases:

  • Fulfill rewards automatically

  • Maintain internal points or credit systems

  • Sync participant and referral data into your database

Duplicate Delivery Handling

Webhook handlers should be idempotent because the same event can arrive more than once. Store an idempotency key before changing anything in your system.

Webhook Security & Idempotency

GrowSurf signs webhook deliveries when the webhook has a secret configured: each delivery includes a GrowSurf-Signature HMAC header computed with that secret (the secret is write-only and never returned). To securely use webhooks, we recommend the following:

  • Set a secret on the webhook and verify the GrowSurf-Signature header on receipt

  • Validate the payload shape and expected event type

  • Deduplicate webhook events using an idempotency key, because the same event can arrive more than once

The GrowSurf MCP server provides a helper tool (growsurf_webhook_normalize ) that normalizes webhook payloads and generates a best-effort idempotency key to simplify safe webhook processing.

Development and Testing

npm run dev
npm test

Additional Resources

Read developer docs at the following:

The GrowSurf MCP server helps GrowSurf customers implement referral programs and affiliate programs quickly.

Available Tools

63 tools
growsurf_add_participantAInspect

Add or fetch a participant by email. Existing participants are returned unchanged. This is trusted direct enrollment; do not use it for a public application when the program requires affiliate review. For affiliate programs, set isAffiliate to true to enroll a new participant as approved or false to create a non-affiliate. If you omit it, a valid referredBy creates a referred non-affiliate; without a valid referrer, the new participant is enrolled as approved. A valid referredBy can be combined with isAffiliate: true. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
emailYes
lastNameNo
metadataNo
firstNameNo
ipAddressNo
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
referredByNo
fingerprintNo
isAffiliateNoAffiliate programs only. Controls affiliate enrollment for a new participant. `true` enrolls the participant with `affiliateStatus: APPROVED`; `false` creates a non-affiliate without `affiliateStatus`. Existing participants are returned unchanged.
referralStatusNo
mobileInstanceIdNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are all false, so the description carries the burden. It discloses idempotent behavior ('Existing participants are returned unchanged'), explains affiliate status logic in detail, and warns about misuse. It doesn't mention side effects like email triggers, but the core behavior is well covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is lengthy but each sentence carries essential information. It front-loads the primary action, then details conditional logic. No filler, and the structure follows a logical order from purpose to exclusions to parameter behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter tool with an output schema, the description covers enrollment logic, campaign targeting, and warnings. It omits explanation of several less-critical parameters and does not describe output or error scenarios, though the output schema covers return values. Adequate but with gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 18%, so description must compensate. It does explain isAffiliate and referredBy extensively, and reinforces campaignId. However, it is silent on other parameters like metadata, ipAddress, fingerprint, etc., leaving those unclear. It adds value for the most critical params but not all.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Add or fetch a participant by email' with a specific verb and resource, and clarifies that existing participants are returned unchanged. It also contrasts with public application flows, distinguishing itself from the broader enrollment context, though it does not explicitly name a sibling tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides explicit guidance: 'This is trusted direct enrollment; do not use it for a public application when the program requires affiliate review.' It also details when to set isAffiliate true/false and the interaction with referredBy, plus campaign targeting via campaignId or default. While it doesn't name an alternative tool, the conditions are clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_agent_program_creation_evalA
Read-onlyIdempotent
Inspect

Generate one-shot GrowSurf program-creation eval prompts and acceptance checks for agent steering: starter content review, conservative rewards, configuration review, and frontend install proof.

ParametersJSON Schema
NameRequiredDescriptionDefault
programTypeNoboth
includeOneShotPromptsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only, idempotent, and non-destructive behavior, so the description's burden is reduced. It adds value by specifying the output nature (eval prompts and acceptance checks for four areas), which goes beyond the structured hints and aligns with the read-only intent without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, well-structured sentence that front-loads the primary action and then lists specific sub-areas. It is concise, and every phrase contributes to understanding the tool's scope without unnecessary fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has two optional parameters and an output schema, but the description does not explain parameter usage, which is critical for correct invocation. While the output schema likely documents returns, the input side is underspecified, leaving the agent uncertain about how to set programType or includeOneShotPrompts for different eval scenarios.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and the description does not mention either parameter (programType or includeOneShotPrompts). The agent receives no semantic guidance on how these optional parameters influence the generated prompts, forcing inference from enum values and defaults alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool generates one-shot eval prompts and acceptance checks for GrowSurf program creation, listing specific coverage areas (starter content review, conservative rewards, configuration review, frontend install proof). This distinguishes it from sibling CRUD tools and leaves no ambiguity about its function.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description mentions 'for agent steering' but does not explicitly state when to use this tool versus alternatives or provide exclusions. Since no sibling performs a similar function, the intended use is somewhat self-evident, but the lack of explicit usage context or conditions is a gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_api_library_snippetsC
Read-onlyIdempotent
Inspect

Generate official REST API library snippets for TypeScript, Python, PHP, Ruby, and Java, including Create Mobile Participant Token.

ParametersJSON Schema
NameRequiredDescriptionDefault
emailNo
languageNoall
workflowNoall
campaignIdNo
referredByNo
participantIdOrEmailNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds that it generates snippets for specific languages and includes a particular workflow, which is useful but not deeply behavioral. It does not disclose rate limits, response format, or any side effects beyond what annotations imply. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, dense sentence with no filler. It front-loads the core action and includes relevant details about languages and a key workflow. It could be slightly more structured (e.g., listing all workflows), but it is appropriately concise and information-dense.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 6 optional parameters, two enums, and an output schema, this description is far too minimal. It does not explain how the parameters customize the generated snippets, what the response contains, or any workflow-specific requirements. Even though annotations cover safety, an agent would not know how to correctly populate the parameters to get the desired snippet. The description leaves too much implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must explain the parameters. It only hints at the 'language' parameter by listing languages and the 'workflow' parameter by mentioning 'Create Mobile Participant Token' (which maps to one enum value). There is no explanation of email, campaignId, referredBy, or participantIdOrEmail, leaving most parameters under-explained. The description carries the burden but only partially addresses it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Generate') and the output ('official REST API library snippets') for a specific set of languages. It also highlights a distinct workflow ('Create Mobile Participant Token'), making the purpose clear. However, it does not explicitly distinguish this tool from related snippet-generation siblings like growsurf_client_snippets or growsurf_embeddable_element_snippet, so it loses a point for not differentiating.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus the many sibling tools. No conditions, prerequisites, or alternatives are mentioned. The description only states what it does, not when it should be chosen over other snippet generators or integration guides. This is a significant gap for a tool with many related siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_bulk_delete_participantsA
DestructiveIdempotent
Inspect

Bulk delete participants from your GrowSurf program in one request. DESTRUCTIVE: deletion is permanent, cannot be undone, and removes the participants' referrals, rewards, commissions, and payout records. Each entry in participants is a GrowSurf participant ID or an email address (mixed lists are allowed), up to 200 entries per request — chunk larger lists across multiple calls. Returns a summary (total, deletedCount, notFoundCount, duplicateCount, errorCount) plus per-row results in request order, each with status DELETED, NOT_FOUND, DUPLICATE (resolves to the same participant as an earlier entry), or ERROR — a 200 response can still include NOT_FOUND or ERROR rows, so check the summary. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
participantsYesGrowSurf participant IDs and/or email addresses to delete (1-200 entries; mixed lists allowed).

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultsNoOne entry per submitted identifier, in request order.
summaryNoCounts across all submitted entries.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveHint=true and idempotentHint=true, but the description goes far beyond by detailing exactly what is destroyed (referrals, rewards, commissions, payouts), the response structure (summary and per-row statuses), and the fact that a 200 response can include NOT_FOUND or ERROR rows. This prepares the agent for partial failures and cascading effects, adding significant value beyond structured metadata.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense yet efficient — the destructive warning is front-loaded, and every subsequent sentence adds distinct value (chunking, response format, campaign fallback). There is no filler or redundancy, and the structure guides the agent from warning to usage to expectation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with this complexity — bulk deletion with nuanced response semantics and destructive side effects — the description is complete. It explains limits, response parsing, status meanings, and the campaign fallback, all essential for correct invocation, especially given the existing output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides 100% description coverage for both parameters, including mixed types, max 200 entries, and the default campaignId. The description reiterates these points but does not introduce new semantic meaning beyond the schema, so it meets the baseline for high schema coverage without adding extra value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool bulk deletes participants from a GrowSurf program, using the specific verb 'delete' and resource 'participants'. It distinguishes itself from single-participant and campaign-level tools by emphasizing 'bulk' and 'in one request'. The scope is immediately evident.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description offers practical usage guidance, including chunking lists larger than 200 entries and the campaignId default behavior. However, it does not explicitly name alternative tools (e.g., growsurf_update_participant) or state when not to use this tool, so it's clear but lacks comparative exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_cancel_delayed_referralA
DestructiveIdempotent
Inspect

Cancel a pending delayed referral trigger for a participant before the delay elapses (e.g. on refund/cancellation). Returns { success, message }. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
participantIdNo
participantEmailNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable result message. Present when credit was not awarded immediately.
successNoWhether referral credit was awarded, scheduled, or cancelled.

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and idempotentHint=true. The description adds the 'before delay elapses' limit and the return shape, but does not disclose error behavior (e.g., if the delay already elapsed or the participant is not found). It provides some context beyond annotations but not comprehensive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two well-structured sentences: the first states the action and context, the second covers return format and campaignId default. It is efficient and avoids fluff, though the return format might be redundant given an output schema exists.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the core purpose and typical scenario, but misses edge cases like behavior after the delay elapses, error messages, and which participant identifier to prefer. With an output schema present, it is adequate for a simple cancel operation but not fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 33% – only campaignId is described. The description clarifies campaignId's default but leaves participantId and participantEmail entirely undocumented. With low coverage, the description should compensate but does not, leaving param semantics weak.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('cancel'), the resource ('a pending delayed referral trigger for a participant'), and the timing condition ('before the delay elapses'). This distinguishes it from sibling tools like growsurf_trigger_referral, making the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a specific use case ('on refund/cancellation') and implies the constraint that cancellation is only valid before the delay expires. However, it does not explicitly compare with alternatives or state when not to use it, leaving the agent to infer routing logic.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_capture_referral_flow_screenshotsAInspect

Capture temporary GrowSurf preview screenshots after the user explicitly asks for screenshots or screenshot proof. Returns short-lived URLs for the controlled referrer Window and referred-friend experience for this program. This does not prove the user's installed site; use browser automation for that. This tool does not accept arbitrary URLs, HTML, JavaScript, or external screenshot targets. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
expiresAtNoWhen the signed URLs stop working (ISO 8601).
generatedAtNoWhen the screenshots were captured (ISO 8601).
screenshotsNoOne entry per captured view.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide no safety hints (all false), so the description must carry the transparency burden. It discloses that URLs are short-lived, that the tool targets campaignId or falls back to GROWSURF_CAMPAIGN_ID, that it does not prove installed sites, and that it rejects arbitrary inputs. This is meaningful behavioral disclosure. A minor gap is that it doesn't mention any side effects (e.g., whether it stores or modifies anything), but given the read-like nature, this is acceptable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences, front-loaded with the core action, then constraints and targeting. It avoids filler but does repeat 'screenshot' a few times. Overall it is efficient and well-structured for an agent to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given an output schema exists (which will define the return structure), the description covers everything an agent needs to decide when to use it and how to invoke it: the exact trigger, the limitation (does not prove installation), the rejection of arbitrary inputs, and the default behavior for the campaignId parameter. No critical context is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter `campaignId` is fully documented in the schema with 100% coverage, and the description only restates the same information ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID'). Since the schema already covers the semantics, the description adds no new meaning, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action: 'Capture temporary GrowSurf preview screenshots'—a specific verb with a specific resource. It also explicitly scopes the tool to the controlled referrer window and referred-friend experience, and disambiguates from any generic screenshot tool by stating it does not accept arbitrary URLs or external targets. This strongly distinguishes it from the listed sibling tools, none of which are screenshot-specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Contains an explicit trigger condition: 'after the user explicitly asks for screenshots or screenshot proof.' It also names an alternative ('use browser automation for that') to clarify what this tool does not prove, and clearly states what it does not accept (arbitrary URLs, HTML, JavaScript, external targets). This leaves no doubt about when to use this tool versus alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_client_snippetsC
Read-onlyIdempotent
Inspect

Generate copy-pasteable client-side snippets for GrowSurf referral tracking, embeddable elements, and the GrowSurf Window (JS + CSS), with placement guidance for app UI work.

ParametersJSON Schema
NameRequiredDescriptionDefault
programTypeNoboth
singlePageAppNo
referralTriggerNosignup_plus_qualifying_action
includeUnreadBadgeNo
includeGrowSurfWindowNo
participantAuthEnabledNo
includeEmbeddableElementsNo
includeEventSubscriptionsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

C2.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already disclose that the tool is read-only and idempotent (readOnlyHint=true, idempotentHint=true). The description adds minimal behavioral context by noting it produces 'copy-pasteable' snippets and includes 'placement guidance', but it does not elaborate on output specifics or side effects. Given the annotations cover safety, the description provides only marginal additional transparency, warranting a mid-range score.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that efficiently communicates the tool's purpose and scope, front-loading the action and resource. It avoids fluff but is slightly dense; however, it remains concise and clear. No redundant information is included, though it could be broken into two sentences for better readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has 8 parameters (all optional) and no schema parameter descriptions, and an output schema exists but its content is not provided. The high-level description contributes little to understanding the parameter functionality or the expected return structure. Without any explanation of how parameters control the output, the context is incomplete for an agent to use it effectively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% – none of the 8 parameters have descriptions in the schema. The tool description does not explain any parameter such as `programType`, `singlePageApp`, `referralTrigger`, or the boolean toggles. With zero compensation for the missing schema documentation, an agent cannot determine how these parameters affect the generated snippets. This is a critical gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb ('Generate') and a specific resource ('copy-pasteable client-side snippets for GrowSurf referral tracking, embeddable elements, and the GrowSurf Window (JS + CSS)') with placement guidance. It names the types of snippets and distinguishes itself from pure configuration tools, though it does not explicitly differentiate from the sibling `growsurf_embeddable_element_snippet` which overlaps in scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description offers no explicit guidance on when to use this tool versus alternatives. It mentions 'placement guidance for app UI work' which implies a UI integration scenario, but it does not state exclusions or name sibling tools (e.g., `growsurf_embeddable_element_snippet`) that cover specialized cases. An agent would have to infer usage, which is not sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_clone_campaignAInspect

Clone your GrowSurf program (campaign) into a new DRAFT program. Integrations and credentials are not copied; active rewards are cloned. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (mutation, non-destructive), the description adds key behaviors: integrations/credentials are not copied, active rewards are copied, and the resulting program is a DRAFT. This informs the agent of the tool's side effects and scope, which is valuable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the primary action and outcome, then caveats about exclusions and defaults. Every sentence adds information; no wasted words or repetitive phrasing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the tool's purpose, parameter default, and critical behavioral nuances (what is not copied). The presence of an output schema reduces the need to describe return values. It does not mention edge cases or side effects on the original, but for a clone operation this is sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already fully documents the campaignId parameter, including its default behavior and how to obtain it. The description merely restates this ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID') without adding new meaning. With 100% schema coverage, a baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Clone'), the resource ('GrowSurf program (campaign)'), and the outcome (a new DRAFT program). It also details what is and isn't copied, making it distinct from sibling tools like create_campaign or update_campaign by focusing on duplication.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the use case (duplicating an existing program) but does not explicitly contrast with alternatives or state when NOT to use it. It avoids mentioning that this is for cloning rather than creating from scratch, leaving the agent to infer from the verb 'clone'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_create_accountA
Destructive
Inspect

Create a brand-new GrowSurf account and return an API key. Call this tool only after the authorized owner explicitly approves account creation and accepts GrowSurf's Terms of Service (https://growsurf.com/terms) and Privacy Policy (https://growsurf.com/privacy). This is the only tool that does not require GROWSURF_API_KEY. The account starts a 14-day Business trial without a credit card. The endpoint returns the new key once in apiKey. A lost key cannot be recovered through this API, so do not create an account here unless you can store the key somewhere that outlives the current conversation. If you cannot, ask the account owner to connect GrowSurf's hosted MCP server at https://mcp.growsurf.com instead, which keeps the credential with your tool rather than in chat. The key is locked until the account owner's email address is verified. Until then, program and resource endpoints return a 403 with error code EMAIL_NOT_VERIFIED_ERROR. Create the account, tell the owner to click the link in the verification email, then retry until that error clears. Use growsurf_resend_team_owner_verification_email if the email was lost. The welcome email also contains a set-password link for dashboard access. Accounts whose email is never verified are deleted automatically after 7 days. Verification unlocks the same key you were given, so keep it and retry rather than asking for a replacement. Separately, the API key is replaced the first time the account owner signs in to the GrowSurf dashboard; after that the previous key returns a 403 with error code NOT_AUTHORIZED_ERROR. Some actions, such as emailing participants, also require GrowSurf to verify the team. Personal and disposable email addresses are not accepted.

ParametersJSON Schema
NameRequiredDescriptionDefault
emailYes
companyNo
lastNameNo
firstNameNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
emailNoEmail address for the new account.
apiKeyNoAn API key for the new account. Shown once, locked (`403` `EMAIL_NOT_VERIFIED_ERROR`) until the account's email is verified, and rotated when the owner first signs in to the dashboard.
verificationStatusNoTeam verification state for the new account.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only set readOnlyHint=false and destructiveHint=true. The description goes far beyond, disclosing trial period, key locking until email verification, auto-deletion after 7 days, key replacement on first sign-in, and the specific error codes. This is extensive behavioral context that an agent needs and is not present in structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every sentence adds necessary information about verification, error handling, and key storage. It is front-loaded with the primary purpose and preconditions. While dense, it is not redundant; a 4 is appropriate for its efficiency given the complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex account-creation tool, the description covers the full lifecycle: prerequisites, token retrieval, verification, error codes, retry logic, key replacement, and automatic deletion. An output schema exists so return values need not be explained. Nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden. It explains constraints on email (personal/disposable not accepted) but does not clarify the meaning or format of company, firstName, or lastName. Partial compensation; enough to avoid misuse of email but leaves other fields ambiguous.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action (create a brand-new account), the resource (GrowSurf account), and the key outcome (returns an API key). It also differentiates from all siblings by noting it's the only tool not requiring GROWSURF_API_KEY. This is unambiguous and distinguishes it well.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit conditions for use (owner approval, terms acceptance) and explicitly names an alternative (hosted MCP server) when key storage is not possible. Also gives post-call guidance (verification email, resend tool) and when to retry. This fully covers when and when-not to use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_create_campaignAInspect

Create a new GrowSurf program (campaign) pre-populated with type-appropriate starter content, optionally with inline rewards. Starter content includes Design, Emails, Options, Installation, and GrowSurf Window defaults. Only type is required; the program is created in DRAFT status owned by the credential's bound team. currencyISO sets the program's currency (defaults to USD) and is immutable after creation. Pass goal so the share settings suit the audience; it is set here or not at all. Ask the person for the incentive rather than choosing one: leave rewards out unless they named an amount, and tell them the program starts with GrowSurf's starter rewards switched off so it awards nothing yet. Editor-tab config (design, emails, options, installation) is not accepted here. Fetch and review those config sub-resources after creation, then patch only what needs to change. Does NOT require GROWSURF_CAMPAIGN_ID. The response includes the new program id; pass it as campaignId to the other tools (or set GROWSURF_CAMPAIGN_ID) to configure and operate the program.

ParametersJSON Schema
NameRequiredDescriptionDefault
goalNoWhat the program is for, which seeds share settings that suit that audience. Programs selling to businesses (`CUSTOMERS`, `USERS`, `B2B_SAAS_SELF_SERVICE`, `B2B_SAAS_ENTERPRISE`) start with the LinkedIn share button visible. Consumer, financial, education, insurance, newsletter, and waitlist programs (`B2C_SUBSCRIPTIONS`, `FINANCIAL_SERVICES`, `ONLINE_EDUCATION`, `ONLINE_INSURANCE`, `SUBSCRIBERS`, `WAITLIST`) start with it hidden. Omit `goal` and every share button keeps its standard default. Change any of it afterward with `growsurf_update_campaign_design`. Set only at creation; `growsurf_update_campaign` does not accept it.
nameNo
typeYes
rewardsNoRewards to create with the program. Include this only when the person told you the amount and who funds it. Omit it and the program is seeded with starter rewards that are switched off, awarding nothing until the customer enables one. Send `[]` to start with no rewards at all.
companyNameNo
currencyISONo
companyLogoImageUrlNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations are all false, so the description carries the full burden of disclosing effects. It does this well: the program is created in DRAFT status, owned by the bound team, starts with GrowSurf's starter rewards switched off, custom currency is immutable after creation, and no GROWSURF_CAMPAIGN_ID is required. It also says the response includes the new program id and how to use it, which is exactly the operational behavior an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than the MCP norm, but nearly every sentence earns its place by preventing a common mistake: leaving rewards to renting behavior, passing too much bulk because currency immutable, or expecting it is a patch tool. It is front-loaded with the core purpose and only later moves to workflow details. It does not have any fluff, but a bullet or paragraph break could help an agent scan it quickly, so it loses one point on structure.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a creation tool, the description gives all the context needed to invoke it correctly: defaults, required vs optional behavior, what is not accepted, what the response supplies, and how to chain the id into the rest of the GrowSurf toolset. Since an output schema exists, the description does not need to inventory the return fields. There are no major gaps that would cause a placeholder execution besides unclear user-provided values, which no static text can resolve.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With parameter-based schema coverage only 29%, guidance needed to compensate, and the description does that for the most important fields: `type` is mandatory, `goal` is set only at creation and configures sharing, `currencyISO` defaults to USD and is immutable, and `rewards` has clear inclusion rules plus the `[]` distinction. `name`, `companyName`, and `companyLogoImageUrl` are left to their self-evident names and simple schema labels, so the description does not document every param but it does add high-value semantics for the ones that matter most.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Create a new GrowSurf program (campaign)' and immediately states the main behavior—pre-populating the program with starter content and optionally adding rewards. It also distinguishes this creation tool from related configuration tools by explicitly saying editor-tab config is not accepted here and that the resulting id is used by other tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear guidance on when valid, including 'Only type is required', when to omit or send rewards, and why to pass goal. It states that editor-tab configuration is not handled here and should be fetched and patched afterward. It does not explicitly name sibling alternatives like growsurf_create_campaign_reward or growsurf_update_campaign_design, but it points the agent to the correct post-creation workflow using config sub-resources, so the guidance is strong but not fully explicit on alternative tool names.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_create_campaign_rewardAInspect

Create a new campaign reward (reward config) on your GrowSurf program. type must be compatible with the program type (affiliate programs support only AFFILIATE rewards; referral programs support the other types). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
typeYes
eventNoThe referral event that earns this Campaign Reward. Use `LEAD` for a referred signup or `CONVERSION` for a qualifying action. A `LEAD` reward requires a later custom conversion trigger. Referral reward types only.
limitNo
orderNo
titleNo
valueNoTax valuation for the reward (the referrer's side of a double-sided reward). `fairMarketValueUSD` is the manual fair-market value in USD (major units). `taxCharacter` is the reason the recipient earns the reward. For configurable non-commission rewards, `null` inherits the program's confirmed treatment. Commission rewards always use `NONEMPLOYEE_SERVICES`.
imageUrlNo
metadataNo
isVisibleNo
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
couponCodeNo
descriptionNo
isUnlimitedNo
limitDurationNo
referredValueNoTax valuation for the referred friend's side of a double-sided reward. `taxCharacter` is the reason the recipient earns the reward. For configurable non-commission rewards, `null` inherits the program's confirmed treatment. Commission rewards have no referred-friend side, so GrowSurf clears these settings. Use `PURCHASE_REBATE` only when that is the correct tax character.
numberOfWinnersNo
referralCouponCodeNo
commissionStructureNoAffiliate commission structure (AFFILIATE rewards only). Provide a positive `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission. CLICK and LEAD commissions must use FIXED.
conversionsRequiredNo
nextMilestonePrefixNo
nextMilestoneSuffixNo
referralDescriptionNo
referredRewardUpfrontNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate this is a write operation (readOnlyHint=false). The description adds the behavioral constraint that type must match program type for the server to accept it, and explains the campaignId fallback. It does not disclose side effects or edge cases, but for a create operation the key behaviors are covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each with a clear purpose: the action, the most important validation rule, and the campaign targeting behavior. No fluff or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a complex 23-parameter schema, the description is too terse to fully guide an agent. It covers the essential 'what' and 'where' but doesn't explain reward types, required fields beyond 'type', or how this fits into the broader campaign creation flow. The output schema is available, so return values are covered, but an agent would still need to deeply inspect the schema to use this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 22%, and the description compensates only minimally. It adds the type compatibility rule for the 'type' parameter and restates the campaignId default which the schema already documents. The remaining 18+ parameters are left unexplained in both the schema and the description, so the agent has little guidance on what to fill.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Create a new campaign reward (reward config)'. It clearly distinguishes from sibling update/list/delete tools by the word 'Create' and identifies the object being created.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear context on when to use this tool: it mentions the type compatibility rule and the campaignId default behavior. Although it doesn't explicitly say 'use this instead of update_campaign_reward', the verb 'create' and sibling names make the distinction clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_create_campaign_webhookAInspect

Add a webhook to your GrowSurf program. payloadUrl is required. events is the list of events this webhook is subscribed to (omit to subscribe it to no events). secret is write-only — GrowSurf uses it to sign deliveries (the GrowSurf-Signature HMAC header) and never returns it. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
eventsNo
secretNoWrite-only. Signs deliveries; never returned.
isEnabledNo
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
payloadUrlYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses important behaviors beyond the sparse annotations: secret is write-only and never returned, and campaignId defaults to GROWSURF_CAMPAIGN_ID when omitted. This provides useful context for invocation and security. It does not contradict annotations and adds meaningful insight.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (three sentences) and front-loaded with the primary purpose. Each sentence adds value without redundancy, covering the essential parameter behaviors and default behavior in a compact, well-structured manner.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a create-webhook tool, the description covers the required payloadUrl, events subscription semantics, secret signing behavior, and campaign targeting. It omits details about isEnabled and potential error conditions, but given the output schema exists and annotations carry little weight, it is sufficiently complete for an agent to call correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 40%, but the description compensates by explaining payloadUrl is required, events list semantics (omit to subscribe to none), and secret's write-only nature. It also confirms campaignId default. The only parameter not mentioned is isEnabled, which remains bare, but the majority of parameters are clarified.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Add a webhook') and the resource ('to your GrowSurf program'). It distinguishes from siblings by the verb 'add' (create) versus update/delete/list, but does not explicitly name alternatives. The purpose is unambiguous, though not explicitly differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides parameter usage details, such as payloadUrl being required and events semantics, but gives no explicit guidance on when to use this tool versus siblings like growsurf_update_campaign_webhook or growsurf_delete_campaign_webhook. The intended use case is implied by the create nature, but not explicitly stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_create_mobile_participant_tokenAInspect

Create or fetch a participant, then create a participant-scoped mobile SDK token via GrowSurf REST. Participant creation is trusted direct enrollment; do not use it for a public application when the program requires affiliate review. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
emailYes
lastNameNo
metadataNo
firstNameNo
ipAddressNo
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
referredByNo
fingerprintNo
isAffiliateNoSets whether the participant is an affiliate. Use `true` only for trusted direct enrollment. Public applicants should follow the program's configured application flow.
referralStatusNo
mobileInstanceIdNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
isNewNoWhether this request created a new participant.
expiresInNoToken lifetime in seconds.
participantNoThe participant record (same shape as the `growsurf_get_participant` result).
participantTokenNoParticipant-scoped bearer token for GrowSurf mobile SDK participant endpoints.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate readOnlyHint=false and destructiveHint=false, but the description adds context about 'trusted direct enrollment' and the risk of misuse for public apps. However, it does not disclose detailed side effects, permissions, or rate limits, so only partial transparency beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences that front-load the main action, then add a crucial warning and targeting logic. Every sentence earns its place, no fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 11 parameters and an output schema, the description leaves many parameters unexplained (email, lastName, metadata, etc.). It does not mention how token creation interacts with the output or whether any preconditions exist. The warning about affiliate review is useful but the overall context is incomplete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 18%, so the description needs to compensate. It adds meaning for campaignId (default behavior) and isAffiliate (trusted enrollment context), but does not explain the other 9 parameters (email, firstName, etc.). It adds some value but not sufficient for the low coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb and resource: 'Create or fetch a participant, then create a participant-scoped mobile SDK token.' It distinguishes itself from siblings by mentioning the token scope and the GrowSurf REST endpoint, and notes the campaign targeting behavior. No confusion about what it does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a clear warning: do not use for public application when affiliate review is required, which helps decide when to avoid it. It also implies when to use it (trusted direct enrollment). It does not explicitly name alternative tools, but the warning and context are helpful.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_create_program_resourceAInspect

Create a FILE, LINK, or TEXT resource for participants. LINK requires an HTTPS url. TEXT requires plain text. For a FILE up to 10 MB, call growsurf_prepare_program_resource_file first and pass its uploadTicket and uploadResult unchanged. New resources default to draft unless you set isPublished. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoUsed only with `LINK`.
textNoUsed only with `TEXT`.
typeYes
titleYes
categoryNo
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
descriptionNo
isPublishedNo
uploadResultNoThe unmodified result returned by the secure upload flow. Used only with `FILE`.
uploadTicketNoThe one-time upload ticket. Used only with `FILE`.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already signal mutation and non-idempotency, and the description adds non-obvious behavior: draft-by-default unless isPublished is set, campaignId fallback to GROWSURF_CAMPAIGN_ID, and the 10MB FILE upload path. It does not discuss duplicate/retry behavior, but it goes meaningfully beyond what annotations alone convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the operation and resource discriminators, and every clause maps to a real parameter or workflow step. It is compact despite covering a conditional multi-type API.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex conditional create operation, the description integrates the multi-step upload flow, field constraints, defaults, and targeting behavior. Return-value details are handled by the output schema, so an agent has enough to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only 50% schema coverage, the description compensates for the most important conditional parameters: url for LINK, text for TEXT, uploadTicket/uploadResult for FILE, isPublished defaulting, and campaignId fallback. It leaves title/category/description mostly implicit, but the schema names those self-evidently and the critical disambiguation is covered.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific action—creating a participant-facing program resource—and enumerates the exact resource types (FILE, LINK, TEXT). It also names the prerequisite sibling workflow for FILE, which differentiates it from update/delete/prepare tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly tells FILE callers to call growsurf_prepare_program_resource_file first and pass the returned values unchanged, and it states the LINK and TEXT field requirements. It does not explicitly contrast with update/list/delete siblings, but the create-vs-manage distinction is clear enough from the verb and context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_delete_campaign_rewardA
DestructiveIdempotent
Inspect

Delete a campaign reward (reward config) from your GrowSurf program. The reward is deactivated, removed from the program's reward set, and any connected upfront-discount coupons are cleaned up. campaignRewardId is the reward key. Returns { id, success }. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
campaignRewardIdYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoThe deleted campaign reward id.
successNoWhether the campaign reward was deleted.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and idempotentHint=true. The description goes beyond by specifying exactly what gets destroyed (reward config and connected upfront-discount coupons) and the return shape ({ id, success }). This aligns with annotations and adds valuable context about the cleanup behavior. It does not contradict any annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences with zero filler. The core action is front-loaded, and each sentence earns its place: action/effects, parameter clarification, and targeting logic. No redundancy or verbosity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive tool with an output schema, the description covers the return shape, the cleanup side effects, and the default target behavior. It does not mention error conditions or permissions, but annotations provide the destructive hint and the output schema presumably documents the response. Overall, it is complete enough for an agent to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50% (only campaignId has a description). The description compensates: it explicitly identifies '`campaignRewardId` is the reward key' and explains the default behavior of campaignId (targets GROWSURF_CAMPAIGN_ID when omitted). This adds meaning beyond the bare schema for the required parameter and clarifies optional parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('Delete'), the resource ('campaign reward'), and the scope ('from your GrowSurf program'). It also details the side effects (deactivated, removed, coupons cleaned up), which distinguishes it from update or create siblings. An agent can immediately tell what this tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes it clear that this is the delete/removal tool, implying use when a reward should be permanently removed. However, it does not explicitly contrast with update_campaign_reward for partial modifications or state when not to use it. The context is clear but could be stronger with an explicit 'use this for deletion, use update for changes' statement.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_delete_campaign_webhookA
DestructiveIdempotent
Inspect

Remove a webhook from your GrowSurf program by id. Returns { id, success }. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
webhookIdYes
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoId of the webhook that was deleted.
successNoWhether the webhook was deleted.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true, so the destructive nature is already disclosed. The description adds value by specifying the return format ({ id, success }) and the fallback targeting behavior (GROWSURF_CAMPAIGN_ID when campaignId is omitted). It does not contradict any annotations and provides useful behavioral context beyond the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is remarkably concise: two sentences plus a targeting note. It fronts the core action immediately, includes only essential behavioral details, and contains no filler or redundant phrases. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a delete operation with annotations covering destructive behavior, the description provides the return format and the campaign resolution logic, which are critical for correct invocation. It does not mention side effects or prerequisites, but given the simplicity of the operation and presence of an output schema, the description is sufficiently complete. A slight gap is not explaining the exact format of webhookId (e.g., where to obtain it), but this is minor.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema covers campaignId with a detailed description, while webhookId has no schema description. The tool description mentions 'by id' for webhookId but adds no new meaning—webhookId's role is inferred from the name. For campaignId, the description restates what the schema already says ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID') without adding further detail. With 50% schema coverage, the description only partially compensates for the undocumented webhookId.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Remove'), the resource ('a webhook'), and the scope ('from your GrowSurf program'), which distinguishes it from sibling tools like create, update, list, and test webhooks. The inclusion of the return format { id, success } adds clarity without confusion.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the use case (deleting a webhook) but does not explicitly provide when-to-use guidance or mention alternatives. It does not state when not to use this tool or contrast it with other webhook operations. The targeting logic for campaignId is a parameter detail, not usage guidance. Overall, usage context is clear from the name but not explicitly articulated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_delete_program_resourceA
DestructiveIdempotent
Inspect

Delete a participant resource from your GrowSurf program. This does not remove its reusable Media Center asset. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
resourceIdYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoThe deleted resource id.
successNoWhether the resource was deleted.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark destructiveHint=true and idempotentHint=true, and the description adds the important nuance that the Media Center asset survives deletion. It also discloses the campaignId targeting behavior, going beyond the minimal mutation signal.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences front-load the action, then clarify the asset side effect and campaign targeting. Every sentence adds information; no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 2-parameter destructive tool with an output schema and annotations, the description covers the key call-time decisions: what is deleted, what is not deleted, and which campaignId is used. It doesn't discuss reversibility, but destructiveHint and the delete verb already convey that risk.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

resourceId is not described in the schema and the description only identifies it by the noun 'participant resource.' The campaignId fallback behavior is repeated from the schema, so the description adds modest but not comprehensive parameter meaning for 50% schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action and object: 'Delete a participant resource from your GrowSurf program.' It also distinguishes the tool's effect from deleting a 'reusable Media Center asset,' and the target object differs from siblings like update_program_resource or delete_campaign_webhook.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear context by noting that the reusable Media Center asset is not removed, which helps an agent avoid using this tool when asset deletion is intended. The campaignId fallback/override behavior also explains when to pass the optional parameter, though no alternative tool is named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_email_participantA
Destructive
Inspect

Send an email to a participant (by GrowSurf participant ID or email). Provide EITHER emailType to trigger one of the program's configured email templates, OR subject + body for a free-form email (optionally preheader). Free-form emails are sent with the same compliance handling (company name, postal address, and an unsubscribe link are added automatically, and unsubscribed participants are suppressed). Sending requires the team to be verified by GrowSurf and a verified custom email domain on the program (set up in Campaign Editor > 3. Emails > Email Settings). Returns 400 until one is verified. The email is accepted for delivery. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
bodyNoFree-form HTML body. You can personalize it with dynamic text, inserting `{{...}}` tokens like `{{firstName}}` or `{{shareUrl}}`. See [Guide to using dynamic text in GrowSurf emails](https://support.growsurf.com/article/213-guide-to-using-dynamic-text-in-growsurf-emails).
subjectNoFree-form subject. Supports dynamic text (`{{...}}` tokens), the same as the body.
emailTypeNoThe program email template to trigger. Send the camelCase key; the available types depend on the program type. The template's `isEnabled` setting controls automatic sends only, so this tool can trigger any sendable template. System and transactional types (login link, payout destination confirmation, tax) and the invite email cannot be sent. Referral programs: `welcomeNonReferred`, `referralLinkViewedFirstTime`, `referralLinkUsed`, `referredSignup`, `welcomeReferred`, `goalAchieved`, `campaignEndedWinners`, `campaignEndedNonWinners`, `progressUpdateMonthly`. Affiliate programs: `welcomeNonReferred`, `referralLinkViewedFirstTime`, `referredSignup`, `commissionGenerated`, `commissionAdjusted`, `payoutPending`, `payoutSentSuccess`, `progressUpdateMonthly`.
preheaderNo
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
participantIdNo
participantEmailNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusNoThe email was accepted for delivery.
successNoWhether the email request was accepted.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses critical behaviors: automatic compliance handling (company name, postal address, unsubscribe link), suppression of unsubscribed participants, and the 400 error until verification is complete. While annotations indicate destructiveHint=true and readOnlyHint=false, the description adds concrete details about side effects and preconditions, going beyond the structured annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately long given the tool's complexity, with the core purpose and options front-loaded, followed by prerequisites and behavior. It is well-structured and each sentence contributes essential information, though it is denser than a minimal description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description fully covers selection between template and free-form, identification methods, targeting, prerequisites, and failure behavior. An output schema exists, so return details are not required. It is complete for an agent to call this tool correctly without additional guidance.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema coverage at 57%, the description compensates by explaining the either/or relationship between emailType and subject/body, the default behavior for campaignId, and the meaning of participant identification via ID or email. It adds operational meaning beyond the schema's basic property descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Send an email to a participant'), identifies the resource (participant by ID or email), and differentiates between template and free-form email modes. It is unambiguous and does not merely restate the tool name, and it clearly distinguishes the tool's function from other GrowSurf tools by focusing on email delivery.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit conditions for use: either emailType (template) or subject+body (free-form), and outlines prerequisites (team verified, custom email domain verified) and default targeting via campaignId. It does not explicitly name alternative tools, but the tool's specific function (sending participant emails) makes usage context clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_embeddable_element_snippetB
Read-onlyIdempotent
Inspect

Generate the HTML snippet for a GrowSurf embeddable element (with optional auth attributes).

ParametersJSON Schema
NameRequiredDescriptionDefault
elementYes
participantNo
withAuthAttributesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds no behavioral detail beyond 'generate', offering no information on side effects, rate limits, authentication needs, or what the snippet actually produces. It essentially restates the name with a minor addition.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, clear sentence with no extraneous words. The core purpose is stated upfront, and the optional modifier is concise. It is an efficient, well-structured definition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 3 parameters (one required) with a nested object and an output schema exists, the description is minimal. It conveys the basic intent but does not explain the role of all parameters or when to use it. Since the output schema is present, return details are covered elsewhere, but the description lacks depth for a tool with this complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It touches on 'auth attributes' which maps to withAuthAttributes, but it does not explain the 'participant' object or how it relates to the element. The explanation is incomplete, leaving the agent to guess the purpose of participant fields like email and names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Generate') and a precise resource ('HTML snippet for a GrowSurf embeddable element'), plus a clarifying modifier about optional auth attributes. This clearly distinguishes it from sibling snippet tools like growsurf_client_snippets or growsurf_grsf_config_snippet, which target different aspects of embedding.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives such as growsurf_client_snippets or growsurf_api_library_snippets, nor any conditions or prerequisites. The description does not explain the context in which this snippet generator is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_get_campaignA
Read-onlyIdempotent
Inspect

Fetch your GrowSurf campaign (program) details via REST. Embedded reward settings do not establish that an individual reward was earned, approved, or delivered; read the affected participant for earned reward records. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoThe program's unique id.
nameNoThe program name (internal only, never shown to participants).
typeNoThe program type.
statusNoThe program status.
rewardsNoThe program's reward configs (`CampaignReward`). Item shape is documented on the `growsurf_list_campaign_rewards` tool.
currencyISONoThe program currency as an ISO 4217 code (e.g. `USD`).
inviteCountNoTotal invites sent by participants.
winnerCountNoParticipants with at least one approved reward.
referralCountNoTotal referrals.
rewardEvidenceNoWhat this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.
impressionCountNoTotal referral-link views across participants.
participantCountNoTotal participants.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish read-only, idempotent, non-destructive behavior. The description adds a non-obvious semantic caveat about reward settings and clarifies target selection behavior, both of which help the agent interpret the response correctly without contradicting the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with its purpose, followed by a valuable caveat and a parameter-targeting note. It contains minimal filler, though the REST qualifier and default mention overlap with schema details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter, read-only tool with full schema coverage and an output schema, the description covers the important traps: target selection and misinterpretation of reward settings. No critical information for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the campaignId schema entry already explains the default and how to use an id from growsurf_create_campaign. The description re-states the default behavior but does not add meaningful parameter semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the action ('Fetch') and resource ('campaign (program) details'), making the core purpose easy to grasp. It distinguishes from create/update/delete/list siblings, though it does not explicitly differentiate itself from the more specialized get_campaign_* sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives useful context: it is the campaign-level fetch and falls back to GROWSURF_CAMPAIGN_ID when campaignId is omitted. It also steers agents away from treating embedded reward settings as proof of earned rewards and points them to the participant record for that data.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_get_campaign_activation_analyticsA
Read-onlyIdempotent
Inspect

Fetch strict activation for eligible participants in one enrollment cohort. Referral programs group by enrolledAsAdvocateAt; affiliate programs group by approvedAsAffiliateAt. The ordered stages are ELIGIBLE, PORTAL_VIEWED, SHARE_ACTION, UNIQUE_REFERRAL_VISIT, LEAD, and CREDITED_REFERRAL. Each participant gets the selected 7- or 30-day observation window. Omit both cohort bounds for the latest fully matured cohort. Read coverageStartAt, state, and reason before interpreting a null or zero; unavailable history does not mean an action never happened. Targets campaignId if passed, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
cohortToNoExclusive eligibility-cohort end, Unix timestamp in ms. Must be greater than `cohortFrom`.
timezoneNoIANA timezone used to advance cohort boundaries. Defaults to `UTC`.
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
cohortFromNoInclusive eligibility-cohort start, Unix timestamp in ms. Use with `cohortTo`.
cohortIntervalNoBucket size for `cohorts`. Defaults to `day`.
observationWindowDaysNoDays after eligibility in which stages can count. Defaults to `30`.

Output Schema

ParametersJSON Schema
NameRequiredDescription
cohortsNoSelected range split into exact half-open eligibility-cohort buckets.
timezoneNoIANA timezone used to advance cohort boundaries.
aggregateNoStrict activation metrics for one exact enrollment cohort.
programTypeNoProgram eligibility model.
cohortIntervalNoBucket size for `cohorts`.
coverageStartAtNoEarliest expected complete activation capture time (Unix ms), or `null` until coverage begins.
portalViewedLabelNoProgram-specific display label for the stable `PORTAL_VIEWED` stage.
metricContractVersionNoShared activation and engagement metric version.
observationWindowDaysNoDays after eligibility in which stages count.
portalViewedHelperTextNoDisplay definition for a qualifying signed-in portal view.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral nuance: the observation window (7- or 30-day), the grouping keys by program type, and crucially the warning that 'unavailable history does not mean an action never happened'—directing the agent to read coverageStartAt/state/reason before interpreting nulls. This goes beyond annotations and is essential for correct interpretation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but well-organized. It front-loads the primary purpose, then moves through grouping, stages, observation window, cohort bounds, and interpretation guidance. Every sentence contributes functional information; there is no fluff. While it is longer than average, the complexity of the tool justifies the length, and the logical flow makes it scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 6 parameters, 2 enums, and an output schema, the description is exceptionally complete. It covers the exact stages, the cohort selection logic, the observation window options, the default target, and vital data-interpretation warnings. Since an output schema exists, return-value details are not required in the description. Nothing necessary for an agent to invoke this tool correctly and interpret results is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage, each parameter is already documented. The description adds meaningful semantics beyond the schema: it ties cohortFrom/cohortTo together via the conditional requirement, explains that omitting them yields the latest matured cohort, and clarifies the default behavior of campaignId (targets GROWSURF_CAMPAIGN_ID when omitted). This helps the agent reason about parameter combinations and defaults, exceeding the baseline for high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Fetch strict activation for eligible participants in one enrollment cohort.' It distinguishes this from general campaign analytics by specifying 'strict activation' and the enrollment cohort scope, and it immediately clarifies the two grouping modes (referral vs. affiliate). This makes the tool's unique purpose unambiguous and separates it from sibling analytics tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool: it is specifically for activation analytics in a single enrollment cohort, with explicit instructions on cohort bounding ('Omit both cohort bounds for the latest fully matured cohort') and interpretation ('Read coverageStartAt, state, and reason...'). While it doesn't explicitly name alternative tools to avoid, the detailed policy on cohort handling and the warning about missing history effectively guide correct usage without needing exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_get_campaign_analyticsA
Read-onlyIdempotent
Inspect

Fetch analytics for your GrowSurf program: participants, referrals, impressions, per-channel shares, and affiliate revenue, commission, and payout metrics when applicable. For what impressions, unique impressions, leads, and referrals mean, or why counts differ from another analytics tool, call growsurf_troubleshoot_referral_tracking with symptom numbers_do_not_match rather than guessing. Pass interval (day, week, or month) for a per-period series. Pass comma-separated include values for previousPeriod, statusCounts, rates, email, or engagement. engagement groups unique active, sharing, repeat, and retained participants by when portal views and share actions occurred. Its coverageStartAt, state, and reason distinguish measured zeroes from partial or unavailable history. Scope the timeframe with days (default 365, max 1825) or an explicit startDate/endDate window (Unix ms). timezone and platform apply to engagement only. Targets campaignId if passed, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNo
endDateNoEnd of the timeframe, Unix timestamp in ms.
includeNoComma-separated optional data: `previousPeriod`, `statusCounts`, `rates`, `email`, and `engagement`. Combine values when the question needs more than one view.
intervalNoday/week/month adds a per-period `series`; total (default) returns totals only.
platformNoClient-platform filter for engagement. Defaults to `ALL`.
timezoneNoIANA timezone for engagement interval and distinct-day calculations. Used with `include=engagement`.
startDateNoStart of the timeframe, Unix timestamp in ms. Use with endDate instead of days.
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
emailNoSent, delivered, opened, clicked, bounced, and spam complaint metrics for program emails in the requested window.
ratesNoDerived referral rates, each a ratio from 0 to 1. Present only when `include` contains `rates`.
seriesNoPer-period totals in ascending order. Present only when `interval` is `day`, `week`, or `month`.
endDateNoEnd of the analytics timeframe, as a Unix timestamp in milliseconds.
analyticsNoAnalytics totals: `invites`, `impressions`, `uniqueImpressions`, `participants`, `referrals`, `referralCreditPendings`, `referralCreditExpireds`, per-channel share counts (`emailShares`, `twitterShares`, `copyRefLinkShares`, ...), and for affiliate programs `totalRevenue` and `totalCommissions` (in minor currency units (e.g. cents)) plus `totalCommissionCount` and `uniqueCommissionReferrals`.
startDateNoStart of the analytics timeframe, as a Unix timestamp in milliseconds.
engagementNoOpt-in participant engagement grouped by when activity occurred.
statusCountsNoStatus-count breakdowns: dashboard-aligned reward counts, and for affiliate programs `affiliateStatus`, `commissionStatus`, and `payoutStatus` (counts and amounts in minor currency units (e.g. cents)). Present only when `include` contains `statusCounts`.
previousPeriodNoTotals for the equal-length window immediately before the requested one (`analytics`, `startDate`, `endDate`). Present only when `include` contains `previousPeriod`.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish read-only, idempotent, non-destructive behavior. The description adds substantial behavioral context beyond that: the default timeframe of 365 days and max of 1825, the campaignId fallback to GROWSURF_CAMPAIGN_ID, that timezone/platform apply only to engagement, and that engagement's coverageStartAt/state/reason distinguish measured zeroes from partial or unavailable history. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence earns its place: purpose first, then the troubleshooting pointer, then parameter and scoping guidance. The description is dense but not padded, with no redundant restatement of the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 8 parameters, 2 enums, and an output schema, the description covers defaults, exclusions, engagement semantics, timeframe scoping, and the target fallback. With an output schema present, omitting return-value details is fine. There is no missing guidance an agent needs to call this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 88%, but the description adds meaning the schema lacks: interval day/week/month yields a per-period 'series', include is comma-separated and names the exact options, engagement is defined as grouping unique active/sharing/repeat/retained participants by portal views and share actions, and engagement's coverage fields carry semantics. It also clarifies days vs startDate/endDate usage and timezone/platform scope.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence names a specific verb and resource ('Fetch analytics for your GrowSurf program') and enumerates the concrete metrics: participants, referrals, impressions, per-channel shares, and affiliate revenue/commission/payout. This is enough to distinguish it from other analytics siblings like growsurf_get_campaign_activation_analytics and growsurf_get_participant_analytics, even without comparing schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent to a sibling for metric definitions or count reconciliation: 'call growsurf_troubleshoot_referral_tracking with symptom numbers_do_not_match rather than guessing.' It also gives concrete usage conditions for interval, include, engagement, and timeframe parameters, so an agent knows exactly how to shape the request.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_get_campaign_designA
Read-onlyIdempotent
Inspect

Fetch the configured design fields for your GrowSurf program, including GrowSurf Window content, colors, sharing sections, participant avatars under participantAvatarStyle, referred-visitor content such as the Claim Offer Popup, participant sign-in copy under login, payout-destination confirmation page copy under payoutDestinationConfirmation, and country-name overrides under countryLabels. participantAvatarStyle is CHARACTERS, INITIALS, ANIMALS, or GRADIENT; missing or unknown values mean INITIALS. The confirmation section is omitted when no confirmation fields are stored. Stored null fields are returned as null; omitted and null fields use localized defaults. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
loginNoThe returning-participant sign-in form plus its success, resend, validation, and error text.
shareNoShare channels, invite settings, and share-button styling.
statsNoThe participant's referral-progress stats panel. Only `title` is editable.
themeNoVisual theme styling (colors, shadows, and similar).
headerNoHeader content for participants (`postText`) and non-participants (`preText`).
signupNoSignup form fields, GDPR consent, and button and login text.
windowNoLayout of the GrowSurf window (`navigationMode`: `TABS` or `LIST`).
payoutsNoAffiliate programs only. The Payouts section of the participant portal.
rewardsNoHeading, icon, and empty-state text of the rewards panel.
resourcesNoParticipant Resources presentation settings: visibility, title, link and copy labels, the message shown when nothing is published, and the section icon. Resource items use the program Resource tools.
commissionsNoAffiliate programs only. The Commissions section of the participant portal.
leaderboardNoThe leaderboard section: labels, selectors, and name masking.
landingPagesNoPortal and landing pages: company info, `content`, `styles`, third-party script ids, and SEO meta tags.
countryLabelsNoParticipant-facing country-name overrides keyed by ISO 3166-1 alpha-2 code (for example `GB`). Each label replaces the default country name wherever participants pick a country, such as payout and tax forms. Overrides merge per code on `PATCH`; `null` (or the default name) restores a code's default. Only overridden codes are returned.
referralStatusNoThe section listing who a participant invited and each invite's progress.
referralSummaryNoReferral programs only. The participant's row of summary tiles (clicks, leads, referrals, rewards).
affiliateSummaryNoAffiliate programs only. The affiliate's row of summary tiles (clicks, revenue, payouts).
referredExperienceNoThe banner, headline, and Claim Offer Popup shown to a visitor who arrives through a referral link. The popup is available for referral and affiliate programs.
participantSettingsNoThe participant's account settings area (logout, PayPal and Wise payout confirmation/status messages, tax details).
participantAvatarStyleNoHow participant avatars appear in the GrowSurf Window. New programs use `CHARACTERS`; missing or unknown stored values return `INITIALS`.
payoutDestinationConfirmationNoCustomizable text for the payout-destination confirmation page opened from payout integration cards. One shared set applies to every enabled payout provider. Provider-aware text may use `{{payoutProvider}}`; omitted and `null` fields use localized defaults.

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so the read-only nature is covered. The description goes beyond this by detailing default behavior for participantAvatarStyle (unknown values default to INITIALS), handling of null and omitted fields (null returned as null, omitted and null use localized defaults), omission of confirmation section when no fields stored, and the fallback to GROWSURF_CAMPAIGN_ID. These behavioral specifics add significant value beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence earns its place. It front-loads the purpose, then lists fields, then explains default and edge-case behaviors. There is no redundancy, filler, or repetition; it packs substantial information into a well-organized paragraph without wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema exists, return values are fully documented elsewhere. The description covers all non-obvious behaviors: field list, enum values, defaults, null handling, and campaign targeting. It also clarifies the confirmation section omission. An agent has everything needed to call this tool correctly without consulting additional documentation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage for the single parameter campaignId is 100%, with the schema description already explaining its default and purpose. The tool description repeats the targeting behavior but adds no new semantic detail. Per the rubric, when schema coverage is high, the baseline is 3, and the description adds little beyond that baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Fetch' and the resource 'configured design fields for your GrowSurf program', then enumerates the specific fields returned. This unambiguously distinguishes it from the sibling growsurf_update_campaign_design, so an agent can tell them apart without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes the read intent clear but does not explicitly state when to use this tool versus alternatives like growsurf_update_campaign_design. There is no mention of exclusions or conditions for selection; the usage is implied by the 'Fetch' verb rather than stated as guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_get_campaign_emailsA
Read-onlyIdempotent
Inspect

Fetch the Emails tab configuration for your GrowSurf program (participant and admin email templates and settings). Returns the full object with every field and its current value — the same shape you send back on update. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
inviteNoThe invitation email a participant sends to friends. `useCompanyReplyTo` sets who receives replies.
settingsNoSender (`sender`), physical contact address (`contact`), and shared design (`design`) settings. The design object includes `unsubscribeAffiliateInvite` for direct affiliate invitation emails.
loginLinkNoOne-time sign-in link for returning participants. Transactional; its toggle cannot be changed.
goalAchievedNoSent when a participant unlocks a reward. Referral programs only.
offerClaimedNoSent when a referred visitor saves an offer through the Claim Offer Popup. Referral and affiliate programs. Promotional; its toggle can be changed.
payoutPendingNoSent when a payout is on the way. Affiliate programs only.
referredSignupNoSent to a referrer each time someone signs up using their link. Referral and affiliate programs.
taxInfoMissingNoAsks a participant to submit required tax information. Transactional; its toggle cannot be changed.
inviteAffiliateNoInvites a prospective affiliate to join the program. Its body must keep `{{affiliateInviteLink}}`. Affiliate programs only. Promotional; its toggle can be changed.
taxInfoApprovedNoTells a participant their tax form is complete and approved. Transactional; its toggle cannot be changed.
taxInfoReceivedNoConfirms submitted tax information was received. Transactional; its toggle cannot be changed.
taxInfoRejectedNoTells a participant their tax information needs to be resubmitted. Transactional; its toggle cannot be changed.
welcomeReferredNoWelcome email for someone who signs up through a referral link. Referral programs only.
referralLinkUsedNoSent to a referrer when they earn referral credit. Referral programs only.
payoutSentSuccessNoSent when a payout completes. Affiliate programs only.
commissionAdjustedNoSent when a commission is adjusted after a refund or chargeback. Affiliate programs only.
welcomeNonReferredNoWelcome email for a participant who joins without being referred. Referral and affiliate programs.
commissionGeneratedNoSent to an affiliate when they earn a new commission. Affiliate programs only.
campaignEndedWinnersNoSent to reward winners when the program ends. Referral programs only.
progressUpdateMonthlyNoMonth-end progress recap for participants. Referral and affiliate programs.
campaignEndedNonWinnersNoSent to non-winners when the program ends. Referral programs only.
payoutDestinationChangedNoTells a participant their payout destination changed. Its body must keep `{{payoutDestinationMaskedEmail}}`. Referral and affiliate programs. Transactional; its toggle cannot be changed.
affiliateApplicationDeniedNoTells an applicant their affiliate application was not approved. Affiliate programs only. Transactional; its toggle cannot be changed.
referralLinkViewedFirstTimeNoSent the first time a participant's referral link is viewed. Referral and affiliate programs.
affiliateApplicationApprovedNoTells an applicant their affiliate application was approved. Affiliate programs only. Transactional; its toggle cannot be changed.
affiliateApplicationReceivedNoConfirms an affiliate application was received and is under review. Affiliate programs only. Transactional; its toggle cannot be changed.
payoutDestinationConfirmationNoAsks a participant to confirm the payout destination where they will receive payouts, such as a PayPal or Wise email address. Its body may use `{{payoutProvider}}` and must keep `{{payoutDestinationConfirmationLink}}`. Referral and affiliate programs. Transactional; its toggle cannot be changed.
affiliateApplicationStatusLinkNoSends an applicant a secure link to view their application status. Its body must keep `{{applicationStatusLink}}`. Affiliate programs only. Transactional; its toggle cannot be changed.
affiliateEmailChangeVerificationNoAsks an affiliate to confirm a new account email address. Its body must contain `{{identityVerificationLink}}`. Affiliate programs only. Transactional; its toggle cannot be changed.
affiliateApplicationEmailCorrectionNoAsks an applicant to confirm a corrected email address. Its body must contain `{{identityVerificationLink}}`. Affiliate programs only. Transactional; its toggle cannot be changed.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior, so the safety profile is covered. The description adds useful behavioral detail beyond annotations: it returns the full object with all fields and current values, and it falls back to GROWSURF_CAMPAIGN_ID when campaignId is omitted.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler; the primary purpose is front-loaded, the return shape is clarified, and the default campaign behavior is stated compactly. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read tool with one optional parameter, full schema coverage, strong annotations, and an output schema, the description covers everything needed to invoke it correctly. It explains the object shape, update relationship, and default campaign resolution, so no critical context is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the campaignId property is already well documented in the schema, including its default and provenance from growsurf_create_campaign. The tool description repeats the default behavior but adds little beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Fetch') and resource ('Emails tab configuration'), including what that resource contains (participant and admin email templates and settings). It clearly distinguishes this read operation from the sibling update_campaign_emails tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes clear this is a fetch operation and that the returned shape is what you send back on update, implicitly connecting it to growsurf_update_campaign_emails. It also explains campaign targeting behavior with the default GROWSURF_CAMPAIGN_ID, giving an agent actionable context, though it doesn't explicitly state when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_get_campaign_installationA
Read-onlyIdempotent
Inspect

Fetch the Installation tab configuration for your GrowSurf program (embed/installation and tracking setup). Returns the full object with every field and its current value — the same shape you send back on update. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
mobileNoGrowSurf iOS and Android SDK settings.
signupNoCustom signup-form settings (used with `FORM_DETECTION`).
shareUrlNoThe landing page referred friends reach from a referral link. Set this before adding other origins to `allowedUrls`.
allowedUrlsNoEvery additional browser origin where the GrowSurf Window or SDK may run, including development origins such as `http://localhost:3000`. Preserve the full array when patching it. An origin absent from both `shareUrl` and this list can return `403`.
signupEventNoThe signup tracking method: automatic form detection, or participants added via the SDKs and REST API.
referralTriggerNoReferral programs only. `ON_SIGNUP` counts a referral as soon as the friend signs up; `CUSTOM` also requires a qualifying action.
useGrowSurfHostedLinksNoUse GrowSurf-hosted referral links that route clicks by the visitor's device. Mainly for mobile apps.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the tool's safety profile is well covered. The description adds the behavioral fact that it returns the full object with every field, which is useful for understanding the response but not a new risk or constraint. It adds minor context beyond annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise at three sentences with no redundancy. The purpose is front-loaded, the return shape is clearly stated, and the parameter default is mentioned efficiently. Every sentence contributes essential information, and there is no fluff or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only getter with one optional parameter and an existing output schema, the description is complete. It states what the tool fetches, the default behavior, and the return shape. While it could mention that the Installation tab is a sub-configuration of a campaign or that this is typically used before updating, those are minor and covered by the output schema and sibling context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides 100% coverage for the single parameter campaignId, including its default behavior and a recommendation to pass the id from growsurf_create_campaign. The description repeats this in its last sentence without adding new meaning. Since schema coverage is high, the baseline of 3 applies; the description does not enhance parameter understanding beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the tool's purpose: it fetches the Installation tab configuration for a GrowSurf program. The verb 'Fetch' and the specific resource 'Installation tab configuration' make it unambiguous. It also distinguishes it from sibling getters like get_campaign_design or get_campaign_options by naming the exact tab and mentioning the return shape (full object same as update).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description mentions the default campaignId behavior and that the returned object is the same shape sent on update, which subtly implies a read-before-update workflow. However, it does not explicitly state when to use this tool versus alternatives like update_campaign_installation or other getters. No exclusions or alternative tools are named, leaving usage context implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_get_campaign_optionsA
Read-onlyIdempotent
Inspect

Fetch the Options tab configuration for your GrowSurf program (referral triggers, anti-fraud lists and toggles, affiliate enrollment and application review, notifications, and other behavior options). Returns the full object with every field and its current value, the same shape you send back on update. autoFulfillRewards: false permits manual fulfillment and does not prove that any reward went undelivered. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
fraudNoAnti-fraud settings: `blockedEmails`/`blockedIps`/`blockedCountries` and matching allow lists, `blockBurnerEmails`, `blockDataCenterIps`, `blockHighRiskReferrers`, `autoBlockHighRiskIps`, per-IP signup rate limits, and `recaptcha`.
autoBlockFraudNoAutomatically block signups flagged as high fraud risk.
rewardEvidenceNoWhat this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.
payoutThresholdNoAffiliate programs only. Minimum payout in minor currency units (e.g. cents). `0` or `null` means no minimum.
taxDocumentationNoAffiliate programs only. Company billing details (name, address, VAT number) used on affiliate payout invoices and for VAT handling.
autoFulfillRewardsNoReferral programs only. Automatically mark earned rewards as fulfilled. `false` permits manual fulfillment and does not establish a delivery failure.
notificationEmailsNoOwner notification settings: `recipients` plus per-event `events` toggles.
blockPaidAdsTrafficNoDo not attribute referrals from visitors who arrived through paid ads.
enforceGdprComplianceNoStore only the minimum participant data (no IP addresses, fingerprints, or mobile instance ids).
requireParticipantAuthNoRequire returning participants to authenticate. Affiliate programs require `true`.
affiliateApplicationModeNoAffiliate programs only. How public signups join the program. `OPEN_ENROLLMENT` enrolls them directly; `MANUAL_REVIEW` collects an application you approve or deny; `AUTO_APPROVE` collects the application and approves it immediately. A reviewed mode requires the program's published application page. Enrollment through the API, CSV import, dashboard, or invites is never blocked by this setting.
referralCookieWindowDaysNoHow long a referral-link click is remembered in the visitor's browser, in days.
referralCreditWindowDaysNoHow long a referred friend has to complete the qualifying action, in days. `null` means the credit never expires.
requireManualFraudApprovalNoFlag suspected fraud for review instead of blocking signups automatically.
requireManualRewardApprovalNoReferral programs only. Hold each earned reward for manual approval before it unlocks.
affiliateReapplicationPolicyNoAffiliate programs only. Whether a denied applicant may apply again. `AFTER_COOLDOWN` (the default) allows a new application once `affiliateReapplicationCooldownDays` has passed; `DISABLED` never allows one.
affiliateReapplicationCooldownDaysNoAffiliate programs only. How many days a denied applicant waits before they can apply again (1-365, default 30). Only used when `affiliateReapplicationPolicy` is `AFTER_COOLDOWN`.
affiliateApplicationReviewEstimateBusinessDaysNoAffiliate programs only. Optional review-time expectation shown to pending applicants, in business days (1-60). `null` clears it.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations readOnlyHint=true, idempotentHint=true, destructiveHint=false already tell the agent this is a safe read operation. The description adds behavioral nuance by noting the `autoFulfillRewards: false` does NOT prove rewards went undelivered (a corrective against misinterpretation), and clarifies that passing `campaignId` is optional with a default. This goes beyond the annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description packs essential details into a few sentences: what is fetched, the return shape, the autoFulfillRewards caveat, and the targeting default. It is front-loaded with the purpose, and every sentence adds value. No fluff or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the low complexity (1 optional param), high schema coverage, and presence of an output schema, the description is quite complete. It mentions return shape ('same shape you send back on update') and cautions against misinterpreting a field. Missing only explicit indication of which specific fields exist, but the output schema covers that. Strong for the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% (the description for campaignId explains the default and how to get the id from create_campaign). The description itself does not add much beyond the schema, but it reinforces the default behavior architecturally which is already in the schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Fetch the Options tab configuration' and lists what is included (referral triggers, anti-fraud lists, notifications, etc.), which is specific and distinguishes it from related tools like update_campaign_options. However, it doesn't explicitly contrast with siblings that might also fetch campaign configuration (e.g., get_campaign_design, get_campaign_emails), though the listing of scope is enough to infer differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides context on when to use it (fetch options) and explains the `campaignId` targeting behavior including the default to GROWSURF_CAMPAIGN_IDepth. It does not explicitly exclude alternatives or say when NOT to use it, but it is clear enough for an agent to know it's the right call for reading options. The caveat about autoFulfillRewards is more of a semantic clarification than usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_get_participantA
Read-onlyIdempotent
Inspect

Fetch a single participant by GrowSurf participant ID or email address. referralStatus describes credit to their referrer; referralCount counts referrals this participant generated, so zero is consistent with CREDIT_AWARDED. In rewards, approved records approval; status, isFulfilled, and fulfilledAt record fulfillment marking, not confirmation of delivery. Use growsurf_list_participants first if you need to find a participant ID. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
participantIdNo
participantEmailNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoThe participant's unique id.
rankNoAll-time leaderboard rank.
emailNoThe participant's email address.
isNewNo`true` when the request created the participant. Returned by participant creation calls.
notesNoInternal notes. Never shown to participants.
rewardsNoRewards the participant has earned.
isWinnerNo`true` once the participant has earned at least one reward.
lastNameNoThe participant's last name.
metadataNoCustom key/value metadata (single level).
referrerNoSummary of the participant's referrer (same core fields as a participant). Present only when the participant was referred.
shareUrlNoThe participant's unique referral link. Omitted for affiliate program participants who are not approved affiliates.
createdAtNoWhen the participant joined, as a Unix timestamp in milliseconds.
firstNameNoThe participant's first name.
ipAddressNoIP address recorded for the participant, or `null`.
referralsNoIds of participants they successfully referred (100 most recent).
referredByNoId of the referrer. Present only when the participant was referred.
shareCountNoShare counts keyed by channel (e.g. `email`, `facebook`, `twitter`, `copyRefLink`, `iosNativeShare`).
vanityKeysNoThe participant's vanity keys.
fingerprintNoBrowser identifier recorded for the participant, or `null`.
inviteCountNoInvites sent by the participant.
isAffiliateNoAffiliate programs only. Whether this participant is an enrolled affiliate. A referred customer who has not joined the program is `false`.
monthlyRankNoCurrent-month leaderboard rank (resets monthly).
unsubscribedNo`true` if the participant unsubscribed from program emails.
referralCountNoAll-time referrals credited to the participant.
fraudRiskLevelNoThe participant's fraud risk level.
payoutSettingsNoActions the participant must complete before a payout can be released. Always present.
referralSourceNoHow the participant joined the program.
referralStatusNoThe referrer's credit status for this participant. Present only when the participant was referred.
rewardEvidenceNoWhat this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.
affiliateStatusNoAffiliate programs only. The enrolled affiliate's status (`APPROVED`, `SUSPENDED`, or `BANNED`). `null` for participants who are not affiliates.
fraudReasonCodeNoReason code behind `fraudRiskLevel` (e.g. `UNIQUE_IDENTITY`, `DUPLICATE_EMAIL`, `MANUAL_UPDATE`).
impressionCountNoTotal views of the participant's referral link.
prevMonthlyRankNoPrevious-month leaderboard rank.
mobileInstanceIdNoApp-install scoped identifier supplied by a native app, or `null`.
monthlyReferralsNoIds of participants they successfully referred this month (100 most recent).
paypalEmailAddressNoPayPal email address on file, used for affiliate or PayPal reward payouts.
unreadPayoutsCountNoPayouts the participant has not yet viewed. Affiliate programs only.
monthlyReferralCountNoReferrals credited this month (resets monthly).
allMatchingFraudstersNoOther participants flagged as matching this participant during anti-fraud checks.
uniqueImpressionCountNoUnique views of the participant's referral link.
unreadCommissionsCountNoCommissions the participant has not yet viewed. Affiliate programs only.
prevMonthlyReferralCountNoReferrals credited the previous month.
affiliateEnrollmentSourceNoAffiliate programs only. How the affiliate enrolled (`OPEN_ENROLLMENT`, `APPLICATION`, `PARTICIPANT_AUTH`, `INVITE`, `REST_API`, `CSV`, or `DASHBOARD`). `null` when not recorded.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this as read-only, idempotent, and non-destructive, and the description adds valuable interpretive context beyond that: referralStatus vs referralCount semantics, why zero referrals can align with CREDIT_AWARDED, and the distinction between fulfillment marking and actual delivery confirmation. This prevents misinterpretation of returned fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core action is front-loaded, and the subsequent sentences each add necessary disambiguation about field meanings and campaign targeting. There is little to no filler, and the density is justified by the need to prevent interpretation errors.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that the annotations cover safety and the output schema describes return structure, the description supplies the missing decision info: how to find a participant ID, what the fields mean semantically, and how campaign targeting behaves. An agent has enough clarity to invoke this tool correctly without further investigation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 33% since participantId and participantEmail lack descriptions, but the description compensates by explaining that either a GrowSurf participant ID or an email address is used to fetch the participant. It also gives campaignId practical meaning by noting the default GROWSURF_CAMPAIGN_ID behavior. Full field-level detail is still somewhat light, but the essential semantics are present.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening phrase 'Fetch a single participant by GrowSurf participant ID or email address' states a specific verb, resource, and lookup method. It clearly distinguishes this tool from growsurf_list_participants by emphasizing 'single participant' and even names the sibling explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'Use growsurf_list_participants first if you need to find a participant ID,' giving concrete guidance on when to use an alternative tool. It also explains the campaignId targeting behavior and fallback to GROWSURF_CAMPAIGN_ID, so an agent knows exactly how to route the call.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_get_participant_activity_logsA
Read-onlyIdempotent
Inspect

List a participant's activity logs (by GrowSurf participant ID or email), most recent first, offset/limit paginated. limit is 1-100 (default 20); offset skips logs. The response offset is the cursor for the next page (null when there are no more). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
offsetNo
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
participantIdNo
participantEmailNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
limitNoNumber of activity logs returned per page.
offsetNoOffset for the next page, or `null` when there are no more logs.
activityLogsNoActivity log entries for the participant.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so no contradiction. The description adds behavioral details: results are most recent first, offset acts as a cursor, and campaignId defaults to an environment variable. This enriches the agent's understanding of the operation's behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the main purpose, followed by pagination and campaign targeting details. No redundancy or filler. Each sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers participant identification, sort order, pagination semantics including the response offset as cursor, and campaign targeting. The presence of an output schema means return values needn't be described. This is complete enough for an agent to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 20% (only campaignId has a description). The description compensates by explaining limit constraints (1-100, default 20), offset usage (skips logs), and how to identify the participant (by ID or email). It also clarifies the role of campaignId with a default. This adds meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('List') and resource ('participant's activity logs') with identification methods (ID or email) and sort order. It clearly distinguishes from sibling tools like growsurf_get_participant and growsurf_get_participant_analytics by naming the exact resource type.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear operational context: how to identify the participant (ID or email), pagination parameters and defaults, and campaign targeting behavior. It does not explicitly mention alternative tools to avoid, leaving some inference to the agent, but the guidance is sufficient for correct invocation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_get_participant_analyticsA
Read-onlyIdempotent
Inspect

Fetch analytics for one participant by GrowSurf participant ID or email. The base response includes all-time engagement, rank, share, and applicable affiliate revenue, commission, and payout metrics. Add activation to include for the program-specific eligibility anchor and covered first milestones, including firstPortalViewedAt and firstShareChannel. A null milestone with a partial or unavailable state is unknown, not proof that the action never happened. Request both activation and series for covered portalViews and shareActions buckets. Date-window parameters filter optional series and email data, not the base response or activation milestones. Targets campaignId if passed, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoNumber of days for optional `series` and `email` analytics. Does not filter the all-time base response.
endDateNoEnd of the optional-data timeframe, Unix timestamp in ms. Use with `startDate`.
includeNoComma-separated optional data. Current values are `series`, `email`, and `activation`; the API returns `400` for unknown values.
intervalNoBucket size for `series` and email series. Defaults to `day`.
startDateNoStart of the optional-data timeframe, Unix timestamp in ms. Use with `endDate` instead of `days`.
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
participantIdNo
participantEmailNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
emailNoSent, delivered, opened, clicked, bounced, and spam complaint metrics for program emails in the requested window.
ranksNoLeaderboard ranks for this participant.
seriesNoThis participant's per-period activity. Present when `include` contains `series`.
endDateNoWindow end (Unix ms). Present with `series` or `email`.
analyticsNoAll-time participant analytics totals. Date-window parameters do not filter these fields.
startDateNoWindow start (Unix ms). Present with `series` or `email`.
activationNoOpt-in covered eligibility and first-milestone analytics for one participant.
shareCountNoPer-channel share counts (e.g. `email`, `facebook`, `twitter`).

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark read-only/idempotent/non-destructive, and the description adds rich behavioral detail: date windows only affect optional series/email data, null milestones with partial state are unknown rather than proof of non-occurrence, and campaignId fallback. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence carries distinct semantic value, starting with the core purpose and then layering optional behavior, edge-case semantics, and scoping rules. No filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a parameter-rich analytics call, the description covers identification methods, optional data selection, date filtering scope, default campaign targeting, and null-state interpretation. The output schema exists, so return value details are not required.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds substantial meaning beyond the schema: it defines include values (activation, series, email), explains activation milestone semantics, and clarifies that date-window parameters do not filter the base response. This compensates for the 75% schema coverage and clarifies the most subtle parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description opens with a specific verb and resource: 'Fetch analytics for one participant by GrowSurf participant ID or email.' It clearly delimits scope (one participant) and names the response contents, making it distinguishable from campaign-level analytics siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clear context is provided: the tool is for per-participant analytics, with optional include values and campaign targeting behavior. It doesn't explicitly name alternatives or say when not to use it, but the one-participant scope and optional-data guidance are sufficient in context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_get_participant_payout_destinationA
Read-onlyIdempotent
Inspect

Get a participant's payout-destination status (by GrowSurf participant ID or email) across every payout provider enabled for the program (PayPal and/or Wise). For each provider it reports the current status, the confirmed payout email, the legal recipient type, and — when a delivery bounced or a recipient was invalidated — the repair reason. activeProvider is the provider that currently gets paid, or null until the participant confirms one. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
participantIdNo
participantEmailNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
destinationsNoOne entry per enabled payout provider describing the participant's destination for it.
activeProviderNoThe payout provider currently selected, or `null` until the participant confirms one. Provider identifiers are open-ended; current examples include `PAYPAL` and `WISECOM`.
enabledProvidersNoPayout provider identifiers enabled for this program. Values are open-ended; current examples include `PAYPAL` and `WISECOM`.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds substantial behavioral context: it explains what 'activeProvider' means and when it is null, describes the repair reason for bounced/invalidated recipients, and states that status is reported per provider. This goes well beyond the annotations and gives an agent a clear mental model of the tool's behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and front-loaded with the primary action, then covers return fields and the campaign targeting nuance in a logical order. Every sentence adds value—no fluff, no repetition of annotation info. It is a single paragraph but well-structured and efficient for an agent to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that an output schema exists (not shown but indicated), the description does not need to enumerate return format. It covers the key usage scenarios: looking up by ID or email, the provider context, the meaning of activeProvider, and failure states (bounce/invalidation). The default campaignId behavior is explicitly stated. An agent can select and invoke this tool correctly with no gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 33% (only campaignId has a description). The description compensates by explaining that participantId or participantEmail are identifiers, reinforcing the anyOf constraint, and fully explaining campaignId's default behavior. It adds meaning to the identifier parameters without going into format details, which is acceptable for a read tool. This strong compensation for low schema coverage merits a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description opens with a precise verb-resource pair: 'Get a participant's payout-destination status' and immediately clarifies scope (per provider, by ID or email). It lists specific return fields (status, confirmed email, legal recipient type, repair reason, activeProvider) that distinguish it from sibling tool growsurf_get_participant and analytics tools. The target ambiguity (campaignId vs default) is resolved in the last sentence.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies the tool is for checking payout-related state, contrasting with siblings like analytics or activity logs, and explains the campaignId override. It does not explicitly name alternative tools or say 'when not to use', but the purpose is specific enough that an agent would know when to call it. Lacking an explicit exclusion statement keeps it at a 4 rather than 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_get_teamA
Read-onlyIdempotent
Inspect

Fetch the team bound to the API key or OAuth connection. verificationStatus is VERIFIED once GrowSurf has verified the team, which is required before a program can email participants. Personal profiles and internal identifiers are not returned. Requires GROWSURF_API_KEY; does not require GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
nameNoThe team's display name.
verificationStatusNoTeam verification state. `VERIFIED` is required before a program can send participant emails.
verificationRequestedAtNoWhen verification was last requested, as a Unix timestamp in milliseconds.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the bar is lower. The description adds real value beyond annotations: the verificationStatus=VERIFIED semantic and its workflow implication (required before emailing participants), the exclusion of personal profiles/internal identifiers, and auth expectations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences with zero waste. Purpose is front-loaded, followed by the verification-state caveat, the privacy exclusion, and auth requirements. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists and handles return values. For a 0-parameter read tool, the description covers the key operational facts: what it fetches, the verification prerequisite, what is NOT returned, and which credentials are needed. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters and 100% schema coverage, so the schema has nothing to document. With no params, the baseline is 4; the description correctly fills the semantic gap by explaining authentication context (API key vs OAuth) that shapes how input is resolved.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Fetch') + resource ('team') + scope ('bound to the API key or OAuth connection'). Among a long sibling list containing update_team and verification tools, this unambiguously identifies a read-only team retrieval operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit prerequisites: requires GROWSURF_API_KEY and, notably, does NOT require GROWSURF_CAMPAIGN_ID — a useful signal for when this tool applies versus campaign-scoped siblings. Doesn't name alternatives outright, but as the only 'get team' tool among siblings this is a minor gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_grsf_config_snippetA
Read-onlyIdempotent
Inspect

Generate the snippet for participant auto-auth using window.grsfConfig (place before the GrowSurf Universal Code).

ParametersJSON Schema
NameRequiredDescriptionDefault
hashNo
emailNo
campaignIdNo
affiliateJoinNo
useCampaignIdPlaceholderNo
enableParticipantAutoAuthNo
includeAutoAuthCommentHeaderNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the description doesn't need to cover safety. It adds value by specifying the output artifact (a code snippet) and the configuration context (participant auto-auth, window.grsfConfig), which are not in annotations. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence with zero redundancy; the primary purpose and placement are front-loaded. Everything present earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having an output schema, the tool description omits essential details about parameter usage and selection logic. With 7 undocumented parameters and multiple sibling snippet tools, the description is insufficient for an agent to confidently invoke this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the tool description provides no parameter explanations. With 7 optional parameters (hash, email, campaignId, affiliateJoin, etc.), the agent has no guidance on what values to provide or how they affect the snippet. The description fails to compensate for the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool generates a <head> snippet for participant auto-auth using window.grsfConfig, with a specific placement instruction. This distinguishes it from other snippet tools like growsurf_embeddable_element_snippet or growsurf_client_snippets by naming the purpose (auto-auth) and the configuration variable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a placement instruction ('place before the GrowSurf Universal Code') but does not explain when to choose this tool over other snippet-related siblings. Given the large set of sibling tools, an agent would benefit from explicit selection criteria, which are absent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_integration_guideC
Read-onlyIdempotent
Inspect

Generate a guided, happy-path GrowSurf integration plan (referral + affiliate).

ParametersJSON Schema
NameRequiredDescriptionDefault
programTypeNoboth
singlePageAppNo
referralTriggerNosignup_plus_qualifying_action
webhookSecurityNotoken_in_url
participantAuthEnabledNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the agent knows this is a safe, non-destructive operation. The description adds the 'happy-path' qualifier and scopes to referral + affiliate, but does not disclose what the plan contains or any constraints on how it is generated. Given the annotations, a 3 is appropriate since the description is consistent but does not add meaningful behavioral context beyond the structured metadata.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, concise sentence that immediately states the tool's purpose. It is front-loaded with the verb and outcome. While it is short, it is not overly verbose and does not waste words. The structure is appropriate for a simple guide generator, though it could afford to include a bit more detail without losing conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has five parameters, a rich schema with enums and defaults, and an output schema exists, the description should provide enough context for the agent to know how to configure the plan. However, it offers only a vague 'happy-path' concept and program type, leaving the other parameters ambiguous. There is no explanation of what the plan will include or how the parameters influence it, making it incomplete for confident invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema description coverage at 0%, the description must clarify parameter meanings, but it fails to do so. The only hint is 'referral + affiliate' which maps to programType, but none of the other four parameters (singlePageApp, referralTrigger, webhookSecurity, participantAuthEnabled) are mentioned or explained. The schema provides enums and defaults, but the description does not add semantics or usage context for any parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb ('Generate') and a specific resource ('a guided, happy-path GrowSurf integration plan') and mentions the scope ('referral + affiliate'). This is not a tautology and conveys the tool's essential role. However, it does not explicitly differentiate itself from similar sibling tools like growsurf_mobile_sdk_guide or growsurf_api_library_snippets, which also appear to be guides.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit guidance on when to use this tool versus alternatives, such as the other guide-style tools (e.g., growsurf_mobile_sdk_guide). The purpose is implied but not stated with exclusions or conditions. The agent would have to infer that this is the correct guide based on the 'referral + affiliate' wording, but no when-to-use or when-not-to-use information is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_list_campaign_rewardsA
Read-onlyIdempotent
Inspect

List your GrowSurf program's configured rewards. These settings do not establish that a participant earned or received a reward; inspect their rewards with growsurf_get_participant. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
rewardsNoThe program's active, visible, and enabled reward configs.
rewardEvidenceNoWhat this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint false. The description adds meaningful behavioral context: listed rewards are configurations, not evidence of participant earning, and the call defaults to GROWSURF_CAMPAIGN_ID when campaignId is omitted. This goes beyond the annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences carry the primary purpose, a critical caveat, an alternative tool reference, and the default parameter behavior. Every sentence earns its place with no redundant filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-optional-parameter, read-only listing tool with an output schema and supportive annotations, the description covers the key contextual needs: what is returned, what it does not imply, and how targeting works. No critical information appears missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the schema already documents that campaignId defaults to GROWSURF_CAMPAIGN_ID and can be populated with the id from growsurf_create_campaign. The description repeats part of this behavior rather than adding new parameter semantics, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List') and resource ('program's configured rewards'), and clarifies it is about configured settings, not participant reward status. It also implicitly distinguishes itself from participant-related tools by pointing to growsurf_get_participant.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says when not to rely on this tool: these settings do not establish that a participant earned or received a reward, and directs the agent to growsurf_get_participant instead. It also explains the campaignId defaulting behavior, giving clear guidance for selecting the right target.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_list_campaignsA
Read-onlyIdempotent
Inspect

List the GrowSurf programs available to the bound team. Use this first when you need to choose a campaignId before calling campaign-scoped tools. Deleted programs are not returned. Does NOT require GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
campaignsNoPrograms available to the API key's bound team.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds behavioral context beyond that: it notes that deleted programs are not returned and that GROWSURF_CAMPAIGN_ID is not required. Since the output schema exists, it doesn't need to detail return structure. This is solid complementary info.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: the first states the core purpose, the second gives usage context, and the third covers a behavioral nuance. The most important information (what it lists and when to use) is front-loaded. No filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a no-parameter list tool, the description is complete: it states what it does, when to use it, what it omits (deleted programs), and clarifies the environment variable requirement. With an output schema available, the agent has everything it needs to call and interpret this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so there is nothing to document, and the description adds no parameter details (which is expected). The note about not requiring GROWSURF_CAMPAIGN_ID clarifies a common context, but it's not about a parameter in this tool. Baseline for 0 params is 4, and nothing is missing.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('List') and the resource ('GrowSurf programs available to the bound team'). It explicitly differentiates itself from campaign-scoped siblings by noting it should be used first to select a 'campaignId' before calling those tools. This makes its purpose precise and non-overlapping.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides explicit when-to-use guidance: 'Use this first when you need to choose a campaignId before calling campaign-scoped tools.' It also clarifies that it does not require GROWSURF_CAMPAIGN_ID, which is a key trigger for when this tool is appropriate versus others. The exclusion of deleted programs adds a useful caveat for interpreting results.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_list_campaign_webhooksA
Read-onlyIdempotent
Inspect

List your GrowSurf program's webhooks (secrets are never returned). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
webhooksNoWebhooks configured for the program.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds behavioral context beyond annotations: it explicitly states that secrets are never returned, which is a crucial security-related behavior not captured in structured fields. It also clarifies the default campaignId behavior, though that is also in the schema. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences with zero waste. The core purpose and the critical secret-handling caveat are front-loaded, followed by the parameter behavior. Every sentence earns its place, and there is no redundant or fluff content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple list tool with one optional parameter, the description is complete. Annotations cover the read-only and safe nature, an output schema exists to document return values, and the description clarifies the campaign targeting and security guarantee. Nothing an agent needs to correctly invoke this tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already fully documents campaignId, including its default to GROWSURF_CAMPAIGN_ID. The description repeats this information ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID') without adding new semantics beyond what the schema provides. Since the schema carries the burden, a baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists webhooks for a GrowSurf program, using a specific verb ('List') and resource ('webhooks'). It also mentions an important caveat (secrets never returned) and the campaign targeting behavior. This distinguishes it clearly from sibling webhook tools like create/update/delete/test, and from list_campaigns which lists campaigns, not webhooks.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context (read-only listing) and explains the campaignId targeting behavior, which helps the agent decide when to call it. However, it does not explicitly name alternatives (e.g., 'use growsurf_create_campaign_webhook to add webhooks') or state when NOT to use this tool. The sibling names make the distinction fairly obvious, but explicit guidance would elevate this to a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_list_integrationsA
Read-onlyIdempotent
Inspect

List every integration your GrowSurf program can connect (Stripe, PayPal, Wise, Mailchimp, Slack, Zapier, Webhooks, and more) with its current state, so you can check whether an integration is connected before you act on it. Each entry has connected (credentials are stored), enabled (switched on and working), autoDisabled (GrowSurf switched it off after repeated delivery failures — the credentials are still stored, but nothing is delivered until the user reconnects it), and connectUrl (the dashboard link to hand the user). Integrations that do not apply to the program type are omitted (for example, Wise on a referral program). Read-only: connecting an integration happens in the GrowSurf dashboard, not through the API — call growsurf_get_integration_connect_link for the link to hand the user. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
integrationsNoEvery integration this program can connect, in the order the GrowSurf dashboard lists them.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and the description reinforces the read-only nature. It adds meaningful context beyond the annotations by defining the state fields (connected, enabled, autoDisabled, connectUrl) and disclosing that autoDisabled means delivery stops until reconnection. Consistent with annotations, no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose and readable, but slightly verbose — the field definitions and omission rule, while valuable, could be tightened. Every sentence earns its place, so the length is justified rather than padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complete for a filtered-list tool: an output schema exists so return values are covered there, and the description explains the state semantics, the omission behavior, the read-only constraint, the alternative tool, and the targeting rule. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single campaignId parameter is fully documented in the schema, including the default and the create_campaign hint. The description adds only a marginal targeting note ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID') that mostly restates the schema. Baseline 3 is appropriate since the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List) + resource (every integration for a program) + scope, and enumerates concrete examples (Stripe, PayPal, Mailchimp, Slack, Zapier, Webhooks). The read-only caveat and connect-link routing differentiate it from siblings like growsurf_get_integration_connect_link and growsurf_integration_guide, so an agent can distinguish it without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit use case ('check whether an integration is connected before you act on it'), explains that inapplicable integrations are omitted, and names the alternative tool with the condition that selects it ('call growsurf_get_integration_connect_link for the link to hand the user'). Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_list_participantsA
Read-onlyIdempotent
Inspect

List participants in your GrowSurf program, newest page first. limit is 1-100 (default 10). Pass response nextId into the next call to continue paging. Use this when you need a participant ID before calling participant-scoped tools. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
nextIdNoParticipant ID returned as `nextId` from the previous page.
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
limitNoMaximum number of participants requested for this page.
nextIdNoParticipant id to pass as `nextId` for the next page, or `null` when there are no more results.
participantsNoParticipants returned for this page.
rewardEvidenceNoWhat this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark it read-only, idempotent, and non-destructive. The description adds valuable behavioral detail beyond those hints: newest-first ordering, the 1-100 limit with default 10, continuation via nextId, and the campaignId fallback to GROWSURF_CAMPAIGN_ID. No annotation contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: one states the core action and ordering, one covers limit and paging, and one covers when to use it and campaign targeting. No fluff or redundant filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema available, return values do not need to be described. The description covers purpose, ordering, pagination, default behavior, campaign targeting, and when to use the tool, making it fully actionable for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers nextId and campaignId, but the description adds the default limit (10), reinforces the 1-100 range, and explains the pagination flow. It compensates for the limit parameter lacking a schema description, though it partly restates existing parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action ('List participants'), a specific resource ('your GrowSurf program'), and a distinguishing behavior ('newest page first'). The note about needing participant IDs before participant-scoped tools clearly differentiates it from get/add/update participant siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when-to-use criterion: 'Use this when you need a participant ID before calling participant-scoped tools.' It also explains the paging flow and campaign targeting. It does not explicitly name alternatives or say when not to use it, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_list_program_resourcesA
Read-onlyIdempotent
Inspect

List the participant resources configured for your GrowSurf program, including drafts. Results stay in display order. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resourcesNoThe program's resources in participant display order, including drafts.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, destructiveHint, and idempotentHint, which cover the safety profile. The description adds extra behavioral value by noting 'including drafts' and 'results stay in display order', plus the default targeting behavior, enriching the agent's understanding beyond the structured annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three concise sentences, front-loaded with the primary purpose, then two relevant behavioral details. There is zero redundancy and every sentence contributes to the agent's ability to use the tool correctly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a low-complexity tool with a single optional parameter and an output schema, the description covers purpose, scope (including drafts), ordering, and default targeting. Nothing necessary for correct invocation is missing, and the output schema handles return-value details.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% since the single parameter campaignId has a thorough description explaining the default and how to pass a newly created campaign ID. The tool description merely restates this default targeting behavior without adding new information, so it provides no additional parameter semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it lists participant resources for a GrowSurf program, including drafts. It identifies the resource type and the action (list) precisely, and this distinguishes it from sibling tools that list campaigns, participants, or rewards.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context for when to use the tool (listing program resources) without naming alternatives or exclusions. It doesn't explicitly say 'use this instead of X', but the specificity of 'participant resources' makes the usage unambiguous among the many sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_mobile_sdk_guideB
Read-onlyIdempotent
Inspect

Generate native iOS/Android SDK 0.4.0 guidance, including attribution, shareUrl sharing, trackShare, and the native GrowSurf Window.

ParametersJSON Schema
NameRequiredDescriptionDefault
platformNoboth
campaignIdNo
mobilePublicKeyNo
participantStateNoboth
attributionProviderNoall
includeInstallSnippetsNo
serverVerifiedQualifyingActionNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

B3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, covering the safety profile. The description adds the topics covered but does not disclose any additional behavioral traits, such as required setup or output format. It provides some context but not deep behavioral detail.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence with no wasted words. It efficiently states the purpose and key features, though it could structure the content with more detail without becoming verbose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 7 parameters and an output schema, the description is too sparse. It does not explain what the generated output looks like, which parameters are essential, or any constraints. Even with annotations and an output schema, an agent would struggle to call this correctly without additional information.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the description does not explain any of the 7 parameters (e.g., platform, campaignId, mobilePublicKey, participantState). An agent receives no guidance on how to set these parameters or what each represents, leaving the schema enums and defaults as the only clues.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool generates guidance for the native iOS/Android SDK version 0.4.0, listing specific features like attribution, shareUrl sharing, trackShare, and the native GrowSurf Window. This distinguishes it from siblings like growsurf_integration_guide and growsurf_client_snippets.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not mention when to use this tool versus alternatives. With many sibling guide/snippet tools present, there is no explicit differentiation in terms of usage context, such as 'for web use X' or 'for client-side snippets use Y'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_participant_auth_hashA
Read-onlyIdempotent
Inspect

Compute the server-side SHA-256 HMAC for GrowSurf Participant Auto Authentication. Set affiliateJoin only when this signed-in user may join the affiliate program directly.

ParametersJSON Schema
NameRequiredDescriptionDefault
emailYes
affiliateJoinNo
participantAuthSecretNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
hashNoThe computed hash. Pass it to the GrowSurf client as the participant's `hash` value.

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering safety and side-effect behavior. The description adds the 'server-side' qualifier and the affiliateJoin condition, but does not disclose more behavioral traits like error handling, validation, or external dependencies. Given the annotation coverage, a 3 is appropriate—it adds small value without contradicting annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, with no filler. The first sentence front-loads the core purpose, and the second adds a focused parameter note. Every word earns its place, and the structure is efficient for an agent scanning for intent.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no schema descriptions and three parameters, an agent needs more guidance. The description explains only one parameter's condition, leaving email and participantAuthSecret open to interpretation. While an output schema exists (not shown), the description does not clarify the intended use of the output or the role of the secret. This is a material gap for a tool with 0% schema coverage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the burden. It explicitly explains the semantics of affiliateJoin ('only when this signed-in user may join the affiliate program directly'), but leaves email and participantAuthSecret unaddressed. email is self-explanatory as a string, but participantAuthSecret is not explicitly tied to the HMAC secret key—it's only implied by 'server-side SHA-256 HMAC'. This is insufficient for a 0% coverage scenario.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Compute') and a precise resource ('server-side SHA-256 HMAC for GrowSurf Participant Auto Authentication'). This clearly distinguishes the tool from siblings like participant retrieval or campaign management by focusing on auth-hash generation. The additional affiliateJoin note clarifies a secondary purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides an explicit condition for when to set affiliateJoin ('only when this signed-in user may join the affiliate program directly'), which is a direct usage guideline. There are no true alternatives among siblings—no other tool computes an auth hash—so a 'when not to use' isn't necessary. The purpose sentence implies the primary use case (generating an auth hash for auto authentication).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_prepare_program_resource_fileAInspect

Prepare a local file for a FILE Program Resource. Pass the safe file name, matching supported MIME type, and padded base64 bytes (10 MB maximum). GrowSurf requests a one-time ticket and uploads only to the secure HTTPS destination selected by GrowSurf. The result contains only uploadTicket and uploadResult; pass both unchanged to growsurf_create_program_resource or growsurf_update_program_resource. The tool does not accept upload URLs or credentials and never retries an ambiguous upload. This tool is the only source of uploadTicket and uploadResult, and it needs GROWSURF_UPLOAD_ALLOWED_ORIGINS set on the server; without it, FILE resources are unavailable and only LINK and TEXT resources can be created. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileNameYesA safe base name with an allowed extension: jpg/jpeg/png/gif/webp/pdf/csv/zip/doc/docx/xls/xlsx/ppt/pptx.
mimeTypeYesThe supported MIME type matching fileName's extension.
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
fileBase64YesCanonical padded base64 file bytes only. Do not include a data-URL prefix or whitespace.

Output Schema

ParametersJSON Schema
NameRequiredDescription
uploadResultNoThe minimal signed upload confirmation. Pass it unchanged to create/update.
uploadTicketNoThe one-time GrowSurf ticket. Pass it unchanged to create/update.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description discloses one-time ticket behavior, no retry on ambiguous uploads, no acceptance of upload URLs or credentials, secure HTTPS destination, environment variable requirement, and campaignId targeting. It matches the annotations and adds substantial execution context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence carries operational value: purpose, inputs, security behavior, output contract, failure policy, prerequisite, and campaign targeting. It opens with the core action and required inputs before adding supporting details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a file-upload preparation tool with a multi-step contract, the description covers prerequisites, output shape, downstream consumer, constraints, and fallback behavior. Nothing an agent needs to call it correctly or route the result is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already documents all parameters at 100 percent coverage, so the baseline is 3. The description adds value by stating the 10 MB maximum, requiring a safe name and matching MIME type, and emphasizing padded base64 bytes with no data-URL prefix, reinforcing constraints an agent might otherwise miss.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action (prepare a local file), defines the resource type (FILE Program Resource), and explicitly ties its output to growsurf_create_program_resource and growsurf_update_program_resource. The scope is unambiguous and clearly distinguished from the create/update siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the create/update tools that consume the ticket and states that this tool is the only source of uploadTicket and uploadResult. It also explains the server-side prerequisite, warns that FILE resources are unavailable without it, and notes LINK and TEXT as the only alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_program_design_advisorA
Read-onlyIdempotent
Inspect

Use for program designs, benchmarks, typical rewards, and metric definitions, including participant-to-referral and lead-to-referral ratios. Read-only; call with known context before asking questions. Returns a short draft, complete benchmarkFacts to quote, exact configurationPlan tool calls, and unresolved decisions. Preserve the calls and leave unresolved incentives open. Use the default summary for first designs and configuration drafts; use detail: full when the user requests detailed benchmark tables or a specific figure absent from the summary. Hosted figures describe GrowSurf's high-performing programs; without a bundle, guidance is documentation-based. Use programType: AFFILIATE for affiliates and industry: other for local services, pets, hospitality, or agencies. All inputs are optional.

ParametersJSON Schema
NameRequiredDescriptionDefault
goalNoWhat a successful referral means for the business. `paid_conversions` and `leads` imply a qualifying action; `signups`, `subscribers`, and `waitlist` count the signup unless a separate `qualifyingAction` needs clarification. This is the advisor's goal enum; use the separate creation goal returned in `configurationPlan` for `growsurf_create_campaign`.other
detailNoUse summary for a first design or configuration draft, including a reward structure recommendation. Use full only for requested detailed benchmark tables or specific figures absent from the summary, such as reward amounts, share channels, or integration proportions.summary
audienceNoWho refers whom.
industryNoClosest industry segment: `financial_services_fintech` (banking, lending, investing, insurance, payments, crypto), `saas_ai` (software sold to businesses, developer tools, AI products), `media_newsletters` (newsletters, podcasts, publishers, content brands), `healthcare_wellness` (clinics, telehealth, fitness, nutrition, mental health, supplements), `education_workforce` (courses, bootcamps, tutoring, hiring and job platforms), `consumer_subscriptions_commerce` (consumer apps, e-commerce, marketplaces, subscription boxes). Use `other` when no segment clearly fits (local services, pets, hospitality, agencies) rather than stretching one; `other` returns the platform-wide figures.other
companyNameNoUsed in the heading and proposed program name; omit it when unknown.
currencyISONoISO 4217 code. Non-USD advice omits the dollar reward bands. No exchange rate or equivalent-currency benchmark is available.
programTypeNoREFERRAL
salesMotionNoUse `sales_led` for demos, sales calls, negotiated pricing, or signed contracts; use `self_service` when customers buy directly. This selects the reward structure. Omit when unknown.
includeRulesNoAppend guidance on applying the recommendations. Off by default.
businessModelNoOne line on what the business sells and how. Also set `salesMotion` when the buying process is known.
qualifyingActionNoThe action a referred friend must complete, in the customer's words.
rewardBudgetPerReferralNoThe customer's spending limit per successful referral, in major currency units. A budget does not select an incentive amount or commission rate. Budget comparisons omit the mixed-currency reward amount bands.

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe requested summary or full advice, including the same configuration calls and their conditions.
decisionsNoUse one qualifying action throughout the draft. Unresolved choices require a customer decision before configuration.
benchmarkFactsNoComplete benchmark statements with metric units, median, Q1, Q3, sample, and source. Quote each statement intact. Empty when no suitable figures are available.
configurationPlanNoProposed calls using the listed tools' argument shapes. Preserve each tool and arguments object when presenting the plan; replace <new-program-id> with the creation response's id before execution.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds meaningful behavioral detail beyond the annotations: it is read-only, returns exact tool calls that the caller must preserve, leaves unresolved incentive decisions open, and depends on a bundle vs documentation-based guidance. These details are not available in annotations and shape how the caller must handle the result.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but front-loaded with purpose, mode, and parameter-choice guidance. It is longer than necessary because some detail is already covered by the schema, but each sentence adds behavioral or selection context, making the extra length largely justified.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 12 optional parameters, output schema, and complex how-to-use decisions, the description covers behavior, return shape, parameter selection, and data-source variation. It also flags preservation rules for the generated configurationPlan calls and unresolved decisions, making it fully operational for the agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 92% schema coverage, most parameter meaning is already available, but the description adds value by explicitly mapping programType AFFILIATE and industry other to practical scenarios, and by prescribing summary vs full detail usage. Some instructions repeat schema parameter descriptions, so it does not fully exceed the schema, but it still improves selection and usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: it is a read-only program design advisor for benchmarks, reward structures, metric definitions, and with output that includes a draft, benchmarkFacts, configurationPlan calls, and unresolved decisions. This clearly differentiates it from the many create/update action tools in the sibling set.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear context for when to use the tool, such as using summary mode for first drafts and full mode for requested benchmark tables, and it maps programType/industry values to common user cases. It does not explicitly name sibling alternative tools to exclude or state when-not-to-use though, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_record_saleA
Idempotent
Inspect

Record a sale/transaction for an affiliate program. Use webhooks to know when commissions are added. Requires at least one transaction identifier (externalId, transactionId, orderId, paymentId, invoiceId, paymentIntentId, or chargeId) so repeated calls are de-duplicated instead of double-paying the referrer; reuse the same one when refunding. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
paidAtNo
orderIdNo
chargeIdNo
currencyYes
testModeNoRequired with `paymentProvider`: `true` for test or `false` for live. Otherwise omit.
invoiceIdNo
netAmountNo
paymentIdNo
taxAmountNo
amountPaidNo
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
customerIdNo
externalIdNo
totalTaxesNo
descriptionNo
grossAmountYes
invoiceTotalNo
amountCashNetNo
participantIdNo
transactionIdNo
subscriptionIdNo
totalTaxAmountNo
paymentIntentIdNo
paymentProviderNoConnected provider for this payment. Requires `transactionId` and `testMode`. Supply matching `grossAmount` and `currency`; other payment IDs and tax or net-amount overrides are not accepted. GrowSurf reads payment details from the provider and detects duplicate webhook/API/manual submissions.
totalTaxAmountsNo
participantEmailNo
invoiceTotalExcludingTaxNo
invoiceSubtotalExcludingTaxNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable result message.
successNo`true` when the sale was recorded; `false` when it matched an existing transaction.
duplicateNo`true` when the sale matched an existing transaction.
firstSaleNoWhether this was the referred customer's first recorded sale.
duplicateFieldsNoIdentifier fields that matched an existing transaction.
commissionsCreatedNoCommissions created by this duplicate request.
matchingCommissionIdsNoCommission ids that matched the submitted identifiers.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the idempotentHint annotation, the description discloses the real-world consequence of duplicate calls ('double-paying the referrer'), explains that identifiers enable de-duplication, and advises reusing the same identifier when refunding. This is valuable behavioral context; it doesn't cover auth or side-effect details, but annotations already cover safety.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, no filler. The core action, key requirement, deduplication rationale, and campaign targeting behavior are all front-loaded and each sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 28-parameter tool with complex conditional requirements, the description plus schema and output schema cover the essentials: required identifier group, dedup behavior, campaign default, and paymentProvider nuances are in the schema. It could mention the participantId/participantEmail requirement explicitly, but the schema's allOf already encodes it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only 11% schema description coverage, the description compensates by enumerating the accepted transaction identifiers and explaining why one is required, and by stating campaignId targeting with GROWSURF_CAMPAIGN_ID fallback. It does not explain amount units or participant selection, but it addresses the most non-obvious parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource: 'Record a sale/transaction for an affiliate program.' The description also explains the deduplication purpose, which distinguishes this write/record tool from siblings like refund_transaction and add_participant.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes clear this tool is for recording sales/transactions and mentions the webhook follow-up for commissions, giving solid context. It does not explicitly name alternatives or state when not to use it, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_refund_transactionA
DestructiveIdempotent
Inspect

Record an amendment (refund, partial refund, or chargeback) against a previously recorded affiliate transaction; reverses or adjusts the referrer's commission. The inverse of growsurf_record_sale. Identify the original transaction with the same identifier you sent when recording it (omit amountRefunded for a full refund). Already-paid commissions are not clawed back (recorded for tax only). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
amountNo
orderIdNo
chargeIdNo
currencyNo
refundIdNoStable per-refund identifier. Required when canceling a refund or changing the refunded total after a cancellation. Reuse the original refund's identifier for its cancellation. An amendment without enough refund identity returns `409` without applying the cancellation. Newly observed higher cumulative refunds and incomplete coverage are retained for reconciliation.
testModeNoOriginal payment mode: `true` for test or `false` for live. Requires `paymentProvider`.
invoiceIdNo
paymentIdNo
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
externalIdNo
descriptionNo
refundAmountNoPositive amount for this individual refund, no greater than the sale amount, in the sale currency's minor unit. Send it with `refundId` on each original refund to support cancellations and out-of-order amendments. The amount for a given `refundId` cannot change. A cancellation can omit it when the original amount is already recorded. Incomplete refund history returns `409` without applying the cancellation. Newly observed higher cumulative refunds and incomplete coverage are retained for reconciliation.
refundStatusNo
amendmentTypeNo
participantIdNo
transactionIdNo
amountRefundedNo
paymentIntentIdNo
paymentProviderNoConnected provider for the original payment. Requires its `transactionId` and `testMode`. This amends GrowSurf records without sending a refund through the provider.
participantEmailNo
refundHistoryCompleteNoSet true only after reconciling and recording every original refundId and refundAmount, including refunds later canceled. This confirmation resolves previously incomplete history. Omit during ordinary delivery. Replaying an old confirmation cannot resolve a later gap; confirm a newly reconciled refund or complete provider list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
deletedNoPending commissions deleted by the amendment.
matchedNoCommissions found for the provided identifiers.
messageNoHuman-readable result message.
successNo`true` when the amendment was processed; `false` when no matching transaction was found.
adjustedNoCommissions partially adjusted.
notFoundNoPresent and `true` when no commission matched the provided identifiers.
reversedNoCommissions reversed (set to zero amount).
amendmentTypeNoAmendment type that was processed.
matchingCommissionIdsNoCommission ids that matched the submitted identifiers.

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark destructive and idempotent hints, but the description adds essential behavioral facts: "Already-paid commissions are not clawed back (recorded for tax only)" and "Targets `campaignId` if you pass it, otherwise GROWSURF_CAMPAIGN_ID." These details go beyond annotations and clarify side effects, tax treatment, and default targeting, giving the agent a fuller picture.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured paragraph with no filler. It front-loads the core purpose, then provides the inverse relationship, identification guidance, refund amount nuance, commission clawback caveat, and campaign targeting default. Every sentence carries useful information, and the length is appropriate for the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 21 parameters and a complex anyOf-required schema, the description covers the high-level intent and one nuance (full refund), but it omits critical usage context such as the mandatory identifier groups and the distinction between refundId/refundAmount for cancellations. The schema does carry these details for some fields, and the output schema covers return values, so the description is not entirely inadequate, but it leaves gaps that an agent must discover elsewhere. Given the complexity, a more complete description would reference these requirements.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema description coverage at only 29% (6 of 21 properties have descriptions), the description must compensate for the undocumented parameters. It only mentions amountRefunded ("omit amountRefunded for a full refund") and campaignId (default behavior). It does not explain the required group combinations (participantId/email plus one transaction identifier), nor the purpose of fields like refundStatus, description, or currency. The schema descriptions for some params are rich, but the main description adds little beyond two parameters, so it fails to support the majority of the API surface.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-resource pair: "Record an amendment (refund, partial refund, or chargeback) against a previously recorded affiliate transaction," and clarifies its effect ("reverses or adjusts the referrer's commission"). It explicitly names the sibling relationship with "The inverse of growsurf_record_sale," which distinguishes it from the most relevant alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear when-to-use guidance: it is the inverse of growsurf_record_sale and gives operational details like "Identify the original transaction with the same identifier you sent when recording it" and "omit amountRefunded for a full refund." It does not explicitly list when not to use it, but the inverse relationship and the amendment context are sufficient for an agent to select it. No other sibling tools serve a similar reverse function.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_request_participant_payout_destination_confirmationA
Destructive
Inspect

Ask a participant to confirm their payout destination for a provider (by GrowSurf participant ID or email). Sends them a one-time confirmation link for the chosen provider; only the participant can open the link and confirm — this just triggers the message, and the provider must be enabled for the program. Returns { status, provider, providerDisplayName, expiresAt }. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
providerYesThe payout provider the participant should confirm a destination for.
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
participantIdNo
participantEmailNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusNoConfirms the message was requested (`CONFIRMATION_REQUESTED`).
providerNoThe payout provider identifier the participant was asked to confirm. Values are open-ended; current examples include `PAYPAL` and `WISECOM`.
expiresAtNoWhen the confirmation link expires, as a Unix timestamp in milliseconds.
providerDisplayNameNoThe customer-facing provider name (e.g. "PayPal", "Wise").

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint=false, destructiveHint=true, etc.), the description adds useful behavioral detail: it sends a one-time confirmation link, only the participant can confirm, and it 'just triggers the message' (implying no direct state change on the participant). It also notes the provider must be enabled. These specifics go beyond the structured annotations, though it doesn't mention potential side effects like multiple sends or rate limits. No contradiction with annotations is apparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is succinct, about 70 words, with no fluff. It front-loads the core purpose, then provides key behavioral notes, return value, and campaign targeting in a logical order. Every sentence contributes necessary information without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the moderate complexity (4 params, output schema present, annotations provided), the description covers the essential usage context: what triggers, prerequisites (provider enabled), return format, and campaign targeting default. It does not explain error conditions or authentication requirements, but these are not required given the output schema and typical tool documentation. The description is sufficiently complete for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has only 50% description coverage (provider and campaignId have descriptions; participantId and participantEmail do not). The description compensates by clarifying that participantId and participantEmail are alternative identifiers for targeting the participant (aligning with the anyOf constraint), explains the provider parameter's role, and details the campaignId default behavior. This adds meaning beyond the bare schema, though it doesn't specify formats or validations beyond what the schema already conveys.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Ask a participant to confirm their payout destination'), the target (a participant, by ID or email), and the mechanism (sends a one-time confirmation link). It also distinguishes itself from sibling tools like growsurf_get_participant_payout_destination (which retrieves the destination) by emphasizing that this triggers a confirmation request rather than performing the confirmation itself.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides contextual guidance: it triggers a message (not the actual confirmation), requires the provider to be enabled, and explains campaign targeting with a default. However, it does not explicitly state when to use this tool over alternatives or when not to use it. For example, it doesn't say 'Use this to initiate a confirmation request, rather than growsurf_get_participant_payout_destination to view the current destination.' This leaves some inference to the agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_request_team_verificationA
Idempotent
Inspect

Ask GrowSurf to verify the team bound to the API key or OAuth connection. Verification is required before a program can email participants. Calling this again while a request is pending does not create a duplicate. Returns the team with its updated verificationStatus. Requires GROWSURF_API_KEY; does not require GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
nameNoThe team's display name.
verificationStatusNoTeam verification state. `VERIFIED` is required before a program can send participant emails.
verificationRequestedAtNoWhen verification was last requested, as a Unix timestamp in milliseconds.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds value beyond the annotations by specifying that repeated calls during a pending request do not create duplicates (aligning with idempotentHint) and that it returns the team with its updated verificationStatus. It also notes the API key requirement, which is not in the annotations. No contradictions with the provided annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise at three sentences, with the primary action front-loaded. Every sentence earns its place: purpose, prerequisite, idempotency, and return behavior. No redundant or filler content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter tool, the description is complete: it explains what the tool does, when it's needed, its idempotency, its return value, and its prerequisites. The presence of an output schema reduces the need to detail return values further. It could explicitly mention that this is different from resending the verification email, but that is a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the description cannot add parameter-specific context. Per the calibration, a baseline of 4 is appropriate, and the description does not miss any parameter documentation responsibilities.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Ask GrowSurf to verify the team') and the specific resource (team bound to API key or OAuth connection). It also explains the purpose ('Verification is required before a program can email participants'), distinguishing it from other tools like growsurf_get_team or growsurf_resend_team_owner_verification_email.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides clear context for when to use the tool (before emailing participants) and mentions idempotency ('Calling this again while a request is pending does not create a duplicate'). While it doesn't explicitly contrast with the sibling resend email tool, the requirement statement implies the appropriate use case.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_resend_team_owner_verification_emailA
Destructive
Inspect

Resend the email-verification message to the bound team's owner. The response never reveals the owner's email address. A 200 with status: SENT is returned only when an email was sent. Returns 400 if the email is already verified and 429 if one was sent too recently. Requires GROWSURF_API_KEY; does not require GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusNoStatus of the verification email request.
successNoWhether the verification email request was accepted.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate this is a mutating operation (readOnlyHint=false, destructiveHint=true). The description adds valuable details beyond that: the response never reveals the owner's email, and it specifies exact HTTP status conditions (200 with SENT, 400 if verified, 429 if rate-limited). This is exactly the kind of non-obvious behavioral information an agent needs. It doesn't contradict annotations and goes beyond them, though it could mention what happens on other errors or failure modes to be fully transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is tightly packed and front-loaded. The first sentence states the core action, followed by response semantics and requirements. Every sentence earns its place; there is no filler or redundancy. For a zero-parameter tool, this is appropriately concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has no parameters, an output schema exists, and annotations cover side effects, the description covers all necessary operational details: what it does, response codes, error conditions, and environmental prerequisites. Nothing is missing for an agent to call this tool correctly. It's fully self-contained for its simple purpose.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so schema coverage is trivially 100%. Per the rubric, a tool with 0 params gets a baseline of 4. The description mentions the required API key and that campaign ID is not required, which are environmental requirements rather than parameters, adding context without inventing parameters. There's nothing else to clarify.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action: 'Resend the email-verification message to the bound team's owner.' This is a specific verb and resource, and it distinguishes itself from sibling tools like growsurf_request_team_verification by emphasizing 'resend' and the targeted owner. The purpose is immediately clear without ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides contextual cues for when to use the tool: it mentions that a 400 is returned if already verified (implying you shouldn't use it for verified owners) and a 429 if sent too recently (indicating rate-limiting). It also notes the API key requirement and that campaign ID is not needed, which helps the agent decide if this tool fits the environment. However, it doesn't explicitly name alternative tools or provide exclusions, so it's not a perfect 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_test_campaign_webhookA
Destructive
Inspect

Send a live test event to a webhook on your GrowSurf program using its stored URL and secret. Optionally pass event to choose which event type to simulate; when omitted, the webhook's first enabled event is used (returns 400 if the webhook has no enabled events). Returns the mock payload and the receiving endpoint's response. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
eventNo
webhookIdYes
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
payloadNoThe mock event payload that was sent.
successNoWhether the test webhook request completed.
responseNoResponse returned by the webhook endpoint during the test.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are sparse (destructiveHint=true, openWorldHint=true) but the description adds meaningful context on top: it discloses that a live event goes to an external endpoint using stored credentials, that it returns both the mock payload and the endpoint's response, and the 400 error edge case for webhooks with no enabled events. No contradiction with annotations — the side-effecting 'send live' behavior aligns with destructiveHint=true. Could have noted that delivery is a genuine external call, but the 400 and response detail already carry the burden.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four tight sentences, all substantive: core action first, then event semantics, then return value, then campaign targeting. The most important scoping constraint (default event, 400 case) is front-loaded. No filler or repetition of schema-only content; each sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a moderate-complexity tool (3 params, 1 enum, open-world campaign default, error cases), the description is largely complete: it covers purpose, param behavior, return value, and the notable failure mode. Since an output schema exists, the return description is a bonus rather than required. Minor residual gaps — e.g., behavior when webhookId is invalid or network errors on the endpoint — are not covered, but the essentials are present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 33% (only campaignId is documented in the schema), so the description must compensate. It does: it explains `event`'s defaulting and error behavior, clarifies campaignId's GROWSURF_CAMPAIGN_ID fallback, and implies webhookId's role via 'webhook on your GrowSurf program using its stored URL and secret.' Only minor gap is that webhookId itself is never named as the target identifier, but the enum for `event` and campaignId guidance give agents enough to call it correctly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-resource pair — 'send a live test event to a webhook' — and clarifies it uses 'its stored URL and secret.' This clearly distinguishes it from sibling webhook tools (create/update/delete/list) since it is the testing action, and the purpose is unambiguous even before reading the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains behavioral outcomes well (default event selection, 400 on no enabled events, campaignId fallback) but never says when to reach for this tool versus alternatives like growsurf_create_campaign_webhook or growsurf_webhook_normalize. Usage context is implied by 'test' in the name rather than stated, and no exclusions or 'use X instead' guidance is offered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_trigger_referralA
Destructive
Inspect

Trigger referral credit for a referred participant (use when your trigger is Sign up + Qualifying Action). Optionally pass delayInDays (1-90) to hold the credit for N days before awarding it (e.g. to cover a refund window). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
delayInDaysNo
participantIdNo
participantEmailNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable result message. Present when credit was not awarded immediately.
successNoWhether referral credit was awarded, scheduled, or cancelled.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and openWorldHint=true, covering the mutation nature. The description adds useful context about the delayInDays behavior and campaign targeting (GROWSURF_CAMPAIGN_ID fallback), but does not disclose additional side effects such as irreversibility or interaction with growsurf_cancel_delayed_referral. Since annotations carry the safety profile, this is adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single well-structured sentence plus a brief second sentence on campaign targeting. Every clause adds value—the use case, the delay option, and the default behavior—with no redundant wording.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema, so return values are covered. However, the description omits important operational details such as error conditions, behavior when both participantId and participantEmail are provided, and the relationship with growsurf_cancel_delayed_referral for delayed credits. Given the complexity (anyOf, delay, campaign selection), more context would aid correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 25%, and the description only elaborates on campaignId and delayInDays. The participantId and participantEmail parameters, which are critical and mutually exclusive via anyOf, are left unexplained. The description mentions 'referred participant' but does not clarify which identifier to pass under what conditions, leaving a significant gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action 'Trigger referral credit for a referred participant' and specifies the exact use case (when trigger is Sign up + Qualifying Action). It distinguishes this from other sibling tools like growsurf_record_sale by referencing the specific trigger condition, making its purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a clear condition for use ('use when your trigger is Sign up + Qualifying Action') and explains the optional delayInDays parameter for refund windows. However, it does not explicitly mention when not to use it or alternative tools for other trigger types (e.g., growsurf_record_sale for purchase triggers), leaving some inference to the agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_troubleshoot_referral_trackingA
Read-onlyIdempotent
Inspect

Call first for a program problem, even without a program or participant ID. It returns initial checks; ask for IDs before reading records. Covers referrals not credited, participant emails not sending, rewards not issued, participants not added, Universal Code not detected, an integration or CRM (HubSpot, Mailchimp, and others) not syncing, Zapier errors, fraud flags, analytics numbers that look wrong, and more. Returns the checks to run in order (with the read tool and field for each), the likely causes most common first, fixes, and doc links. Pass a symptom key; unknown keys return the available symptoms; a description is matched only when it contains a symptom's label or alias verbatim, otherwise the symptom list is returned.

ParametersJSON Schema
NameRequiredDescriptionDefault
symptomNoThe symptom to diagnose. Known keys: `participant_emails_not_sending`, `reward_not_issued`, `referral_not_credited`, `participants_not_added`, `universal_code_not_detected`, `platform_specific_install`, `numbers_do_not_match`. Unknown keys return the symptom list.
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
descriptionNoThe problem in the customer's words, when `symptom` is unknown.
participantIdNoAffected participant id, echoed into participant-level checks.
participantEmailNoAffected participant email, when the id is unknown.

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, and the description adds behavioral context: it returns checks to run, likely causes, fixes, and doc links. It also explains the matching behavior for the description parameter. This goes beyond the annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but front-loaded with the most important instruction ('Call first') and then systematically lists coverage, return content, and parameter behavior. Every sentence adds value, though it is somewhat long; still, no fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (multiple symptoms, optional parameters, output schema), the description is fully complete: it explains what the tool returns, how to supply input, how matching works, and the need to ask for IDs. It covers all the context an agent needs to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All five parameters have schema descriptions (100% coverage), and the description adds meaning beyond the schema: it explains the symptom key behavior, the campaignId default, and how description matching works. This enriches the schema's baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('troubleshoot') and resource ('referral tracking'), then enumerates the exact problem categories it covers, making it unmistakable what the tool does. It clearly distinguishes itself from sibling tools by being the diagnostic entry point.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly instructs to call this tool first for any program problem and explains when to pass a symptom vs a description, and how unknown keys behave. It doesn't name alternative tools or explicitly say when not to use it, but the 'call first' directive is a strong usage rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_update_campaignA
DestructiveIdempotent
Inspect

Update your GrowSurf program's (campaign's) identity and lifecycle: name, companyName, companyLogoImageUrl, and status (set IN_PROGRESS to publish/resume the program, COMPLETE to end it). Only the fields you send are changed. type, urlId, and currencyISO are immutable (currency is chosen once at program creation), so this tool does not accept them. Editor-tab config (design, emails, options, installation) is edited with the dedicated config sub-resource tools, not here. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNo
statusNoLifecycle transition. IN_PROGRESS publishes/resumes the program; COMPLETE ends it. These are the only accepted targets — DRAFT/PENDING/CANCELLED are rejected by the API.
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
companyNameNo
companyLogoImageUrlNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnly=false, destructive=true, idempotent=true), the description adds meaningful behavior: partial-update semantics ('Only the fields you send are changed'), the lifecycle meanings of status values, and targeting behavior (campaignId or GROWSURF_CAMPAIGN_ID). No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is information-dense and every sentence earns its place: scope, update semantics, immutables, sibling routing, and target resolution. Key purpose is front-loaded in the first sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 5-parameter mutation tool with an output schema and annotations, the description covers all operationally relevant aspects: what is updated, what is immutable, what is excluded, and how the target campaign is selected. Nothing an agent needs to call it correctly is left out.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 40%, so the description must compensate, and it does: it groups name/companyName/companyLogoImageUrl as identity fields, explains the status enum semantically, and clarifies campaignId targeting/defaulting. It does not give format constraints for companyLogoImageUrl or name, but the core meaning is conveyed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Update your GrowSurf program's (campaign's) identity and lifecycle', then enumerates the exact mutable fields (name, companyName, companyLogoImageUrl, status). It distinguishes itself from the config-focused sibling tools by explicitly stating that editor-tab configuration is handled by dedicated config sub-resource tools, not this one.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-not guidance: config fields (design, emails, options, installation) should go to dedicated config sub-resource tools. It also specifies lifecycle usage: IN_PROGRESS publishes/resumes, COMPLETE ends, and immutable fields (type, urlId, currencyISO) are not accepted.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_update_campaign_designA
DestructiveIdempotent
Inspect

Update the design configuration for your GrowSurf program, including participant avatars under participantAvatarStyle, referred-visitor content such as the Claim Offer Popup, participant sign-in copy under login, and payout-destination confirmation page copy under payoutDestinationConfirmation. participantAvatarStyle accepts CHARACTERS, INITIALS, ANIMALS, or GRADIENT. Only the fields you send are changed; anything you leave out is untouched (arrays replace wholesale). Fetch the configuration first, preserve starter content unless the user asked to change it, then pass just the fields you want to change under fields. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsYes
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the annotations by explaining partial-update semantics ('Only the fields you send are changed'), array replacement behavior ('arrays replace wholesale'), and the safe workflow of fetching first. This meaningfully clarifies the destructiveHint=true annotation without contradicting it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but efficiently packed: purpose, key field semantics, enum values, update behavior, and campaign targeting are all covered. The first sentence is long, but every clause earns its place, and the most critical behavioral guidance is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the open-ended nested fields object and the presence of an output schema, the description provides everything an agent needs to call correctly: exact field categories, enum choices, partial-update behavior, array-replacement warning, and campaignId targeting. No critical operational detail is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 50% because fields is an open object with no property descriptions. The description compensates by naming important subfields and listing the accepted values for participantAvatarStyle. It also clarifies campaignId default behavior. It does not enumerate every possible subfield, but the 'including' phrasing signals intentional non-exhaustiveness.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description begins with a specific verb and resource: 'Update the design configuration for your GrowSurf program'. It then enumerates concrete design areas (avatars, Claim Offer Popup, login copy, payout confirmation copy), which clearly distinguishes it from sibling tools like growsurf_update_campaign, growsurf_update_campaign_options, and growsurf_update_campaign_emails.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives concrete workflow guidance: fetch the configuration first, preserve starter content unless explicitly changed, and pass only the fields to change. It also explains campaign targeting with the campaignId fallback. It lacks an explicit 'when not to use this vs. alternatives', but the usage context is clear enough for correct selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_update_campaign_emailsA
DestructiveIdempotent
Inspect

Update the Emails tab configuration for your GrowSurf program. Only the fields you send are changed; anything you leave out is untouched (arrays replace wholesale). Pass just the fields you want to change under fields. To see the full object with every field and its current value, fetch the tab first, then send back only what you want to change. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsYes
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveHint=true and readOnlyHint=false, but the description adds crucial behavioral context: partial update semantics ('only the fields you send are changed; anything you leave out is untouched'), array wholesale replacement, and the pattern of fetching first to see current fields. It also states that campaignId defaults to GROWSURF_CAMPAIGN_ID. No contradiction with annotations found.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a compact 4-sentence block with no filler. Each sentence has a distinct purpose: stating the action, explaining update semantics, advising a fetch-first pattern, and clarifying the campaignId default. Information is front-loaded—purpose first, then critical behavioral rules, then targeting. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with an output schema and annotations, the description covers everything an agent needs to call it correctly: what it updates, how partial updates work, how to get current values, and how to target a specific campaign. It doesn't explain return values, but the output schema presumably handles that. The description is complete enough for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 50% (only campaignId has a description; fields is just 'type object'). The description compensates by explaining that 'fields' is the update payload, with partial update semantics and array replacement behavior. It also clarifies campaignId's default and that it overrides the environment default. This adds meaning beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Update') and a specific resource ('the Emails tab configuration for your GrowSurf program'). It distinguishes this from sibling tools like growsurf_update_campaign_options or growsurf_update_campaign_design by naming the tab it targets. The sentence 'Targets `campaignId` if you pass it, otherwise GROWSURF_CAMPAIGN_ID' further clarifies scope, so an agent can immediately differentiate it from other update tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly explains how to use the tool: 'Only the fields you send are changed; anything you leave out is untouched (arrays replace wholesale).' It advises fetching the tab first to see the full object, and explains the campaignId target and default. While it doesn't explicitly compare to siblings or state when not to use it, the partial-update semantics and fetch-first pattern are strong usage guidance that goes beyond the schema.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_update_campaign_installationA
DestructiveIdempotent
Inspect

Update the Installation tab configuration for your GrowSurf program. Only the fields you send are changed; anything you leave out is untouched (arrays replace wholesale). To let GrowSurf run on another origin, such as http://localhost:3000, add that origin to allowedUrls and preserve the rest of the array; a browser origin missing from both shareUrl and allowedUrls can return 403. Leave shareUrl out of the patch unless the customer asked for a different landing page: every referral link already shared points at the current one. A patch that would replace a Share URL that is already set is refused until you confirm it with the customer and resend with replaceExistingShareUrl: true. Fetch the tab first, then pass just the fields you want to change under fields. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsYesInstallation fields to patch. Common keys include `shareUrl`, `allowedUrls`, `signupEvent`, `referralTrigger`, and `signup`. Arrays replace wholesale.
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
replaceExistingShareUrlNoSet this to `true` only after the customer confirms they want a different landing page. Without it, a patch that would replace a Share URL that is already set is refused.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark destructiveHint=true and idempotentHint=true, and the description significantly extends this: it spells out partial patch semantics, wholesale array replacement, the 403 risk for origins missing from allowedUrls/shareUrl, and the refusal behavior for replacing an existing shareUrl. This is rich behavioral disclosure that goes well beyond the structured data and never contradicts it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than average, but each sentence introduces a necessary nuance around patch semantics, allowedOrigins, shareUrl, and the confirm flag. It is front-loaded with the purpose and reads in a natural cause-and-effect order. A sentence or two could be tightened, but the length is justified by the risk profile.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has an output schema and high schema coverage, the description covers all high-risk operational aspects: array replacement, 403 behavior, shareUrl safety, partial patch behavior, and campaign targeting. There is nothing critical an agent needs to know for safe invocation that is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although the input schema is fully described, the function description adds meaning: it clarifies that fields is a partial-patch payload, allowedUrls must be sent as a full array, shareUrl replacement is blocked unless replaceExistingShareUrl is true, and campaignId overrides GROWSURF_CAMPAIGN_ID. This is substantial additional semantics that helps an agent use the parameters correctly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Update the Installation tab configuration for your GrowSurf program.' This clearly distinguishes it from siblings like growsurf_update_campaign, growsurf_update_campaign_design, and other update-* tools, which target different configuration surfaces. The scope is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives strong procedural guidance: fetch the tab first, patch only changed fields, and preserve array contents. It explains when to avoid touching shareUrl and when to set replaceExistingShareUrl. It doesn't literally name alternative sibling tools for exclusion, but the 'Installation tab' framing, plus the 'fetch first' step, makes the usage context very clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_update_campaign_optionsA
DestructiveIdempotent
Inspect

Update the Options tab configuration for your GrowSurf program. Only the fields you send are changed; anything you leave out is untouched (arrays replace wholesale). Pass just the fields you want to change under fields. To see the full object with every field and its current value, fetch the tab first, then send back only what you want to change. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsYes
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses partial update semantics ('Only the fields you send are changed; anything you leave out is untouched') and array replacement behavior, adding significant value beyond the annotations. Annotations already flag destructive and idempotent, so the description's extra detail on per-field behavior is important and not contradictory.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded: it states the core action, then the critical partial-update behavior, then a recommended workflow, then the campaignId targeting. Every sentence adds necessary information without fluff, and it is well-structured for quick comprehension.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given an output schema exists, the description doesn't need to explain return values. It covers all essential aspects for correct invocation: purpose, partial update semantics, safe usage workflow, and parameter targeting. For a two-parameter tool, this is complete and sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema only describes campaignId (coverage 50%), while the description explains that `fields` is the container for the specific fields to change and clarifies campaignId's default and purpose. This compensates fully for the missing schema description of `fields`, giving clear meaning to both parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it updates the Options tab configuration for a GrowSurf program, distinguishing it from sibling tools like update_campaign and get_campaign_options. The verb 'Update' and resource 'Options tab configuration' are specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidance: fetch the full object first, then send only the fields you want to change. Also clarifies that campaignId defaults to GROWSURF_CAMPAIGN_ID. This tells the agent exactly when and how to use the tool, and how to avoid unintended overwrites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_update_campaign_rewardA
DestructiveIdempotent
Inspect

Update an existing campaign reward (reward config) on your GrowSurf program. campaignRewardId is the reward key (e.g. crew_...). The reward type is immutable. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
eventNoThe referral event that earns this Campaign Reward. Use `LEAD` for a referred signup or `CONVERSION` for a qualifying action. A `LEAD` reward requires a later custom conversion trigger. Referral reward types only.
limitNo
orderNo
titleNo
valueNoTax valuation for the reward (the referrer's side of a double-sided reward). `fairMarketValueUSD` is the manual fair-market value in USD (major units). `taxCharacter` is the reason the recipient earns the reward. For configurable non-commission rewards, `null` inherits the program's confirmed treatment. Commission rewards always use `NONEMPLOYEE_SERVICES`.
imageUrlNo
metadataNo
isVisibleNo
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
couponCodeNo
descriptionNo
isUnlimitedNo
limitDurationNo
referredValueNoTax valuation for the referred friend's side of a double-sided reward. `taxCharacter` is the reason the recipient earns the reward. For configurable non-commission rewards, `null` inherits the program's confirmed treatment. Commission rewards have no referred-friend side, so GrowSurf clears these settings. Use `PURCHASE_REBATE` only when that is the correct tax character.
numberOfWinnersNo
campaignRewardIdYes
referralCouponCodeNo
commissionStructureNoAffiliate commission structure (AFFILIATE rewards only). Provide a positive `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission. CLICK and LEAD commissions must use FIXED.
conversionsRequiredNo
nextMilestonePrefixNo
nextMilestoneSuffixNo
referralDescriptionNo
referredRewardUpfrontNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses two important behaviors beyond what annotations provide: the reward `type` is immutable, and the call targets `campaignId` with a GROWSURF_CAMPAIGN_ID default. Since annotations already flag this as destructive and idempotent, these additions are meaningful but do not contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences carry all the key information with no fluff: the action and resource, the identifier meaning, the immutability constraint, and the targeting default. The most important facts are front-loaded, and every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's high complexity (23 parameters, nested objects, enums, conditional constraints), the description is far too short to guide correct invocation. It does not explain partial update semantics, whether omitted fields are preserved, or how the many optional fields interact. The output schema covers return values, but the input side remains under-specified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 22%, and the description compensates for only two parameters: `campaignRewardId` and `campaignId`. The remaining 21 parameters, including nested objects like `value`, `referredValue`, and `commissionStructure`, receive no additional semantic guidance in the description, leaving agents to rely on an under-documented schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Update an existing campaign reward (reward config)'. The qualifier 'existing' clearly distinguishes it from create/delete siblings, and the target resource is unambiguous. The statement that `campaignRewardId` is the reward key adds further precision.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for updating an existing reward, but it does not explicitly state when to choose this tool over growsurf_create_campaign_reward or growsurf_delete_campaign_reward. It also omits any discussion of prerequisites or conditions that would route an agent to an alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_update_campaign_webhookA
DestructiveIdempotent
Inspect

Update a webhook on your GrowSurf program by id (webhookId is primary for the program's primary webhook). Only the fields you send are changed. secret is write-only and never returned. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
eventsNo
secretNoWrite-only.
isEnabledNo
webhookIdYes
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
payloadUrlNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate write, idempotent, and destructive hints. The description adds valuable behavioral context: partial updates, write-only secret never returned, and the campaignId fallback logic. These go beyond the annotations and help the agent understand side effects and security semantics. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences, front-loaded with the core action, and each sentence adds unique value (identification, partial update, write-only secret, targeting). No redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the key nuances: primary webhook, partial update semantics, write-only secret, and campaign targeting. With an output schema present, return values are handled. Minor gaps remain around the specific meaning of payloadUrl and events values, but these are fairly self-explanatory from the schema enums and naming. Overall, it's sufficiently complete for an update tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 33% (secret and campaignId have descriptions). The description adds meaning for webhookId ('primary' for the primary webhook) and campaignId (targeting behavior). However, payloadUrl, events, and isEnabled are not elaborated beyond their names. Given the low coverage, the description should compensate more for these parameters but only partially does.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Update a webhook'), the resource (GrowSurf program webhook), and the identifier (by id). It also distinguishes the primary webhook with a special id. This is a specific verb+resource that differentiates it from sibling tools like create, delete, list, and test webhooks.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for modifying an existing webhook and explains partial update behavior ('Only the fields you send are changed'), which guides when to use this vs recreating. It also clarifies campaign targeting with campaignId vs the default GROWSURF_CAMPAIGN_ID. However, it doesn't explicitly state when not to use it or mention alternatives like create_campaign_webhook.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_update_participantA
DestructiveIdempotent
Inspect

Update a participant by GrowSurf participant ID or email. Only the fields you send are changed; read-only fields such as counters, isAffiliate, origin, and fraud state are rejected with a 400. In affiliate programs, affiliateStatus accepts APPROVED, SUSPENDED, or BANNED; APPROVED enrolls the participant, while SUSPENDED and BANNED require an existing affiliate. Affiliate enrollment cannot be removed through REST. notes is freeform internal notes (never shown to participants). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
emailNoChange the participant's email address.
notesNoFreeform internal notes (internal only, never exposed to participants).
lastNameNo
metadataNo
firstNameNo
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
referredByNo
vanityKeysNo
unsubscribedNo
participantIdNo
referralStatusNo
affiliateStatusNoAffiliate programs only. Sets the affiliate status. `APPROVED` also enrolls a participant who is not yet an affiliate. `SUSPENDED` and `BANNED` are rejected for non-affiliates.
participantEmailNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses multiple behavioral details beyond annotations: read-only fields are rejected with 400, affiliateStatus has specific enrollment rules and limitations (cannot remove enrollment via REST), notes are internal-only, and campaignId targeting follows a default. This is consistent with annotations (destructiveHint true, idempotentHint true) and adds value for agents deciding whether to call the tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise yet comprehensive: it front-loads the core action, then systematically covers constraints, affiliate-specific logic, notes, and campaign targeting. Every sentence contributes essential information without fluff or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 13 parameters and given the existing output schema and annotations, the description covers the most operationally critical behaviors (partial updates, read-only rejection, affiliate status rules, campaign targeting). Missing parameter explanations (e.g., referredBy, vanityKeys) are minor because the output schema and existing docs might cover them, but the description could be more exhaustive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 31%, so the description compensates by explaining critical parameters: affiliateStatus (enum values and enrollment implications), notes (freeform and internal), campaignId (default and usage), and the identification fields (participantId/participantEmail). However, some parameters like referredBy, vanityKeys, and unsubscribed lack description in both schema and description, leaving gaps for those.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Update') and resource ('a participant') with clear identification methods (GrowSurf participant ID or email). It clearly differentiates from siblings like growsurf_get_participant (read) and growsurf_add_participant (create) by focusing on modifying existing participants.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clarifies partial-update behavior ('Only the fields you send are changed') and the campaign targeting fallback, giving an agent clear context for when to invoke this tool. However, it does not explicitly state when not to use it (e.g., 'use add_participant for creation') or name alternatives, though the purpose is clear enough to infer usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_update_program_resourceA
DestructiveIdempotent
Inspect

Update at least one participant resource field, or move it to a zero-based position. Only sent fields change. To replace a FILE, call growsurf_prepare_program_resource_file first and pass its uploadTicket and uploadResult unchanged. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoUsed with `LINK`.
textNoUsed with `TEXT`.
typeNo
titleNo
categoryNo
positionNo
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server.
resourceIdYes
descriptionNo
isPublishedNo
uploadResultNoThe unmodified result returned by the secure upload flow for a replacement `FILE`.
uploadTicketNoThe one-time upload ticket for a replacement `FILE`.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false, destructiveHint=true, idempotentHint=true. The description adds meaningful behavioral context: only sent fields change (partial update semantics), FILE replacement requires a two-step flow with a one-time upload ticket, and campaignId targeting falls back to GROWSURF_CAMPAIGN_ID. It doesn't explicitly warn about destructive consequences, but the annotations already carry destructiveHint=true. The description adds value beyond annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each dense with useful information: the core action, the FILE replacement prerequisite, and the campaignId targeting rule. No filler, no repetition of schema details. Front-loaded with the primary purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has 12 parameters, nested objects, an output schema, and complex conditional constraints. The description covers the critical workflow (FILE replacement), the partial-update semantics, and the campaign targeting fallback. It doesn't enumerate all field constraints, but the schema already does that. The main gap is that it doesn't mention the output schema or what the response contains, but the output schema exists and the description needn't explain return values. Overall, complete enough for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 42%, so the description must compensate for undocumented parameters. It explains the FILE replacement flow (uploadTicket/uploadResult), the position field, and the campaignId fallback. It also clarifies that url is for LINK and text is for TEXT, which the schema already states. It doesn't explain title, description, category, isPublished, or resourceId semantics, but those are fairly self-evident from their names. The description adds meaningful semantics for the trickiest parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool updates participant resource fields or moves a resource to a zero-based position, and it explicitly names the prerequisite for replacing a FILE (calling growsurf_prepare_program_resource_file). It distinguishes itself from create/delete/list resource siblings by focusing on update semantics. However, it doesn't explicitly contrast with growsurf_create_program_resource or growsurf_delete_program_resource, so it's clear but not fully differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance: 'Update at least one participant resource field, or move it to a zero-based position.' It also provides a critical alternative workflow: to replace a FILE, call growsurf_prepare_program_resource_file first and pass its uploadTicket and uploadResult unchanged. It also explains the campaignId targeting fallback to GROWSURF_CAMPAIGN_ID. This is strong usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_update_teamA
DestructiveIdempotent
Inspect

Update the display name of the team bound to the API key or OAuth connection. Personal profiles, billing, and team ownership are not editable here. Requires GROWSURF_API_KEY; does not require GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesThe team's display name.

Output Schema

ParametersJSON Schema
NameRequiredDescription
nameNoThe team's display name.
verificationStatusNoTeam verification state. `VERIFIED` is required before a program can send participant emails.
verificationRequestedAtNoWhen verification was last requested, as a Unix timestamp in milliseconds.

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate a mutating operation (readOnlyHint: false) and destructiveHint: true. The description adds the auth requirement (GROWSURF_API_KEY) and the scope constraint, but doesn't discuss side effects beyond the name update. Since annotations cover the core mutating nature, the added value is moderate, so a 3 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the action, followed by exclusions and auth requirement. No redundant phrasing; every clause adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a single parameter, an output schema present, and annotations covering mutability, the description covers the essential action, scope limitations, and environmental requirements. The agent has all information needed to call it correctly without further inference.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% coverage for the single parameter 'name', including type and length constraints. The description does not add any extra meaning beyond what the schema provides, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('update') and resource ('display name of the team'), and clarifies scope by listing non-editable attributes (personal profiles, billing, team ownership). This clearly distinguishes it from other tools like growsurf_get_team or growsurf_update_campaign.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit boundaries by stating what cannot be edited here, implying when not to use this tool. It also notes that it requires GROWSURF_API_KEY but not GROWSURF_CAMPAIGN_ID, which helps the agent know the prerequisites. While it doesn't name alternative tools for other team edits, the exclusions effectively guide the agent away from using it for those cases.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

growsurf_webhook_normalizeA
Read-onlyIdempotent
Inspect

Validate/normalize a GrowSurf webhook payload and generate a best-effort idempotency key for dedupe.

ParametersJSON Schema
NameRequiredDescriptionDefault
payloadYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okNoWhether the payload is a valid GrowSurf webhook envelope.
errorNoWhy the payload failed validation. Present only when `ok` is `false`.
envelopeNoThe normalized webhook envelope. Present only when `ok` is `true`.
idempotencyKeyNoA deterministic key for ignoring duplicate deliveries. Present only when `ok` is `true`.

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true, idempotentHint=true, and destructiveHint=false, and the description aligns with these. It adds nuance by mentioning 'best-effort' idempotency key and the purpose 'for dedupe', which clarifies behavior beyond the annotations. This is useful extra context without contradicting the structured metadata.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single concise sentence that front-loads the core action and purpose. It contains no filler or redundant phrases, and every word adds value, making it easy to parse at a glance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool that validates and normalizes payloads, the description omits details about expected input structure, possible error conditions, or the format of the generated idempotency key. Though an output schema exists, we cannot verify whether it covers these details; the description alone leaves significant gaps for correct invocation and result interpretation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has zero description coverage for the single 'payload' parameter, and the description only says 'GrowSurf webhook payload', giving no indication of expected structure, required fields, or format. Since the description is the only source of meaning for the parameter and it is extremely vague, it fails to compensate for the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb ('Validate/normalize') and a specific resource ('a GrowSurf webhook payload'), plus a concrete outcome (generating an idempotency key for dedupe). This distinguishes it from sibling tools that manage webhooks (create/update/delete/test) and other campaign operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage 'when you have a GrowSurf webhook payload to preprocess', but it does not explicitly contrast with alternatives like creating or testing webhooks, nor does it state when not to use it. The context is clear but lacks exclusions or direct comparisons to siblings, leaving some ambiguity for an agent deciding among webhook-related tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 27 tool updatesv0.14.0
    • Changedgrowsurf_create_campaign2 fields changed
      • addedInput schema / properties / goal
        Added value: +{
        +  "description": "What the program is for, which seeds share settings that suit that audience. Programs selling to businesses (`CUSTOMERS`, `USERS`, `B2B_SAAS_SELF_SERVICE`, `B2B_SAAS_ENTERPRISE`) start with the LinkedIn share button visible. Consumer, financial, education, insurance, newsletter, and waitlist programs (`B2C_SUBSCRIPTIONS`, `FINANCIAL_SERVICES`, `ONLINE_EDUCATION`, `ONLINE_INSURANCE`, `SUBSCRIBERS`, `WAITLIST`) start with it hidden. Omit `goal` and every share button keeps its standard default. Change any of it afterward with `growsurf_update_campaign_design`. Set only at creation; `growsurf_update_campaign` does not accept it.",
        +  "enum": [
        +    "CUSTOMERS",
        +    "USERS",
        +    "SUBSCRIBERS",
        +    "WAITLIST",
        +    "B2B_SAAS_SELF_SERVICE",
        +    "B2B_SAAS_ENTERPRISE",
        +    "B2C_SUBSCRIPTIONS",
        +    "FINANCIAL_SERVICES",
        +    "ONLINE_EDUCATION",
        +    "ONLINE_INSURANCE"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / rewards / description
        Added value: +"Rewards to create with the program. Include this only when the person told you the amount and who funds it. Omit it and the program is seeded with starter rewards that are switched off, awarding nothing until the customer enables one. Send `[]` to start with no rewards at all."
    • Changedgrowsurf_create_campaign_reward5 fields changed
      • addedInput schema / properties / commissionStructure / allOf
        Added value: +[
        +  {
        +    "if": {
        +      "properties": {
        +        "event": {
        +          "enum": [
        +            "CLICK",
        +            "LEAD"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "event"
        +      ]
        +    },
        +    "then": {
        +      "properties": {
        +        "amount": {
        +          "minimum": 1,
        +          "type": "integer"
        +        },
        +        "type": {
        +          "enum": [
        +            "FIXED"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "amount"
        +      ]
        +    }
        +  }
        +]
      • changedInput schema / properties / commissionStructure / description
        Previous value: -"Affiliate commission structure (AFFILIATE rewards only). Provide `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission."New value: +"Affiliate commission structure (AFFILIATE rewards only). Provide a positive `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission. CLICK and LEAD commissions must use FIXED."
      • addedInput schema / properties / commissionStructure / properties / amount / minimum
        Added value: +1
      • addedInput schema / properties / commissionStructure / properties / event / description
        Added value: +"The affiliate event that earns the commission. `CLICK` and `LEAD` must use `FIXED`."
      • addedInput schema / properties / event
        Added value: +{
        +  "description": "The referral event that earns this Campaign Reward. Use `LEAD` for a referred signup or `CONVERSION` for a qualifying action. A `LEAD` reward requires a later custom conversion trigger. Referral reward types only.",
        +  "enum": [
        +    "LEAD",
        +    "CONVERSION"
        +  ],
        +  "type": "string"
        +}
    • Addedgrowsurf_create_program_resource
    • Addedgrowsurf_delete_program_resource
    • Changedgrowsurf_get_campaign1 field changed
      • addedOutput schema / properties / rewardEvidence
        Added value: +{
        +  "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.",
        +  "properties": {
        +    "approvalPolicy": {
        +      "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.",
        +      "enum": [
        +        "manual",
        +        "automatic",
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "automaticFulfillmentMarking": {
        +      "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.",
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "basis": {
        +      "enum": [
        +        "this_response_only"
        +      ],
        +      "type": "string"
        +    },
        +    "conclusion": {
        +      "type": "string"
        +    },
        +    "deliveryStatus": {
        +      "enum": [
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "integrationConnection": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    },
        +    "nextStep": {
        +      "type": "string"
        +    },
        +    "programReferralTrigger": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Addedgrowsurf_get_campaign_activation_analytics
    • Changedgrowsurf_get_campaign_analytics4 fields changed
      • changedInput schema / properties / include / description
        Previous value: -"Comma-separated optional data: `previousPeriod`, `statusCounts`, `rates`, and `email`. Combine `email` with `previousPeriod` or a non-total `interval` to receive matching email metrics for those windows."New value: +"Comma-separated optional data: `previousPeriod`, `statusCounts`, `rates`, `email`, and `engagement`. Combine values when the question needs more than one view."
      • addedInput schema / properties / platform
        Added value: +{
        +  "description": "Client-platform filter for engagement. Defaults to `ALL`.",
        +  "enum": [
        +    "ALL",
        +    "WEB",
        +    "IOS",
        +    "ANDROID"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / timezone
        Added value: +{
        +  "description": "IANA timezone for engagement interval and distinct-day calculations. Used with `include=engagement`.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / engagement
        Added value: +{
        +  "description": "Opt-in participant engagement grouped by when activity occurred.",
        +  "properties": {
        +    "breakdowns": {
        +      "description": "Engagement grouped by platform, portal source, and share channel.",
        +      "properties": {
        +        "firstShareChannels": {
        +          "items": {
        +            "properties": {
        +              "key": {
        +                "description": "Stable first-share channel key.",
        +                "type": "string"
        +              },
        +              "sharingParticipants": {
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "platforms": {
        +          "items": {
        +            "properties": {
        +              "activeParticipants": {
        +                "type": "integer"
        +              },
        +              "key": {
        +                "enum": [
        +                  "WEB",
        +                  "IOS",
        +                  "ANDROID"
        +                ],
        +                "type": "string"
        +              },
        +              "portalViews": {
        +                "type": "integer"
        +              },
        +              "shareActions": {
        +                "type": "integer"
        +              },
        +              "sharingParticipants": {
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "portalViewSources": {
        +          "items": {
        +            "properties": {
        +              "activeParticipants": {
        +                "type": "integer"
        +              },
        +              "key": {
        +                "enum": [
        +                  "DEFAULT_LAUNCHER",
        +                  "SDK_OPEN",
        +                  "CSS_CLASS",
        +                  "EMBEDDABLE_ELEMENT",
        +                  "HOSTED_PORTAL",
        +                  "NATIVE_WINDOW",
        +                  "UNKNOWN"
        +                ],
        +                "type": "string"
        +              },
        +              "portalViews": {
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "shareChannels": {
        +          "items": {
        +            "properties": {
        +              "key": {
        +                "description": "Stable share-channel key.",
        +                "type": "string"
        +              },
        +              "shareActions": {
        +                "type": "integer"
        +              },
        +              "sharingParticipants": {
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "comparison": {
        +      "description": "Current-versus-previous engagement changes.",
        +      "properties": {
        +        "metrics": {
        +          "properties": {
        +            "activeParticipants": {
        +              "description": "Change in unique active participants.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "portalViews": {
        +              "description": "Change in total signed-in portal views.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "repeatActiveParticipants": {
        +              "description": "Change in repeat active participants.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "repeatSharingParticipants": {
        +              "description": "Change in repeat sharing participants.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "shareActions": {
        +              "description": "Change in total accepted share actions.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "sharingParticipants": {
        +              "description": "Change in unique sharing participants.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            }
        +          },
        +          "type": [
        +            "object",
        +            "null"
        +          ]
        +        },
        +        "reason": {
        +          "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +          "enum": [
        +            "COVERAGE_UNAVAILABLE",
        +            "PRE_COVERAGE",
        +            "PARTIAL_COVERAGE",
        +            "INSUFFICIENT_COVERAGE",
        +            "EMPTY_DENOMINATOR",
        +            "QUERY_LIMIT_EXCEEDED",
        +            "PARTICIPANT_NOT_ELIGIBLE",
        +            null
        +          ],
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "state": {
        +          "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +          "enum": [
        +            "AVAILABLE",
        +            "PARTIAL",
        +            "UNAVAILABLE"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "coverageStartAt": {
        +      "description": "Earliest expected complete capture time (Unix ms), or `null` until coverage begins.",
        +      "type": [
        +        "integer",
        +        "null"
        +      ]
        +    },
        +    "interval": {
        +      "description": "Bucket size used for `series`.",
        +      "enum": [
        +        "day",
        +        "week",
        +        "month"
        +      ],
        +      "type": "string"
        +    },
        +    "metricContractVersion": {
        +      "description": "Shared activation and engagement metric version.",
        +      "type": "integer"
        +    },
        +    "period": {
        +      "description": "Exact half-open current and previous activity bounds.",
        +      "properties": {
        +        "effectiveFrom": {
        +          "description": "Measured start after coverage, or `null`.",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "from": {
        +          "description": "Inclusive requested activity start (Unix ms).",
        +          "type": "integer"
        +        },
        +        "previousFrom": {
        +          "description": "Inclusive previous-period start (Unix ms).",
        +          "type": "integer"
        +        },
        +        "previousTo": {
        +          "description": "Exclusive previous-period end (Unix ms).",
        +          "type": "integer"
        +        },
        +        "to": {
        +          "description": "Exclusive requested activity end (Unix ms).",
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "platform": {
        +      "description": "Requested and applied client-platform filter.",
        +      "properties": {
        +        "applied": {
        +          "enum": [
        +            "ALL",
        +            "WEB",
        +            "IOS",
        +            "ANDROID"
        +          ],
        +          "type": "string"
        +        },
        +        "requested": {
        +          "enum": [
        +            "ALL",
        +            "WEB",
        +            "IOS",
        +            "ANDROID"
        +          ],
        +          "type": "string"
        +        },
        +        "state": {
        +          "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +          "enum": [
        +            "AVAILABLE",
        +            "PARTIAL",
        +            "UNAVAILABLE"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "previousPeriod": {
        +      "description": "Engagement totals for the immediately previous equal activity period.",
        +      "properties": {
        +        "reason": {
        +          "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +          "enum": [
        +            "COVERAGE_UNAVAILABLE",
        +            "PRE_COVERAGE",
        +            "PARTIAL_COVERAGE",
        +            "INSUFFICIENT_COVERAGE",
        +            "EMPTY_DENOMINATOR",
        +            "QUERY_LIMIT_EXCEEDED",
        +            "PARTICIPANT_NOT_ELIGIBLE",
        +            null
        +          ],
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "state": {
        +          "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +          "enum": [
        +            "AVAILABLE",
        +            "PARTIAL",
        +            "UNAVAILABLE"
        +          ],
        +          "type": "string"
        +        },
        +        "totals": {
        +          "description": "Unique participant metrics and action totals for one activity period.",
        +          "properties": {
        +            "activeParticipants": {
        +              "description": "Eligible participants with a signed-in portal view.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "portalViews": {
        +              "description": "Total accepted signed-in portal-view actions.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "repeatActiveParticipants": {
        +              "description": "Eligible participants active on at least two distinct program-local days.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "repeatSharingParticipants": {
        +              "description": "Eligible participants who shared on at least two distinct program-local days.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "retainedActiveParticipants": {
        +              "description": "Eligible participants active in both the current and previous equal periods.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "shareActions": {
        +              "description": "Total accepted referral-link share actions.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "sharingParticipants": {
        +              "description": "Eligible participants with an accepted share action.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "sharingRate": {
        +              "description": "Sharing participants divided by active participants.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            }
        +          },
        +          "type": [
        +            "object",
        +            "null"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "programType": {
        +      "description": "Program eligibility model.",
        +      "enum": [
        +        "REFERRAL",
        +        "AFFILIATE"
        +      ],
        +      "type": "string"
        +    },
        +    "reason": {
        +      "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +      "enum": [
        +        "COVERAGE_UNAVAILABLE",
        +        "PRE_COVERAGE",
        +        "PARTIAL_COVERAGE",
        +        "INSUFFICIENT_COVERAGE",
        +        "EMPTY_DENOMINATOR",
        +        "QUERY_LIMIT_EXCEEDED",
        +        "PARTICIPANT_NOT_ELIGIBLE",
        +        null
        +      ],
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "series": {
        +      "description": "Continuous half-open activity intervals in ascending order.",
        +      "items": {
        +        "properties": {
        +          "activeParticipants": {
        +            "description": "Unique active participants.",
        +            "type": "integer"
        +          },
        +          "from": {
        +            "description": "Inclusive interval start (Unix ms).",
        +            "type": "integer"
        +          },
        +          "portalViews": {
        +            "description": "Total signed-in portal views.",
        +            "type": "integer"
        +          },
        +          "shareActions": {
        +            "description": "Total accepted share actions.",
        +            "type": "integer"
        +          },
        +          "sharingParticipants": {
        +            "description": "Unique sharing participants.",
        +            "type": "integer"
        +          },
        +          "to": {
        +            "description": "Exclusive interval end (Unix ms).",
        +            "type": "integer"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "state": {
        +      "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +      "enum": [
        +        "AVAILABLE",
        +        "PARTIAL",
        +        "UNAVAILABLE"
        +      ],
        +      "type": "string"
        +    },
        +    "timezone": {
        +      "description": "IANA timezone used for interval and distinct-day calculations.",
        +      "type": "string"
        +    },
        +    "totals": {
        +      "description": "Unique participant metrics and action totals for one activity period.",
        +      "properties": {
        +        "activeParticipants": {
        +          "description": "Eligible participants with a signed-in portal view.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "portalViews": {
        +          "description": "Total accepted signed-in portal-view actions.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "repeatActiveParticipants": {
        +          "description": "Eligible participants active on at least two distinct program-local days.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "repeatSharingParticipants": {
        +          "description": "Eligible participants who shared on at least two distinct program-local days.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "retainedActiveParticipants": {
        +          "description": "Eligible participants active in both the current and previous equal periods.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "shareActions": {
        +          "description": "Total accepted referral-link share actions.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "sharingParticipants": {
        +          "description": "Eligible participants with an accepted share action.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "sharingRate": {
        +          "description": "Sharing participants divided by active participants.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        }
        +      },
        +      "type": "object"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedgrowsurf_get_campaign_design5 fields changed
      • addedOutput schema / properties / participantAvatarStyle
        Added value: +{
        +  "description": "How participant avatars appear in the GrowSurf Window. New programs use `CHARACTERS`; missing or unknown stored values return `INITIALS`.",
        +  "enum": [
        +    "CHARACTERS",
        +    "INITIALS",
        +    "ANIMALS",
        +    "GRADIENT"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / properties / referredExperience / description
        Previous value: -"The banner and headline shown to a visitor who arrives through a referral link."New value: +"The banner, headline, and Claim Offer Popup shown to a visitor who arrives through a referral link. The popup is available for referral and affiliate programs."
      • addedOutput schema / properties / referredExperience / properties
        Added value: +{
        +  "isOfferPopupConfettiEnabled": {
        +    "description": "Whether to show confetti after a claim.",
        +    "type": "boolean"
        +  },
        +  "isOfferPopupEnabled": {
        +    "description": "Whether referred visitors see the Claim Offer Popup.",
        +    "type": "boolean"
        +  },
        +  "isOfferPopupOverlayDimmed": {
        +    "description": "Whether a centered popup dims the page behind it.",
        +    "type": "boolean"
        +  },
        +  "isOfferPopupReferrerImageShown": {
        +    "description": "Whether to show the referrer's profile image.",
        +    "type": "boolean"
        +  },
        +  "isOfferPopupShownOnAllPages": {
        +    "description": "Whether the popup can appear on every installed page.",
        +    "type": "boolean"
        +  },
        +  "offerPopupButtonText": {
        +    "description": "Offer-save button text.",
        +    "maxLength": 100,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "offerPopupDelaySeconds": {
        +    "description": "Delay before the popup appears.",
        +    "enum": [
        +      0,
        +      3,
        +      5,
        +      10
        +    ],
        +    "type": "integer"
        +  },
        +  "offerPopupDescription": {
        +    "description": "Text below the popup heading.",
        +    "maxLength": 255,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "offerPopupImageUrl": {
        +    "description": "Optional popup image.",
        +    "maxLength": 500,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "offerPopupPlacement": {
        +    "description": "Where the popup appears.",
        +    "enum": [
        +      "CENTER",
        +      "BOTTOM",
        +      "BOTTOM_RIGHT",
        +      "BOTTOM_LEFT",
        +      "TOP"
        +    ],
        +    "type": "string"
        +  },
        +  "offerPopupSecondaryLinkText": {
        +    "description": "Optional post-claim link text.",
        +    "maxLength": 100,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "offerPopupSecondaryLinkUrl": {
        +    "description": "Optional post-claim link destination. When saving, use `http://` or `https://`. Send `null` or an empty string to clear it.",
        +    "maxLength": 255,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "offerPopupThankYouButtonText": {
        +    "description": "Post-claim signup button text.",
        +    "maxLength": 100,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "offerPopupThankYouText": {
        +    "description": "Message shown after the offer is saved.",
        +    "maxLength": 255,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "offerPopupTitle": {
        +    "description": "Popup heading.",
        +    "maxLength": 255,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  }
        +}
      • addedOutput schema / properties / resources
        Added value: +{
        +  "description": "Participant Resources presentation settings: visibility, title, link and copy labels, the message shown when nothing is published, and the section icon. Resource items use the program Resource tools.",
        +  "type": "object"
        +}
      • addedOutput schema / properties / theme / properties
        Added value: +{
        +  "referredExperienceOfferPopup": {
        +    "description": "Paid-plan color settings for the Claim Offer Popup.",
        +    "properties": {
        +      "backgroundColor": {
        +        "description": "Popup background color.",
        +        "maxLength": 255,
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "color": {
        +        "description": "Popup text color.",
        +        "maxLength": 255,
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "type": "object"
        +  }
        +}
    • Changedgrowsurf_get_campaign_emails1 field changed
      • addedOutput schema / properties / offerClaimed
        Added value: +{
        +  "description": "Sent when a referred visitor saves an offer through the Claim Offer Popup. Referral and affiliate programs. Promotional; its toggle can be changed.",
        +  "type": "object"
        +}
    • Changedgrowsurf_get_campaign_options2 fields changed
      • changedOutput schema / properties / autoFulfillRewards / description
        Previous value: -"Referral programs only. Automatically mark earned rewards as fulfilled."New value: +"Referral programs only. Automatically mark earned rewards as fulfilled. `false` permits manual fulfillment and does not establish a delivery failure."
      • addedOutput schema / properties / rewardEvidence
        Added value: +{
        +  "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.",
        +  "properties": {
        +    "approvalPolicy": {
        +      "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.",
        +      "enum": [
        +        "manual",
        +        "automatic",
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "automaticFulfillmentMarking": {
        +      "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.",
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "basis": {
        +      "enum": [
        +        "this_response_only"
        +      ],
        +      "type": "string"
        +    },
        +    "conclusion": {
        +      "type": "string"
        +    },
        +    "deliveryStatus": {
        +      "enum": [
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "integrationConnection": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    },
        +    "nextStep": {
        +      "type": "string"
        +    },
        +    "programReferralTrigger": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedgrowsurf_get_integration_connect_link5 fields changed
      • changedInput schema / properties / integration / enum
        Previous value: -[
        -  "stripe",
        -  "chargebee",
        -  "recurly",
        -  "paypal",
        -  "wisecom",
        -  "tangocard",
        -  "hubspot",
        -  "salesforce",
        -  "marketo",
        -  "mailchimp",
        -  "activecampaign",
        -  "bentonow",
        -  "mailerlite",
        -  "resenddotcom",
        -  "loopsdotso",
        -  "convertkit",
        -  "constantContact",
        -  "campaignMonitor",
        -  "aweber",
        -  "klaviyo",
        -  "mailjet",
        -  "sendgrid",
        -  "sendinblue",
        -  "emailoctopus",
        -  "customerio",
        -  "getresponse",
        -  "drip",
        -  "googleanalytics",
        -  "segmentanalytics",
        -  "posthoganalytics",
        -  "mixpanelanalytics",
        -  "pendo",
        -  "fullstory",
        -  "heapanalytics",
        -  "amplitude",
        -  "googleads",
        -  "metaads",
        -  "linkedinads",
        -  "twitterads",
        -  "slack",
        -  "intercom",
        -  "helpScout",
        -  "zapier",
        -  "integromat",
        -  "pabblyConnect",
        -  "webhook",
        -  "baskHealth"
        -]New value: +[
        +  "stripe",
        +  "chargebee",
        +  "recurly",
        +  "paypal",
        +  "wisecom",
        +  "tangoCard",
        +  "tremendous",
        +  "hubspot",
        +  "salesforce",
        +  "marketo",
        +  "mailchimp",
        +  "activecampaign",
        +  "braze",
        +  "bentonow",
        +  "mailerlite",
        +  "resenddotcom",
        +  "loopsdotso",
        +  "convertkit",
        +  "constantContact",
        +  "campaignMonitor",
        +  "aweber",
        +  "klaviyo",
        +  "mailjet",
        +  "sendgrid",
        +  "sendinblue",
        +  "emailoctopus",
        +  "customerio",
        +  "getresponse",
        +  "drip",
        +  "googleanalytics",
        +  "segmentanalytics",
        +  "posthoganalytics",
        +  "mixpanelanalytics",
        +  "pendo",
        +  "fullstory",
        +  "heapanalytics",
        +  "amplitude",
        +  "googleads",
        +  "metaads",
        +  "linkedinads",
        +  "twitterads",
        +  "slack",
        +  "intercom",
        +  "helpScout",
        +  "zapier",
        +  "integromat",
        +  "pabblyConnect",
        +  "webhook",
        +  "baskHealth",
        +  "tangocard"
        +]
      • addedOutput schema / properties / autoDisabled
        Added value: +{
        +  "description": "Whether GrowSurf switched the integration off after repeated delivery failures. Present only when `programVerified` is `true`.",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / connected
        Added value: +{
        +  "description": "Whether the program has stored credentials for this integration. Present only when `programVerified` is `true`.",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / enabled
        Added value: +{
        +  "description": "Whether the integration is switched on and currently working. Present only when `programVerified` is `true`.",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / programVerified
        Added value: +{
        +  "description": "`true` when the program's live integration list was read, so the program id is confirmed and the three state fields below are present and current. `false` when that read was unavailable, for example without an API key or `program:read`: the link still works but points at the production dashboard, and the state fields are omitted because the state is unknown. Never treat an absent state field as `false`.",
        +  "type": "boolean"
        +}
    • Changedgrowsurf_get_participant5 fields changed
      • addedOutput schema / properties / rewardEvidence
        Added value: +{
        +  "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.",
        +  "properties": {
        +    "approvalPolicy": {
        +      "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.",
        +      "enum": [
        +        "manual",
        +        "automatic",
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "automaticFulfillmentMarking": {
        +      "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.",
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "basis": {
        +      "enum": [
        +        "this_response_only"
        +      ],
        +      "type": "string"
        +    },
        +    "conclusion": {
        +      "type": "string"
        +    },
        +    "deliveryStatus": {
        +      "enum": [
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "integrationConnection": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    },
        +    "nextStep": {
        +      "type": "string"
        +    },
        +    "programReferralTrigger": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / rewards / items / properties / fulfilledAt / description
        Previous value: -"When the reward was fulfilled, as a Unix timestamp in milliseconds. `null` until fulfilled."New value: +"When the reward was marked fulfilled, as a Unix timestamp in milliseconds. `null` until marked fulfilled; this is not a delivery receipt."
      • changedOutput schema / properties / rewards / items / properties / isFulfilled / description
        Previous value: -"`true` once the reward has been fulfilled."New value: +"`true` once the reward is marked fulfilled. Confirm actual delivery through fulfillment records."
      • changedOutput schema / properties / rewards / items / properties / status / description
        Previous value: -"Fulfillment status of the earned reward."New value: +"Fulfillment marking of the earned reward. `FULFILLED` records that it was marked fulfilled, not proof of delivery. `CANCELLED` means an unpaid Lead reward was reversed before fulfillment."
      • changedOutput schema / properties / rewards / items / properties / status / enum
        Previous value: -[
        -  "PENDING",
        -  "FULFILLED"
        -]New value: +[
        +  "PENDING",
        +  "FULFILLED",
        +  "CANCELLED"
        +]
    • Changedgrowsurf_get_participant_analytics9 fields changed
      • addedInput schema / properties / days / description
        Added value: +"Number of days for optional `series` and `email` analytics. Does not filter the all-time base response."
      • changedInput schema / properties / endDate / description
        Previous value: -"End of the timeframe, Unix timestamp in ms."New value: +"End of the optional-data timeframe, Unix timestamp in ms. Use with `startDate`."
      • changedInput schema / properties / include / description
        Previous value: -"Comma-separated optional data. Current values are `series` and `email`; the API returns `400` for unknown values."New value: +"Comma-separated optional data. Current values are `series`, `email`, and `activation`; the API returns `400` for unknown values."
      • changedInput schema / properties / startDate / description
        Previous value: -"Start of the timeframe, Unix timestamp in ms. Use with endDate instead of days."New value: +"Start of the optional-data timeframe, Unix timestamp in ms. Use with `endDate` instead of `days`."
      • addedOutput schema / properties / activation
        Added value: +{
        +  "description": "Opt-in covered eligibility and first-milestone analytics for one participant.",
        +  "properties": {
        +    "cohort": {
        +      "description": "Program-specific eligibility anchor and covered value.",
        +      "properties": {
        +        "anchorAt": {
        +          "description": "Covered anchor time (Unix ms). `null` is unknown and does not mean enrollment never occurred.",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "anchorField": {
        +          "enum": [
        +            "enrolledAsAdvocateAt",
        +            "approvedAsAffiliateAt"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "coverageStartAt": {
        +      "description": "Earliest expected complete participant activation capture time (Unix ms).",
        +      "type": [
        +        "integer",
        +        "null"
        +      ]
        +    },
        +    "enrolledAsAdvocateAt": {
        +      "description": "Referral only. Covered advocate enrollment (Unix ms); `null` does not mean enrollment never occurred.",
        +      "type": [
        +        "integer",
        +        "null"
        +      ]
        +    },
        +    "metricContractVersion": {
        +      "description": "Shared activation and engagement metric version.",
        +      "type": "integer"
        +    },
        +    "milestones": {
        +      "description": "Covered first milestones. A `null` value is unknown and does not mean the action never happened.",
        +      "properties": {
        +        "firstCommissionAt": {
        +          "description": "Affiliate only. First covered commission (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "firstLeadAt": {
        +          "description": "First covered referred lead (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "firstPortalViewedAt": {
        +          "description": "First covered signed-in portal view (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "firstReferralAt": {
        +          "description": "First covered credited referral (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "firstReferralLinkCopiedAt": {
        +          "description": "First covered referral-link copy (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "firstRewardAt": {
        +          "description": "Referral only. First covered participant reward (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "firstShareAt": {
        +          "description": "First covered accepted share action (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "firstShareChannel": {
        +          "description": "Channel for `firstShareAt`, or `null` when the first covered share is unavailable.",
        +          "enum": [
        +            "email",
        +            "facebook",
        +            "twitter",
        +            "linkedin",
        +            "pinterest",
        +            "threads",
        +            "bluesky",
        +            "sms",
        +            "messenger",
        +            "whatsapp",
        +            "wechat",
        +            "telegram",
        +            "reddit",
        +            "tumblr",
        +            "qrcode",
        +            "copyRefLink",
        +            "iosNativeShare",
        +            "androidNativeShare",
        +            null
        +          ],
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "firstUniqueClickAt": {
        +          "description": "First covered unique referral visit (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "payoutSetupCompletedAt": {
        +          "description": "First covered payout-setup completion (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "programType": {
        +      "description": "Program eligibility model.",
        +      "enum": [
        +        "REFERRAL",
        +        "AFFILIATE"
        +      ],
        +      "type": "string"
        +    },
        +    "reason": {
        +      "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +      "enum": [
        +        "COVERAGE_UNAVAILABLE",
        +        "PRE_COVERAGE",
        +        "PARTIAL_COVERAGE",
        +        "INSUFFICIENT_COVERAGE",
        +        "EMPTY_DENOMINATOR",
        +        "QUERY_LIMIT_EXCEEDED",
        +        "PARTICIPANT_NOT_ELIGIBLE",
        +        null
        +      ],
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "state": {
        +      "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +      "enum": [
        +        "AVAILABLE",
        +        "PARTIAL",
        +        "UNAVAILABLE"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / analytics / description
        Previous value: -"Participant analytics totals."New value: +"All-time participant analytics totals. Date-window parameters do not filter these fields."
      • changedOutput schema / properties / analytics / properties / leads / description
        Previous value: -"Pending referral credits."New value: +"Current pending referral credits."
      • addedOutput schema / properties / series / items / properties / portalViews
        Added value: +{
        +  "description": "Covered signed-in portal views, or `null` outside known coverage.",
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / series / items / properties / shareActions
        Added value: +{
        +  "description": "Covered accepted share actions, or `null` outside known coverage.",
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
    • Changedgrowsurf_list_campaign_rewards2 fields changed
      • addedOutput schema / properties / rewardEvidence
        Added value: +{
        +  "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.",
        +  "properties": {
        +    "approvalPolicy": {
        +      "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.",
        +      "enum": [
        +        "manual",
        +        "automatic",
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "automaticFulfillmentMarking": {
        +      "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.",
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "basis": {
        +      "enum": [
        +        "this_response_only"
        +      ],
        +      "type": "string"
        +    },
        +    "conclusion": {
        +      "type": "string"
        +    },
        +    "deliveryStatus": {
        +      "enum": [
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "integrationConnection": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    },
        +    "nextStep": {
        +      "type": "string"
        +    },
        +    "programReferralTrigger": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / rewards / items / properties / event
        Added value: +{
        +  "description": "The referral event that earns this Campaign Reward. `LEAD` means a referred signup; `CONVERSION` means a qualifying action.",
        +  "enum": [
        +    "LEAD",
        +    "CONVERSION",
        +    null
        +  ],
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Addedgrowsurf_list_integrations
    • Changedgrowsurf_list_participants1 field changed
      • addedOutput schema / properties / rewardEvidence
        Added value: +{
        +  "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.",
        +  "properties": {
        +    "approvalPolicy": {
        +      "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.",
        +      "enum": [
        +        "manual",
        +        "automatic",
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "automaticFulfillmentMarking": {
        +      "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.",
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "basis": {
        +      "enum": [
        +        "this_response_only"
        +      ],
        +      "type": "string"
        +    },
        +    "conclusion": {
        +      "type": "string"
        +    },
        +    "deliveryStatus": {
        +      "enum": [
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "integrationConnection": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    },
        +    "nextStep": {
        +      "type": "string"
        +    },
        +    "programReferralTrigger": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Addedgrowsurf_list_program_resources
    • Addedgrowsurf_prepare_program_resource_file
    • Addedgrowsurf_program_design_advisor
    • Changedgrowsurf_record_sale3 fields changed
      • changedInput schema / allOf
        Previous value: -[
        -  {
        -    "anyOf": [
        -      {
        -        "required": [
        -          "participantId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "participantEmail"
        -        ]
        -      }
        -    ]
        -  },
        -  {
        -    "anyOf": [
        -      {
        -        "required": [
        -          "externalId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "transactionId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "orderId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "paymentId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "invoiceId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "paymentIntentId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "chargeId"
        -        ]
        -      }
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "anyOf": [
        +      {
        +        "required": [
        +          "participantId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "participantEmail"
        +        ]
        +      }
        +    ]
        +  },
        +  {
        +    "anyOf": [
        +      {
        +        "required": [
        +          "externalId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "transactionId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "orderId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "paymentId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "invoiceId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "paymentIntentId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "chargeId"
        +        ]
        +      }
        +    ]
        +  },
        +  {
        +    "if": {
        +      "required": [
        +        "paymentProvider"
        +      ]
        +    },
        +    "then": {
        +      "required": [
        +        "testMode",
        +        "transactionId"
        +      ]
        +    }
        +  },
        +  {
        +    "if": {
        +      "not": {
        +        "required": [
        +          "paymentProvider"
        +        ]
        +      }
        +    },
        +    "then": {
        +      "not": {
        +        "required": [
        +          "testMode"
        +        ]
        +      }
        +    }
        +  }
        +]
      • addedInput schema / properties / paymentProvider
        Added value: +{
        +  "description": "Connected provider for this payment. Requires `transactionId` and `testMode`. Supply matching `grossAmount` and `currency`; other payment IDs and tax or net-amount overrides are not accepted. GrowSurf reads payment details from the provider and detects duplicate webhook/API/manual submissions.",
        +  "enum": [
        +    "stripe",
        +    "chargebee",
        +    "recurly"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / testMode
        Added value: +{
        +  "description": "Required with `paymentProvider`: `true` for test or `false` for live. Otherwise omit.",
        +  "type": "boolean"
        +}
    • Changedgrowsurf_refund_transaction6 fields changed
      • changedInput schema / allOf
        Previous value: -[
        -  {
        -    "anyOf": [
        -      {
        -        "required": [
        -          "participantId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "participantEmail"
        -        ]
        -      }
        -    ]
        -  },
        -  {
        -    "anyOf": [
        -      {
        -        "required": [
        -          "externalId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "transactionId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "orderId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "paymentId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "invoiceId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "paymentIntentId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "chargeId"
        -        ]
        -      }
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "anyOf": [
        +      {
        +        "required": [
        +          "participantId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "participantEmail"
        +        ]
        +      }
        +    ]
        +  },
        +  {
        +    "anyOf": [
        +      {
        +        "required": [
        +          "externalId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "transactionId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "orderId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "paymentId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "invoiceId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "paymentIntentId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "chargeId"
        +        ]
        +      }
        +    ]
        +  },
        +  {
        +    "if": {
        +      "required": [
        +        "paymentProvider"
        +      ]
        +    },
        +    "then": {
        +      "required": [
        +        "testMode",
        +        "transactionId"
        +      ]
        +    }
        +  },
        +  {
        +    "if": {
        +      "not": {
        +        "required": [
        +          "paymentProvider"
        +        ]
        +      }
        +    },
        +    "then": {
        +      "not": {
        +        "required": [
        +          "testMode"
        +        ]
        +      }
        +    }
        +  }
        +]
      • addedInput schema / properties / paymentProvider
        Added value: +{
        +  "description": "Connected provider for the original payment. Requires its `transactionId` and `testMode`. This amends GrowSurf records without sending a refund through the provider.",
        +  "enum": [
        +    "stripe",
        +    "chargebee",
        +    "recurly"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / refundAmount / description
        Added value: +"Positive amount for this individual refund, no greater than the sale amount, in the sale currency's minor unit. Send it with `refundId` on each original refund to support cancellations and out-of-order amendments. The amount for a given `refundId` cannot change. A cancellation can omit it when the original amount is already recorded. Incomplete refund history returns `409` without applying the cancellation. Newly observed higher cumulative refunds and incomplete coverage are retained for reconciliation."
      • addedInput schema / properties / refundHistoryComplete
        Added value: +{
        +  "description": "Set true only after reconciling and recording every original refundId and refundAmount, including refunds later canceled. This confirmation resolves previously incomplete history. Omit during ordinary delivery. Replaying an old confirmation cannot resolve a later gap; confirm a newly reconciled refund or complete provider list.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / refundId / description
        Added value: +"Stable per-refund identifier. Required when canceling a refund or changing the refunded total after a cancellation. Reuse the original refund's identifier for its cancellation. An amendment without enough refund identity returns `409` without applying the cancellation. Newly observed higher cumulative refunds and incomplete coverage are retained for reconciliation."
      • addedInput schema / properties / testMode
        Added value: +{
        +  "description": "Original payment mode: `true` for test or `false` for live. Requires `paymentProvider`.",
        +  "type": "boolean"
        +}
    • Addedgrowsurf_troubleshoot_referral_tracking
    • Changedgrowsurf_update_campaign1 field changed
      • addedInput schema / anyOf
        Added value: +[
        +  {
        +    "required": [
        +      "name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "companyName"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "companyLogoImageUrl"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "status"
        +    ]
        +  }
        +]
    • Changedgrowsurf_update_campaign_installation1 field changed
      • addedInput schema / properties / replaceExistingShareUrl
        Added value: +{
        +  "description": "Set this to `true` only after the customer confirms they want a different landing page. Without it, a patch that would replace a Share URL that is already set is refused.",
        +  "type": "boolean"
        +}
    • Changedgrowsurf_update_campaign_reward5 fields changed
      • addedInput schema / properties / commissionStructure / allOf
        Added value: +[
        +  {
        +    "if": {
        +      "properties": {
        +        "event": {
        +          "enum": [
        +            "CLICK",
        +            "LEAD"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "event"
        +      ]
        +    },
        +    "then": {
        +      "properties": {
        +        "amount": {
        +          "minimum": 1,
        +          "type": "integer"
        +        },
        +        "type": {
        +          "enum": [
        +            "FIXED"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "amount"
        +      ]
        +    }
        +  }
        +]
      • changedInput schema / properties / commissionStructure / description
        Previous value: -"Affiliate commission structure (AFFILIATE rewards only). Provide `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission."New value: +"Affiliate commission structure (AFFILIATE rewards only). Provide a positive `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission. CLICK and LEAD commissions must use FIXED."
      • addedInput schema / properties / commissionStructure / properties / amount / minimum
        Added value: +1
      • addedInput schema / properties / commissionStructure / properties / event / description
        Added value: +"The affiliate event that earns the commission. `CLICK` and `LEAD` must use `FIXED`."
      • addedInput schema / properties / event
        Added value: +{
        +  "description": "The referral event that earns this Campaign Reward. Use `LEAD` for a referred signup or `CONVERSION` for a qualifying action. A `LEAD` reward requires a later custom conversion trigger. Referral reward types only.",
        +  "enum": [
        +    "LEAD",
        +    "CONVERSION"
        +  ],
        +  "type": "string"
        +}
    • Changedgrowsurf_update_campaign_webhook1 field changed
      • addedInput schema / anyOf
        Added value: +[
        +  {
        +    "required": [
        +      "payloadUrl"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "events"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "secret"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "isEnabled"
        +    ]
        +  }
        +]
    • Addedgrowsurf_update_program_resource
  2. 54 tool updatesv0.12.2
    • First observedgrowsurf_add_participant
    • First observedgrowsurf_agent_program_creation_eval
    • First observedgrowsurf_api_library_snippets
    • First observedgrowsurf_bulk_delete_participants
    • First observedgrowsurf_cancel_delayed_referral
    • First observedgrowsurf_capture_referral_flow_screenshots
    • First observedgrowsurf_client_snippets
    • First observedgrowsurf_clone_campaign
    • First observedgrowsurf_create_account
    • First observedgrowsurf_create_campaign
    • First observedgrowsurf_create_campaign_reward
    • First observedgrowsurf_create_campaign_webhook
    • First observedgrowsurf_create_mobile_participant_token
    • First observedgrowsurf_delete_campaign_reward
    • First observedgrowsurf_delete_campaign_webhook
    • First observedgrowsurf_email_participant
    • First observedgrowsurf_embeddable_element_snippet
    • First observedgrowsurf_get_campaign
    • First observedgrowsurf_get_campaign_analytics
    • First observedgrowsurf_get_campaign_design
    • First observedgrowsurf_get_campaign_emails
    • First observedgrowsurf_get_campaign_installation
    • First observedgrowsurf_get_campaign_options
    • First observedgrowsurf_get_integration_connect_link
    • First observedgrowsurf_get_participant
    • First observedgrowsurf_get_participant_activity_logs
    • First observedgrowsurf_get_participant_analytics
    • First observedgrowsurf_get_participant_payout_destination
    • First observedgrowsurf_get_team
    • First observedgrowsurf_grsf_config_snippet
    • First observedgrowsurf_integration_guide
    • First observedgrowsurf_list_campaign_rewards
    • First observedgrowsurf_list_campaign_webhooks
    • First observedgrowsurf_list_campaigns
    • First observedgrowsurf_list_participants
    • First observedgrowsurf_mobile_sdk_guide
    • First observedgrowsurf_participant_auth_hash
    • First observedgrowsurf_record_sale
    • First observedgrowsurf_refund_transaction
    • First observedgrowsurf_request_participant_payout_destination_confirmation
    • First observedgrowsurf_request_team_verification
    • First observedgrowsurf_resend_team_owner_verification_email
    • First observedgrowsurf_test_campaign_webhook
    • First observedgrowsurf_trigger_referral
    • First observedgrowsurf_update_campaign
    • First observedgrowsurf_update_campaign_design
    • First observedgrowsurf_update_campaign_emails
    • First observedgrowsurf_update_campaign_installation
    • First observedgrowsurf_update_campaign_options
    • First observedgrowsurf_update_campaign_reward
    • First observedgrowsurf_update_campaign_webhook
    • First observedgrowsurf_update_participant
    • First observedgrowsurf_update_team
    • First observedgrowsurf_webhook_normalize

TDQS

A3.5/5.0

Scored across 63 tools

Disambiguation4/5

Most tools are clearly scoped by resource and action (campaign, participant, webhook, reward, resource), and the long descriptions remove much ambiguity. The main risk is the cluster of snippet/guide generators (client_snippets, embeddable_element_snippet, grsf_config_snippet, integration_guide), which can overlap for similar-looking requests.

Naming Consistency4/5

Nearly all tools follow the growsurf_ verb_noun snake_case pattern, and resource names are consistently ordered (e.g. get_campaign, update_participant, delete_campaign_webhook). The main deviations are noun-style guide/snippet tools like program_design_advisor, client_snippets, and participant_auth_hash, plus the object-first webhook_normalize.

Tool Count1/5

63 tools is far beyond the typical MCP tool surface and exceeds the rubric's 50+ extreme threshold. Even though GrowSurf is a broad platform, this volume makes the toolset heavy to navigate and select from.

Completeness4/5

The set covers campaigns, rewards, participants, resources, webhooks, analytics, integrations, team/account management, and diagnostics — very strong coverage of the domain. Minor gaps exist, such as no delete-campaign tool, no single-participant delete (bulk only), and no direct reward-fulfillment mutation, but agents can generally work around them.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    C
    maintenance
    Enables users to manage affiliate marketing directly within Claude by connecting to the Affilync platform. Affiliates can search campaigns and track earnings, while brands can create campaigns, monitor performance, and manage affiliate applications through natural language.
    20
    1
    -
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI agents to access affiliate marketing capabilities through AgentFuse's API, allowing them to browse affiliate programs, generate tracked links, and record conversions without writing HTTP code.
    7
    31 npm
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    Enables AI agents to automate sales outreach, research leads, and manage campaigns directly in OutreachPilot via natural language commands.
    31
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to manage GoHighLevel workspaces through natural language, with 508 tools across 18 domains for complete CRM, marketing, and workflow automation.
    Apache 2.0