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

    • Prompts use details from your conversation and ask only for missing information needed for the next step. No form inputs are needed. Existing prompt names and direct arguments remain supported.

    • 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 so the user can see a draft program

    • 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 a draft is saved or when the user asks to see it. 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. Pass metadata (up to 3 keys) to return only participants whose metadata matches exactly, such as looking someone up by your own customer ID. 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 — Check each row outcome. analyticsErasure.status: "pending" means analytics erasure is still pending; do not repeat successful rows. 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_participantAdd ParticipantAInspect

Add or fetch a participant by email. Existing participants are returned unchanged. This is trusted direct enrollment and bypasses the public application review flow for affiliates. 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. Program IDs also identify newly created programs 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

A4.1/5.0
Behavior5/5

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

Beyond the annotations (readOnlyHint=false, destructiveHint=false, idempotentHint=false), the description discloses real behavior: existing participants are returned unchanged, the call bypasses the public application review flow, and the enrollment status outcome depends on isAffiliate/referredBy. These are consequential side-effect details the annotations cannot express.

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 the key 'existing participants returned unchanged' behavior, then the affiliate logic. The conditional rules are non-obvious and earn their space, though the description is dense and could be tightened.

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?

With an output schema present, return values need not be explained, and annotations cover the safety profile. The description thoroughly covers the affiliate/referral enrollment logic and targeting default, but omits auth/permission needs and most secondary parameter meaning for an 11-param mutation 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 coverage is only 18%, so the description must carry the load, and it does add genuine meaning for the trickiest params (isAffiliate outcomes, referredBy interaction, campaignId default). But it leaves the majority of the 11 params (fingerprint, ipAddress, mobileInstanceId, referralStatus, metadata, name fields) undocumented, so it only partially compensates.

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?

States a specific verb+resource: 'Add or fetch a participant by email.' The add-or-fetch semantics is distinctive and distinguishes it functionally from get_participant (fetch only) and update_participant, though no sibling is named explicitly, keeping it from a 5.

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 of use — 'trusted direct enrollment and bypasses the public application review flow for affiliates' — and conditions for the affiliate/referral flags. However it never names an alternative tool or states when not to use this one versus get_participant/update_participant, so it stops short of explicit routing.

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_evalProgram Creation EvalsA
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.8/5.0
Behavior4/5

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

Annotations already indicate read-only, idempotent, and non-destructive behavior, so the description only needs to add extra behavioral context. It does so by specifying that the tool produces 'one-shot' evaluation prompts and acceptance checks, and by listing the four focus areas, which goes beyond mere annotation repetition.

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 entire description is one front-loaded sentence with no filler. It states the verb, resource, purpose, and key scope areas in a compact list, so every part earns its place.

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?

Output schema and annotations cover return values and safety behavior, and both parameters are optional with defaults, so an agent can invoke the tool minimally. However, with no schema descriptions for parameters, the description leaves programType semantics and the effect of includeOneShotPrompts unexplained, creating a notable completeness gap.

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 carries the burden of explaining the two parameters, but it does not mention programType or define what includeOneShotPrompts controls. Only the word 'one-shot' weakly hints at one parameter, and 'program-creation' weakly hints at the other; this is insufficient compensation for a low-coverage 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 opens with a specific action, 'Generate one-shot GrowSurf program-creation eval prompts and acceptance checks', naming both the deliverable and its purpose. The colon-delimited list of coverage areas further distinguishes it from the many operational sibling tools, making its unique role clear.

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 phrase 'for agent steering' implies the intended context, and the content areas suggest evaluation scenarios. However, there is no explicit when-to-use/when-not-to-use guidance or mention of alternatives, leaving the selection logic mostly to inference.

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

growsurf_api_library_snippetsAPI 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 clear. The description adds no behavioral detail beyond generating snippets, but it does not contradict the annotations either.

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 one concise, front-loaded sentence with no filler. It communicates the deliverable and scope quickly, though a short structured format could improve scannability.

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 six optional parameters, multiple workflow and language enums, and many sibling snippet tools, more contextual guidance is needed for reliable invocation. The description omits when to use this tool, how to populate workflow-specific identifiers, and how it relates to client/embeddable snippet alternatives; the output schema helps with return values but not invocation context.

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 needed to explain how to use email, language, workflow, campaignId, referredBy, and participantIdOrEmail. It only echoes the language options and mentions the mobile participant token workflow, leaving most parameters unexplained; the schema itself already provides the enums and defaults.

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 specific action and resource: generating official REST API library snippets for five named languages, and explicitly calls out the Create Mobile Participant Token workflow. It is reasonably distinguishable from sibling snippet tools like client snippets and embeddable snippets, though it does not name those alternatives.

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 about when to use this tool versus sibling tools such as growsurf_client_snippets, growsurf_embeddable_element_snippet, or growsurf_grsf_config_snippet. The description also does not explain which workflow or language option fits a given scenario.

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

growsurf_bulk_delete_participantsBulk 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 — both 200 and 202 responses can include NOT_FOUND or ERROR rows, and the summary reports these outcomes. A 202 response includes analyticsErasure when analytics erasure is pending. DELETED means participant cleanup completed; reports can retain the participant until analytics erasure completes. Repeating successful rows does not finish analytics erasure. 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. Program IDs also identify newly created programs 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.
analyticsErasureNoAnalytics erasure is pending. Reports can retain removed participants until erasure completes. Do not repeat successful deletions.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already flag destructiveHint and idempotentHint, but the description adds substantial context beyond them: deletion removes referrals, rewards, commissions, and payout records; 200 and 202 both can carry NOT_FOUND or ERROR rows; 202 signals pending analyticsErasure; repeating successful rows does not complete erasure. This is exactly the behavioral depth the annotations cannot convey.

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 destructive warning, then entry format, limits, and response semantics in a logical order. It is dense rather than wasteful, but the run of response-code detail (200/202, DELETED/NOT_FOUND/DUPLICATE/ERROR, analyticsErasure) is long enough that a tighter phrasing would still convey the same guidance.

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 destructive bulk mutation with two parameters, the description covers safety, input limits, chunking, target resolution, and partial-failure semantics (per-row statuses, summary counts, 202 erasure state). Nothing an agent needs to invoke it safely and interpret mixed outcomes 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 100%, so the schema itself documents mixed ID/email lists and the 1-200 bound. The description still adds value by clarifying the chunking strategy for lists over 200 and restating how campaignId falls back to the environment variable, which helps an agent plan multi-call deletions.

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 ('Bulk delete participants from your GrowSurf program') plus scope (single request, up to 200 entries) and target (campaignId or GROWSURF_CAMPAIGN_ID). An agent can distinguish it from growsurf_list_participants, growsurf_add_participant, and growsurf_update_participant without opening any schema.

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 clear operational context: bulk deletion in one request, chunking larger lists across multiple calls, and how the target campaign is resolved. It does not explicitly name the sibling tools or state when deletion is inappropriate versus softer alternatives (e.g. update), so it stops short of full when/when-not guidance.

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

growsurf_cancel_delayed_referralCancel 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. Program IDs also identify newly created programs 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.8/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, readOnlyHint=false and openWorldHint=false, so the safety profile is covered. The description adds what is destroyed (a pending delayed trigger) and the target-resolution fallback, but omits auth requirements, failure modes, and what happens if the delay has already elapsed.

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 short sentences, front-loaded with the operation and then the return shape and targeting rule. No filler; every clause carries information an agent needs.

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?

With an output schema present, return values need not be described, and annotations carry the safety profile. The description is nearly complete for a low-complexity, low-parameter tool; the main residual gap is the participant identifier choice and error behavior.

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 33%: only campaignId is documented in the schema. The description clarifies campaignId targeting ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID') but says nothing about the participantId vs participantEmail either-or requirement encoded in the anyOf, leaving that gap to the schema alone.

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 gives a specific verb+resource+scope: 'Cancel a pending delayed referral trigger for a participant before the delay elapses.' An agent can tell this undoes a pending trigger versus siblings like growsurf_trigger_referral or growsurf_refund_transaction. It stops short of explicitly naming and contrasting a sibling.

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 supplies a clear triggering context — 'before the delay elapses (e.g. on refund/cancellation)' — which tells the agent when this tool is the right call. There are no explicit exclusions or named alternatives, so it falls 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_capture_referral_flow_screenshotsCapture Referral Flow ScreenshotsAInspect

Capture temporary GrowSurf preview screenshots after a draft program is saved. Returns short-lived URLs for the controlled referrer Window and referred-friend experience, with an expiresAt timestamp in UTC. The screenshots reflect the saved program at capture time and do not verify installation on the customer's site. A failed inline image alone does not establish that the URL expired. This tool does not accept arbitrary URLs, HTML, JavaScript, or external screenshot targets. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs 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
Behavior5/5

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

Annotations only declare the safety profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false, openWorldHint=false); the description goes well beyond them by disclosing that URLs are short-lived, that an `expiresAt` UTC timestamp is returned, that screenshots reflect the saved program at capture time rather than live installation state, and that a failed inline image does not prove URL expiry. That is exactly the kind of operational caveat an agent needs before interpreting results.

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?

Purpose and return contract are front-loaded in the first two sentences, with constraints following. Every sentence carries a distinct constraint, though the negative-acceptance list and the expiry caveat could be tightened slightly.

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, zero-required tool with an output schema and full annotation coverage, the description supplies the remaining gaps an agent needs: lifetime of returned URLs, capture-time semantics, and the distinction between a broken image and an expired URL. Nothing material 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% for the single `campaignId` parameter, so the baseline is 3. The description's 'Targets `campaignId` if supplied, otherwise `GROWSURF_CAMPAIGN_ID`' restates the schema's default-resolution behavior without adding format or syntax detail beyond it.

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 ('Capture temporary GrowSurf preview screenshots') and scopes it precisely to 'after a draft program is saved'. No sibling tool covers screenshot capture, so the agent can route to it unambiguously from the name and first sentence alone.

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 a clear precondition ('after a draft program is saved') and explicit negative boundaries ('does not accept arbitrary URLs, HTML, JavaScript, or external screenshot targets'), which tells the agent when not to reach for it. It never names an alternative tool for adjacent needs, so it falls 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_client_snippetsClient SnippetsB
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

B3.4/5.0
Behavior3/5

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

Annotations already provide readOnlyHint=true and idempotentHint=true, making it clear this is a safe read-only operation that can be called repeatedly without side effects. The description adds that it generates snippets and provides placement guidance, but does not disclose the format of the output (e.g., exact code blocks, language specifics) beyond JS + CSS. With annotations covering safety, the description adds moderate value, but it could state that no programmatic changes are made and the output is purely for the UI.

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 is concise and front-loaded with the core purpose ('Generate copy-pasteable client-side snippets'). It covers key topics (referral tracking, embeddable elements, GrowSurf Window) and adds placement guidance without excessive detail. It could be more structured, but it is efficient and earns its place.

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 8 parameters with 0% schema description coverage and no parameter documentation in the description, which is a major gap. There is an output schema, which may define the snippet structure, but since it is not shown here, it is unclear. The description is not complete enough for an agent to correctly set all options without further guidance. It needs to either describe parameters or link to resource guides.

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%, meaning none of the 8 parameters are described in the schema. The description does not explain any parameters, such as programType, singlePageApp, referralTrigger, or includeGrowSurfWindow. This is a significant gap because an agent must guess the meaning of each boolean and enum from names and defaults, which is error-prone. The description should at least summarize key options to compensate for the lack of schema descriptions.

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 generates client-side snippets for GrowSurf referral tracking, embeddable elements, and the GrowSurf Window, specifying JS + CSS and placement guidance. It distinguishes from sibling tools like growsurf_api_library_snippets and growsurf_embeddable_element_snippet by focusing on client-side copy-pasteable snippets for app UI work. The title 'Client Snippets' is more generic, but the description clarifies the specific output.

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 mentions placement guidance for app UI work, indicating it is intended for front-end integration. It implicitly differentiates from API snippets by naming 'copy-pasteable client-side snippets', but it does not explicitly state when to use this tool versus siblings like growsurf_api_library_snippets or growsurf_mobile_sdk_guide. It lacks explicit when-not-to-use alternatives, but the context is clear enough for an agent to infer the primary use case.

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

growsurf_clone_campaignClone ProgramAInspect

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. Program IDs also identify newly created programs without restarting the server.

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?

Annotations only declare readOnly=false, destructive=false, idempotent=false. The description adds genuinely useful behavior the annotations cannot convey: integrations and credentials are NOT copied while active rewards ARE, and the output is a DRAFT rather than a live program. It stops short of noting that repeated calls produce multiple drafts (relevant to idempotentHint=false) or any permission requirements.

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?

Three short sentences, front-loaded with the core action and result state, with the copy semantics placed before the id-targeting detail. Slightly redundant with the schema on the campaignId default, but no wasted framing.

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?

An output schema exists, so return values need not be explained, and the description covers the two things an agent most needs for a mutating clone: what state the result is in (DRAFT) and what is/isn't carried over. The one notable omission is the non-idempotent consequence of calling it more than once.

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% for the single parameter, and the schema description already documents the GROWSURF_CAMPAIGN_ID fallback. The description's targeting sentence therefore restates schema content rather than adding format, validation, or constraint detail. Baseline 3 applies.

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 names a specific verb and resource ('Clone your GrowSurf program (campaign)') and specifies the resulting state ('new DRAFT program'), which is more than a restatement of the title. It does not explicitly contrast itself with the nearby growsurf_create_campaign sibling, so the agent must infer that cloning differs from creating from scratch.

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?

Usage is only implied: you clone an existing program when you want a duplicate draft. There is no statement of when to prefer this over growsurf_create_campaign, no prerequisites, and no exclusions. The targeting sentence describes which id is used, not when the tool is appropriate.

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

growsurf_create_accountCreate GrowSurf AccountA
Destructive
Inspect

Create a brand-new GrowSurf account and return an API key. Requires the authorized owner's explicit approval of account creation and acceptance of 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 new key is returned once in apiKey, cannot be recovered through this API, and requires durable secret storage. The hosted OAuth connector is an alternative that retains credentials with the connection. The key stays locked until the owner verifies their email; program and resource endpoints return 403 with EMAIL_NOT_VERIFIED_ERROR before verification. Verification unlocks the same key. The welcome email includes verification and set-password links. Unverified accounts are deleted after 7 days. The owner's first dashboard sign-in replaces the API key; the old key then returns 403 with NOT_AUTHORIZED_ERROR. Participant emails also require team verification. 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.4/5.0
Behavior5/5

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

Beyond annotations, it discloses extensive behavioral traits: the key is returned once and cannot be recovered, is locked behind email verification with a specific 403 error, unverified accounts are deleted after 7 days, the owner's first dashboard sign-in replaces the key causing `NOT_AUTHORIZED_ERROR`, and the trial details. This is a high level of disclosure for a destructive, open-world creation tool.

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 dense with useful operational details and front-loads the core action and key prerequisite. A few sentences (e.g., participant email verification) are tangential to the tool's immediate invocation, but most content 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?

Given the complexity, high-risk nature (destructiveHint=true), and an output schema that exists, the description is nearly complete on return and behavioral aspects. The main gap is the lack of parameter semantics for three of four fields, which the schema also fails to document.

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 for the four parameters. It only indirectly implies that the `email` parameter is the owner's email and that personal/disposable addresses are rejected; it says nothing about `company`, `firstName`, or `lastName`, leaving their purpose and format undocumented.

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 precise verb and resource: 'Create a brand-new GrowSurf account and return an API key.' It also uniquely distinguishes itself from siblings by noting it is the only tool that does not require `GROWSURF_API_KEY`, which is crucial routing information for an agent.

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 including prerequisites (owner approval, ToS/Privacy acceptance) and names the hosted OAuth connector as an alternative that retains credentials. It also clarifies that this is the only no-API-key tool, leaving little ambiguity about when to select it.

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

growsurf_create_campaignCreate ProgramAInspect

Create a new GrowSurf program (campaign) with type-appropriate starter content and optional inline rewards. Starter content includes Design, Emails, Options, Installation, and GrowSurf Window defaults. Only type is required. The program starts in DRAFT status and is owned by the credential's bound team. currencyISO defaults to USD and is immutable after creation. goal sets the sharing settings at creation and cannot be set later. Incentives require the customer's chosen amount or commission rate. Without rewards, GrowSurf's starter rewards are switched off and award nothing. Editor-tab configuration is not accepted here. Does not require GROWSURF_CAMPAIGN_ID. The response includes the new program id.

ParametersJSON Schema
NameRequiredDescriptionDefault
goalNoWhat the program is for, which seeds the share buttons and the starter rewards that suit that audience. Programs whose participants refer other businesses (`CUSTOMERS`, `USERS`, `B2B_SAAS_SELF_SERVICE`, `B2B_SAAS_ENTERPRISE`, `HEALTHCARE_PROVIDERS`) start with the LinkedIn share button visible. Consumer, financial, education, insurance, telehealth, newsletter, and waitlist programs (`B2C_SUBSCRIPTIONS`, `FINANCIAL_SERVICES`, `ONLINE_EDUCATION`, `INSURANCE`, `ONLINE_INSURANCE`, `TELEHEALTH`, `SUBSCRIBERS`, `WAITLIST`) start with it hidden. On a referral program, each goal also sets the rest of its share buttons to suit that audience — a telehealth program keeps the public feeds off, a consumer subscription turns Pinterest and Reddit on; an affiliate program has its own share defaults, so only the LinkedIn default applies to one. When you create a referral program without `rewards`, the goal also decides the starter rewards: most goals get one double-sided reward, `HEALTHCARE_PROVIDERS` gets a single-sided reward, `SUBSCRIBERS` gets a four-step milestone ladder, and `WAITLIST` gets a leaderboard. Every starter reward arrives switched off with a placeholder name, so the program awards nothing until the customer sets the amount and turns one on. `TELEHEALTH` is for consumer telehealth and wellness subscriptions, where patients refer friends; `HEALTHCARE_PROVIDERS` is for provider networks and clinician-facing products, where practices refer peer practices. `INSURANCE` replaces `ONLINE_INSURANCE`, which is still accepted and behaves identically. Omit `goal` and every share button keeps its standard default. Sharing settings remain editable after creation. The goal itself is set only at creation.
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.5/5.0
Behavior5/5

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

Beyond annotations, the description discloses that the program starts in DRAFT status, is owned by the credential's bound team, currencyISO defaults to USD and is immutable after creation, goal is set only at creation, and omitting rewards seeds switched-off starter rewards that award nothing. It also states that editor-tab configuration is not accepted and that the response includes the new program id, all of which materially inform invocation.

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 front-loaded with the core purpose and then proceeds through creation defaults, immutability rules, and edge cases in a mostly linear order. It is longer than a minimal description but each sentence adds useful behavioral context; minor redundancy exists around goal and rewards, but there is 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?

With an output schema present, the description need not explain return values, and it still notes the response includes the new program id for convenience. Annotations cover the safety profile, and the description adds substantial creation behavior, defaults, and constraints, though it does not address permissions/plan requirements or clarify all seven parameters. It is complete enough for correct invocation in most cases.

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 low at 29%, so the description must compensate, and it does so for key parameters: type is the only required field, currencyISO defaults to USD and is immutable, rewards are optional and affect starter rewards, and goal sets sharing settings only at creation. It leaves name, companyName, and companyLogoImageUrl without explicit semantic guidance, but their purpose is largely self-evident from the parameter 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 opens with a specific verb and resource: 'Create a new GrowSurf program (campaign) with type-appropriate starter content and optional inline rewards.' It clearly differentiates from update/clone siblings by emphasizing that it creates a new program, starts it in DRAFT, and only requires type. An agent can identify the core action and scope 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 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 include rewards, when to omit them, and how goal affects creation, plus a boundary that 'Editor-tab configuration is not accepted here' and that the call 'Does not require GROWSURF_CAMPAIGN_ID.' However, it never names an alternative sibling tool (e.g., clone_campaign or update_campaign) for closely related tasks, so it falls short of explicit when-to-use-vs-alternative guidance.

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

growsurf_create_campaign_rewardCreate 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. Program IDs also identify newly created programs 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.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, idempotentHint=false, destructiveHint=false and openWorldHint=true, so the write/non-idempotent profile is known. The description adds the type-compatibility constraint and the campaign-targeting default, but says nothing about idempotency, error behavior, or side effects beyond that, so it adds only modest value over 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?

Two tight sentences with the core action and the critical constraint front-loaded; no filler. Slightly dense with backticked identifiers but still readable and well-ordered.

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?

An output schema exists, so return values need not be explained, and the two most consequential rules (type compatibility, targeting default) are covered. However, for a 23-parameter creation tool at 22% schema coverage, the description leaves the majority of the parameter surface unexplained.

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 22% across 23 parameters, so the description must compensate, and it does so only for `type` (compatibility rules) and `campaignId` (defaulting). Many parameters (limit, order, title, isVisible, couponCode, numberOfWinners, conversionsRequired, etc.) remain undocumented in both places, leaving a substantial 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?

States a specific verb and resource ('Create a new campaign reward (reward config)') and scopes it to the GrowSurf program, which cleanly separates it from the list/update/delete campaign_reward siblings. It does not explicitly name an alternative, but the create action 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?

Gives real preconditions: `type` must match the program type (affiliate vs referral programs), and the target is `campaignId` if passed, otherwise GROWSURF_CAMPAIGN_ID. This tells the agent when the call is valid and how targeting resolves, though it does not discuss when to prefer a different tool.

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

growsurf_create_campaign_webhookCreate 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. Program IDs also identify newly created programs without restarting the server.
payloadUrlYes

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 already cover the safety profile (readOnlyHint=false, openWorldHint=true, non-idempotent). The description adds genuine value beyond them: the secret is write-only and used for HMAC signing via the GrowSurf-Signature header, and omitting events subscribes the webhook to no events. It omits error/retry or rate-limit behavior, so not a full 5.

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 compact sentences that are front-loaded with purpose, followed by parameter-specific notes. No filler, though the parameter sentences are dense and a slightly more scannable structure would help.

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?

An output schema exists, so return values need not be described. The description covers the required parameter, the non-obvious write-only secret, and the campaign targeting default. The only material gap is the unexplained isEnabled flag.

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 40% schema description coverage, the description compensates well: it clarifies payloadUrl is required, explains events semantics including the omit case, expands on secret's write-only signing role, and documents campaignId's fallback to GROWSURF_CAMPAIGN_ID. Only isEnabled is left unexplained, keeping it from a 5.

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?

States a specific verb+resource: 'Add a webhook to your GrowSurf program.' An agent can readily distinguish this from the sibling list/update/delete/test webhook tools based on the verb 'Add'. It stops short of explicitly naming those alternatives, but the action 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 Guidelines3/5

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

Provides operational guidance (payloadUrl required, omitting events subscribes to nothing, targeting campaignId vs GROWSURF_CAMPAIGN_ID default), which implies when and how to call it. However, it never routes between this and sibling tools like update_campaign_webhook or test_campaign_webhook, nor states prerequisites or exclusions.

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_tokenCreate Mobile Participant TokenBInspect

Create or fetch a participant, then create a participant-scoped mobile SDK token via GrowSurf REST. Participant creation is trusted direct enrollment and bypasses the public application review flow for affiliates. 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. Program IDs also identify newly created programs 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

B3.4/5.0
Behavior4/5

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

Annotations already establish the mutation profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false), and the description adds genuinely useful context: participant creation bypasses the public application review flow for affiliates, and the campaign target falls back to an env var. It stops short of disclosing auth requirements, rate limits, or what 'create or fetch' means for repeat calls.

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?

Three tight, front-loaded sentences with no filler. The core action comes first and the enrollment/targeting caveats follow, which is appropriate sizing for the information present.

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?

An output schema exists, so return values need no explanation, and the enrollment semantics are covered. However, for an 11-parameter mutation tool with 18% schema coverage, the description should have compensated for the many undocumented fields; instead it leaves that gap open.

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 coverage is only ~18% — just campaignId and isAffiliate are described. The description adds only the campaignId fallback behavior, leaving 9 of 11 parameters (email, firstName, lastName, metadata, ipAddress, referredBy, fingerprint, referralStatus, mobileInstanceId) undocumented in both schema and description.

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 names a specific verb+resource (create a participant-scoped mobile SDK token) and clarifies the two-step behavior (create-or-fetch participant, then tokenize). It is clearly specific, but it never differentiates this tool from close siblings like growsurf_add_participant or growsurf_mobile_sdk_guide.

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?

Usage is implied through the 'trusted direct enrollment' framing and the campaignId/`GROWSURF_CAMPAIGN_ID` targeting note, but there is no explicit when-to-use or when-not-to-use guidance and no named alternative for the non-mobile participant case.

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

growsurf_create_program_resourceCreate Program ResourceAInspect

Create a FILE, LINK, or TEXT resource for participants. LINK requires an HTTPS url. TEXT requires plain text. A FILE up to 10 MB requires a one-time uploadTicket and the unmodified uploadResult from GrowSurf's secure upload flow. New resources default to draft unless isPublished is set. API reference: https://docs.growsurf.com/developer-tools/rest-api/api-reference. Targets campaignId if supplied, 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. Program IDs also identify newly created programs 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.3/5.0
Behavior4/5

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

Annotations already declare readOnly=false, idempotent=false, destructive=false, openWorld=true. The description adds genuinely new behavioral context: new resources default to draft unless isPublished is set, the uploadTicket is one-time, FILE is capped at 10 MB, and the unmodified uploadResult must be passed through. It stops short of describing auth/permission needs or failure behavior.

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?

Six tight sentences, front-loaded with the purpose and immediately followed by per-type requirements, then defaults, then the API reference and targeting. Every sentence carries load, though the bare API-reference URL adds little for an agent that already has the schema.

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?

An output schema exists, so return values need no explanation, and the description covers the type matrix, the draft default, the upload flow, and campaign targeting for a 10-parameter conditional mutation. The main remaining gap is not explicitly routing the agent to the prepare-upload sibling that produces uploadTicket/uploadResult.

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 description coverage, the description meaningfully compensates: it explains the conditional coupling of type to url/text/uploadTicket/uploadResult, the HTTPS constraint, the isPublished default, and the campaignId-to-GROWSURF_CAMPAIGN_ID fallback. This adds real semantics the schema's conditional allOf alone makes hard to parse.

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 ("Create a `FILE`, `LINK`, or `TEXT` resource for participants") and immediately enumerates the three subtypes, which lets an agent distinguish it from sibling tools like update_program_resource, list_program_resources, and delete_program_resource without opening a schema.

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 per-type usage conditions (LINK needs HTTPS url, TEXT needs text, FILE needs uploadTicket + uploadResult) and states the draft-by-default behavior. However, it never names the obvious prerequisite sibling `growsurf_prepare_program_resource_file` for the "secure upload flow," leaving the agent to infer where uploadTicket/uploadResult come from.

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

growsurf_delete_campaign_rewardDelete 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. Program IDs also identify newly created programs without restarting the server.
campaignRewardIdYes

Output Schema

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

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already flag destructiveHint=true and idempotentHint=true, but the description adds real value by spelling out the concrete side effects: deactivation, removal from the reward set, and cleanup of connected upfront-discount coupons. It omits permissions/irreversibility, so not a 5.

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?

Three tight sentences, front-loaded with the action and its effects, then the identifier meaning, then the targeting fallback. No filler, though the return-value mention is slightly redundant given the output schema exists.

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 two-parameter destructive tool with an output schema present, the description covers the action, side effects, required key semantics, and targeting default. Only permissions/irreversibility context 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 50% and campaignRewardId has no schema description, so the description compensates by defining it as the reward key. It also restates the campaignId default behavior, which is useful even though the schema already documents it.

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 (Delete) plus resource (campaign reward / reward config) and names the parent program, distinguishing it from list/create/update_campaign_reward siblings. 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 Guidelines3/5

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

The description makes clear it's a destructive removal and explains the fallback target, but never says when to prefer it over alternatives like update_campaign_reward (deactivate without deleting) or when deletion is inappropriate. Usage is implied rather than guided.

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

growsurf_delete_campaign_webhookDelete 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. Program IDs also identify newly created programs without restarting the server.

Output Schema

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

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, idempotentHint=true, readOnlyHint=false, and openWorldHint=true, so the safety profile is covered. The description adds the return shape ({ id, success }) and the campaign-resolution fallback, but never states what is destroyed or whether the removal is reversible beyond the idempotency already annotated.

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 tight, front-loaded sentences with no filler; the operation comes first and the targeting caveat second. The explicit return-shape note is mildly redundant given an output schema exists.

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 two-parameter destructive tool whose annotations carry the safety profile and which has a full output schema, the description covers the essential targeting default and return shape. Missing only a note on failure/permission behavior, which is a minor gap.

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 50% (webhookId has no schema description), and the description only says 'by id'. Its campaignId statement largely duplicates the schema's own description of the GROWSURF_CAMPAIGN_ID default, so it adds little beyond the structured field.

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 ('Remove a webhook from your GrowSurf program by id'), which inherently separates it from the sibling list/create/update/test webhook tools. An agent can identify the operation and its keying parameter 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 Guidelines2/5

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

The description gives no when-to-use guidance, no prerequisites, and never names an alternative (e.g., update vs. delete vs. test webhook). It explains parameter targeting, but that is parameter semantics, not usage guidance.

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

growsurf_delete_program_resourceDelete 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. Program IDs also identify newly created programs without restarting the server.
resourceIdYes

Output Schema

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

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, idempotentHint=true and readOnlyHint=false, so the safety profile is covered. The description adds genuinely non-obvious behavior: deleting the resource does NOT delete the underlying reusable Media Center asset, which an agent could easily assume otherwise.

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 tight sentences with the destructive action stated first, then the important side-effect caveat, then the targeting rule. Nothing is redundant and no sentence is 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?

An output schema exists so return values need no explanation, and annotations cover safety semantics. Adding the media-asset preservation note and the id-fallback rule makes this nearly complete for a 2-param delete; the only real gap is the unexplained resourceId.

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 50%: campaignId is documented in the schema and the description reinforces its fallback behavior, but resourceId has no description in either place, leaving the agent to guess where the id comes from (e.g., list_program_resources). The description compensates on one param but not the other.

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?

States a specific verb and resource ('Delete a participant resource from your GrowSurf program') and immediately scopes it by clarifying that the reusable Media Center asset survives. This separates it from the media-asset concept and from sibling deletes like delete_campaign_reward, though it never names an alternative tool by name.

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 targeting context ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID'), which tells the agent how to address the call, but there is no explicit when-to-use vs. when-not-to-use guidance and no pointer to update_program_resource for modification instead of deletion.

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

growsurf_email_participantEmail 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. Program IDs also identify newly created programs 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.6/5.0
Behavior5/5

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

Beyond the annotations (destructive, non-idempotent, open-world), the description discloses real behavior: automatic compliance injection (company name, postal address, unsubscribe link), suppression of unsubscribed participants, the verification prerequisite with a 400 failure mode, and that delivery is only 'accepted' rather than confirmed. This is meaningful context an agent could not infer from 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 action is front-loaded in the first clause, then mode selection, then compliance/prerequisites, then targeting default. Dense but every sentence carries information; it reads as a single long paragraph rather than clearly separated clauses.

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 7-parameter, no-required-field mutation tool with an output schema, the description covers the required pieces: mode selection, addressing, defaults, prerequisites, error behavior, and post-send semantics. Return-value documentation is correctly left to the output schema.

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 57%, and the description compensates: it explains the emailType/subject+body exclusivity in prose, clarifies participantId vs participantEmail as alternatives, mentions the optional preheader that has no schema description, and confirms the campaignId fallback to GROWSURF_CAMPAIGN_ID.

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 ('Send an email to a participant') and immediately names the two addressing options (participant ID or email), which clearly separates it from sibling participant tools like get_participant or update_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?

It gives strong context for the two mutually exclusive modes ('Provide EITHER emailType ... OR subject + body') and states the prerequisites for sending (verified team, verified custom email domain, 400 until verified). It stops short of explicit when-not-to-use exclusions in the description itself, since the unsendable template list lives in the schema.

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

growsurf_embeddable_element_snippetEmbeddable 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/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 the output is HTML and may include auth attributes, but it does not clarify what those attributes do, what side effects they imply, or whether participant data becomes embedded in the snippet.

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, front-loaded sentence with no filler or redundant wording. It conveys the core action and the main optional capability efficiently.

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 nested participant object, enum choices, and the withAuthAttributes flag, the description is too thin. It does not explain what participant is for, when auth attributes should be used, or how the returned snippet relates to the embeddable element. The output schema covers return shape but not the decision-making needed for 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 0%, so the description must compensate, but it only hints at 'embeddable element' and 'optional auth attributes.' It does not explain the participant object or provide meaning for the element enum values, leaving a significant semantic gap for the agent.

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 uses a specific verb ('Generate') and a specific resource ('HTML snippet for a GrowSurf embeddable element'), making the tool's basic purpose clear. It is distinct from the many campaign/analytics tools, though it does not explicitly differentiate itself from sibling snippet-oriented tools like client_snippets or grsf_config_snippet.

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 provides no guidance about when to use this tool versus alternatives, no prerequisites, and no exclusions. An agent is given no context about when an embeddable element snippet is the right choice compared to other snippet or integration tools.

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

growsurf_get_campaignGet ProgramA
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. Earned reward records belong to the individual participant. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs 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

A3.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 safety is covered. The description adds real behavioral context beyond them: embedded reward settings do not imply a reward was earned, approved or delivered, which prevents an agent from misreading the response.

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?

Three sentences with the purpose front-loaded and no filler. The reward-semantics caveat is a useful clarification, though it occupies two of the three sentences for a point that is secondary to the call itself.

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-required-param, read-only tool with an output schema and full schema coverage, the description supplies what the structured fields do not: the reward-interpretation caveat and the id-resolution rule. Only the absence of sibling routing keeps it short of complete.

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 parameter's own description already documents the GROWSURF_CAMPAIGN_ID fallback, so the description's restatement adds no new meaning. Baseline 3 applies when the schema carries the full load.

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?

States a specific verb and resource: 'Fetch your GrowSurf campaign (program) details via REST.' An agent can tell this is a single-campaign read rather than a list, but the description never names the nearest siblings (growsurf_list_campaigns, growsurf_get_campaign_design/options/emails) to sharpen the boundary.

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 only conditional given is parameter resolution ('Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID'), which is invocation mechanics rather than guidance. Nothing says when to reach for this tool versus the many other campaign-scoped getters or the list tool.

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_analyticsGet 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. Program IDs also identify newly created programs 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/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description adds genuinely non-obvious behavioral context: the cohort-grouping field differs by program type, null/zero must be interpreted against coverageStartAt/state/reason, and unavailable history is not evidence an action never occurred. It stops short of disclosing pagination, result size, or authorization requirements.

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?

Front-loads the core action, then layers cohort semantics, stage order, defaults, interpretation caveat, and target resolution in compact sentences. Every sentence carries actionable information with no 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 present, the description need not explain return values, and it covers everything else an agent needs: cohort boundary pairing, defaults for timezone/interval/window, the funnel stages, and how to read null or zero results. Complete for a six-parameter analytics query.

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 100% so the baseline is 3, but the description adds real meaning: the 7/30-day window applies per participant from eligibility, cohort bounds must be omitted together for the default mature cohort, and campaignId falls back to GROWSURF_CAMPAIGN_ID. This goes beyond restating 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?

States a specific verb (Fetch) and a precisely scoped resource (strict activation for eligible participants in one enrollment cohort), and enumerates the ordered funnel stages. It does not, however, name or distinguish itself from the closely related growsurf_get_campaign_analytics sibling, leaving the agent to infer the boundary.

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?

Offers one concrete usage rule ('Omit both cohort bounds for the latest fully matured cohort') and a fallback for campaignId, which implies intended usage. But it never states when to choose this tool over get_campaign_analytics or get_participant_analytics, nor any prerequisites or exclusions, so selection guidance is only implied.

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

growsurf_get_campaign_analyticsGet Program 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. 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. Explicit dates must both be positive Unix timestamps in milliseconds, with endDate >= startDate and a maximum span of 1825 days. timezone and platform apply to engagement only. Targets campaignId if passed, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNo
endDateNoEnd of the timeframe, positive Unix timestamp in milliseconds. Supply `startDate` too; `endDate` must be >= `startDate` and at most 1825 days later.
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, positive Unix timestamp in milliseconds. Supply `endDate` too; the window must span at most 1825 days.
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs 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

A3.9/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), so the bar is lower. The description adds real behavioral context beyond them: default window of 365 days with a 1825-day cap, default `interval=total`, engagement-only applicability of `timezone`/`platform`, and the `coverageStartAt`/`state`/`reason` semantics that separate measured zeroes from partial history. It does not mention auth or rate limits, but its contributions are substantive.

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 purpose and metrics, then moves efficiently through interval, include, timeframe, and targeting. It is dense and somewhat long, with minor overlap against schema text (Unix-ms date constraints restated), but nearly every sentence carries actionable information.

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 present, return values need not be re-explained, yet the description helpfully clarifies conditional outputs (`series`, engagement sub-fields, previousPeriod) and default resolution for `campaignId` via GROWSURF_CAMPAIGN_ID. For an 8-parameter read tool with rich annotations and an output schema, nothing needed 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?

Schema description coverage is already 88%, so baseline is 3. The description goes beyond it by explaining what `include` values yield (e.g. `engagement` groups unique active/sharing/repeat/retained participants by portal-view and share timing), clarifying that `timezone`/`platform` apply to engagement only, and noting the default `days=365` that the schema omits. This meaningfully supplements the parameter docs.

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 specific verb (Fetch) and resource (analytics for your GrowSurf program) and enumerates the metrics returned (participants, referrals, impressions, per-channel shares, affiliate revenue/commission/payout). This is clearly distinguishable from sibling analytics tools like get_campaign_activation_analytics or get_participant_analytics by scope, though it never names those siblings explicitly.

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 how to shape the request (pass `interval` for a series, `include` values for extra views, `days` vs explicit date window) but gives no guidance on when to choose this tool over sibling analytics tools. Usage is implied rather than stated with conditions or 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_designGet Program 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, the website widget under widget, the participant Traffic report under trafficInsights (it starts on for new affiliate programs and hidden for referral programs, and every setting is returned with its default copy), 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. Program IDs also identify newly created programs 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.
widgetNoThe website widget — the invite that sits in a corner of the customer's own site. It renders as a button or as a card, and its card folds back into the button when a visitor closes it. Both audience switches start off, so a program shows nothing until one is turned on.
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).
trafficInsightsNoThe Traffic report participants can open from the GrowSurf window: visits to their share link over time and where those visits came from. It starts on for new affiliate programs and hidden for referral programs. Every setting is returned, with the default copy for anything not changed. Labels cannot be blank.
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

A3.8/5.0
Behavior4/5

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

Annotations already cover the safe-read profile (readOnlyHint, idempotentHint, destructiveHint=false), so the bar is lower, and the description still adds real behavior: missing/unknown enum values fall back to INITIALS, stored nulls return as null while omitted fields use localized defaults, and the confirmation section is omitted when empty. It stops short of noting auth/permission requirements or error behavior, so not a 5.

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

Conciseness3/5

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

The purpose is correctly front-loaded in the opening clause, but the rest is a single ~120-word run-on sentence packing in every returned field. With an output schema present, much of this enumeration duplicates structured data, making the wall of text hard to scan.

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 one-parameter read tool with full annotations and an output schema, the description is more than complete on behavior and edge cases. Its only weakness is that it over-explains return contents that the output schema already carries.

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% for the single campaignId parameter, and the description's note that it targets campaignId when passed and GROWSURF_CAMPAIGN_ID otherwise largely restates the schema. Baseline 3 is appropriate; no new syntax or format detail is added.

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 ('Fetch the configured design fields for your GrowSurf program') and enumerates the exact sections returned, which cleanly separates it from sibling readers like growsurf_get_campaign (general), growsurf_get_campaign_options, and growsurf_get_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 Guidelines3/5

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

Usage is only implied: the field enumeration signals this is the design-config reader, and the update counterpart (growsurf_update_campaign_design) is never named. The only explicit direction is about which id is targeted, which is parameter behavior rather than when-to-use 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_emailsGet Program EmailsA
Read-onlyIdempotent
Inspect

Fetch the Emails tab configuration for your GrowSurf program, including participant and admin email templates, settings, and read-only fields. settings.sender.fromEmail is read-only and can be changed in the dashboard after domain verification. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs 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

A3.5/5.0
Behavior4/5

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

Annotations already establish readOnlyHint, idempotentHint, and non-destructive status, so the bar is lower. The description still adds real value: it flags that settings.sender.fromEmail is read-only and must be changed in the dashboard after domain verification, a constraint not captured by annotations or schema.

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 sentences, front-loaded with the fetch scope, then the read-only caveat and targeting fallback. No filler, though the targeting sentence partially duplicates the schema.

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?

An output schema exists, so return values need not be explained. The description covers what is returned, a notable read-only caveat, and id resolution, which is adequate for a single-optional-param read 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 100% and the schema already documents the campaignId default to GROWSURF_CAMPAIGN_ID, so the description's restatement of targeting adds little. Baseline 3 applies when the schema carries the parameter semantics.

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?

States a specific verb (Fetch) and resource (Emails tab configuration) and enumerates what's included: participant and admin email templates, settings, and read-only fields. It is distinguishable from the sibling growsurf_update_campaign_emails by the read-only framing, though it never 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 Guidelines2/5

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

No statement of when to use this tool versus growsurf_update_campaign_emails or the other get_campaign_* reads. The only conditional given is which id is targeted, which is parameter behavior rather 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_campaign_installationGet Program 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. Program IDs also identify newly created programs 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`. Known shared-platform root domains, such as `github.io`, do not grant access. Add your site's hostname, such as `https://piedpiper.github.io`, or a domain you own. Path-based shared hosts, such as `unbouncepages.com`, require a domain you own.
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.
instructionSelectionsNoSaved choices shown in the Program Editor installation guide.
useGrowSurfHostedLinksNoUse GrowSurf-hosted referral links that route clicks by the visitor's device. Mainly for mobile apps.

TDQS

A4/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 safety profile is covered. The description adds genuine context beyond them: it returns the full object with every field's current value and mirrors the update payload shape, which tells the agent the response is a complete, re-sendable configuration snapshot.

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 tightly written sentences, front-loaded with what is fetched and followed by the return shape and target resolution. No filler 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?

With an output schema present, the description need not enumerate return fields, and it correctly summarizes the shape instead. Combined with full annotation coverage and a single parameter, an agent has what it needs to invoke the call correctly, though no explicit routing guidance against sibling configuration readers is offered.

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 single campaignId parameter already documents the GROWSURF_CAMPAIGN_ID fallback, so the description largely restates what the schema provides. No additional format or resolution semantics are added beyond the 'if you pass it, otherwise' default rule.

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) and named resource (Installation tab configuration for your GrowSurf program) and scopes it to embed/installation and tracking setup. It also implicitly distinguishes itself from the write counterpart by noting it returns the same shape you send back on update, so an agent can separate it from growsurf_update_campaign_installation without opening either 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 which program is targeted (campaignId vs GROWSURF_CAMPAIGN_ID) and implies the read-before-write pairing with update, but it never states when to use this tool versus alternatives such as growsurf_client_snippets, growsurf_embeddable_element_snippet, or growsurf_update_campaign_installation. Usage 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_get_campaign_optionsGet Program 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. Program IDs also identify newly created programs 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.9/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 safety profile is covered. The description adds real value beyond them: it states the response contains every field with its current value, that it targets campaignId or falls back to the GROWSURF_CAMPAIGN_ID env var, and warns that autoFulfillRewards: false does not prove a reward went undelivered — a genuine misinterpretation guard.

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 core purpose, then the return shape, then the default-targeting rule and the field caveat. Dense but every sentence carries information; the parenthetical field list is slightly long but aids scope recognition.

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?

With an output schema present, the description needn't explain return values, yet it usefully frames the return as update-compatible. For a single-optional-parameter read call it is essentially complete, though it says nothing about failure or permission behavior.

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?

Only one parameter with 100% schema description coverage, so the baseline is 3. The description restates the campaignId/GROWSURF_CAMPAIGN_ID fallback that the schema already documents, adding no new syntax or format detail.

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) and a precisely scoped resource (the Options tab configuration of a GrowSurf program), then enumerates the content domains it covers (referral triggers, anti-fraud, affiliate enrollment, notifications). This clearly separates it from siblings like get_campaign_design, get_campaign_emails, and update_campaign_options.

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?

Usage is implied rather than stated: it notes the return is 'the same shape you send back on update,' which hints at the read-before-write pattern with update_campaign_options, but no alternative tool or condition is named explicitly. The autoFulfillRewards caveat is interpretive guidance, not a when-to-use rule.

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

growsurf_get_participantGet 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. 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. Program IDs also identify newly created programs 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`.
leadCountNoPending referrals that have not converted yet.
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.1/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, non-destructive and closed-world, so the safety profile is covered. The description adds genuine interpretive context beyond that — that a zero referralCount is consistent with CREDIT_AWARDED, and that approved/status/isFulfilled record fulfillment marking rather than delivery — which prevents real misreads of a participant record.

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?

Three sentences, purpose front-loaded, no filler. The middle sentence on referral/reward field semantics is dense and arguably overlaps the output schema's territory, but it is not padding.

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?

With an output schema present the description needn't explain return shape, and annotations cover the safety profile, so the remaining job is purpose, lookup keys and targeting — all covered. Only the missing routing guidance against siblings (list vs get vs analytics/activity logs) and not-found behavior keep it from a 5.

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% (participantId and participantEmail are undocumented in the schema). The description compensates by stating both identifiers work as lookup keys and by restating the campaign targeting rule ('targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID'), covering all three parameters meaningfully.

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?

Names a specific verb (Fetch), the resource (a single participant), and both lookup keys (participant ID or email address). The word 'single' implicitly separates it from the sibling growsurf_list_participants, so an agent can route without opening the schemas.

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?

Usage is only implied — 'single participant' hints this is the targeted-fetch counterpart to list_participants, and the campaign-targeting sentence gives a calling context. There is no explicit when-to-use/when-not statement and no named alternative such as list_participants or get_participant_analytics, which matters given the large sibling surface.

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_logsGet 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. Program IDs also identify newly created programs 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.1/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 safety profile is covered. The description adds genuinely new behavioral detail: the response `offset` acts as the next-page cursor and is null when exhausted, and campaign resolution falls back to an env var. Missing only things like log retention or rate limits.

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?

Three dense sentences, front-loaded with the core purpose, followed by pagination mechanics and the campaign fallback. No filler, though the pagination and defaulting details make it slightly packed.

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?

An output schema exists, so return values needn't be explained, yet the description still clarifies the pagination cursor semantics that agents would otherwise have to infer. Combined with the low schema coverage it covers enough for correct invocation; a brief note on what an activity log entry contains would close the remaining 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?

Schema coverage is only 20%, so the description must compensate, and it largely does: it documents the 1-100 limit range with a default of 20, the offset skip behavior, the ID-or-email alternative for identifying the participant, and campaign targeting. Only the participantId/participantEmail format details remain thin.

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 ('List a participant's activity logs'), names the two accepted lookup keys (participant ID or email), and specifies ordering ('most recent first') and pagination model. This is clearly distinguishable from siblings like growsurf_get_participant or growsurf_get_participant_analytics.

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 the campaignId fallback to GROWSURF_CAMPAIGN_ID, which is useful context for invocation, but gives no explicit guidance on when to reach for this tool versus growsurf_get_participant or growsurf_get_participant_analytics. Usage is implied rather than stated.

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

growsurf_get_participant_analyticsGet 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. Filter optional series and email data with days (up to 1825) or both startDate and endDate as positive Unix timestamps in milliseconds. endDate must be at or after startDate, and the range can span at most 1825 days. These date parameters do not filter 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, positive Unix timestamp in milliseconds. Supply `startDate` too; `endDate` must be >= `startDate` and at most 1825 days later.
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, positive Unix timestamp in milliseconds. Supply `endDate` too; the window must span at most 1825 days.
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs 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.3/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive, but the description adds non-obvious behavior: a null milestone with partial `state` means unknown rather than never-happened, the API returns 400 for unknown `include` values, and date params deliberately do not filter the base response or activation milestones. It stops short of auth or rate-limit context, but the added semantics are substantive.

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 base response contents, then include options, then filtering rules, then campaign targeting — a logical progression. It is dense and repeats the date-window constraint already in the schema, but nearly every sentence carries operational weight.

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 an output schema exists, the description needn't explain return shapes, and it correctly focuses on include semantics, filter scoping, and targeting. The anyOf participantId/participantEmail requirement is only implied ('by ID or email') rather than stated as a mutual requirement, 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?

With 75% schema coverage the schema documents most params, but the description adds real meaning: the 1825-day cap and ordering constraint, that date filters scope only optional series/email data, and that `campaignId` falls back to GROWSURF_CAMPAIGN_ID. It goes beyond restating the schema, though it repeats some schema text.

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 ('Fetch analytics for one participant') and pins the lookup key ('by GrowSurf participant ID or email'). The 'one participant' scope implicitly separates it from sibling campaign-level analytics tools like growsurf_get_campaign_analytics and growsurf_get_campaign_activation_analytics.

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 concrete operational guidance: add `activation` for the eligibility anchor, request both `activation` and `series` for covered buckets, and filter with `days`/`startDate`/`endDate`. However, it never names alternative sibling tools (e.g. participant activity logs vs. campaign analytics) or states when this tool should be chosen over them.

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_destinationGet 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. Program IDs also identify newly created programs 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`, `VENMO`, and `WISECOM`.
enabledProvidersNoPayout provider identifiers enabled for this program. Values are open-ended; current examples include `PAYPAL`, `VENMO`, and `WISECOM`.

TDQS

A4.1/5.0
Behavior5/5

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

Annotations already cover the read-only/idempotent/non-destructive profile, and the description goes well beyond them: it discloses what fields are returned per provider (status, confirmed email, recipient type, repair reason) and the semantics of activeProvider being null until confirmation. Rich behavioral context that the annotations could not convey.

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-loads the core purpose, then layers output detail and targeting logic without redundancy. Slightly dense but every clause carries information; nothing reads as 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?

With an output schema present, return values need not be documented, yet the description helpfully characterizes them. Targeting defaults are covered; the only gap is the missing when-to-use guidance, which is minor for a read 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 coverage is only 33% (campaignId documented, participantId/participantEmail bare). The description compensates partially by noting the participant can be identified by ID or email and by explaining the campaignId fallback to GROWSURF_CAMPAIGN_ID, but it adds no format or validation detail for the identifier params.

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 (Get) and resource (participant's payout-destination status), plus scope (across every payout provider enabled for the program). An agent can distinguish it from the sibling growsurf_request_participant_payout_destination_confirmation purely from the description.

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?

Explains how to target the program (campaignId or GROWSURF_CAMPAIGN_ID), which is useful context, but never says when to use this versus alternatives like get_participant or request_participant_payout_destination_confirmation. Usage is implied rather than stated.

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

growsurf_get_teamGet 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/destructiveHint, so safety is covered. The description adds value beyond annotations by specifying what is not returned (personal profiles, internal identifiers) and clarifying the meaning of verificationStatus, which is useful behavioral 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?

Three sentences, all informative, with the main purpose front-loaded in the first sentence. No filler or redundancy; each sentence contributes a distinct piece of information (what it fetches, verification meaning, and non-returned data).

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 zero parameters, an output schema, and full annotation coverage, the description rounds out the picture by explaining verification semantics and data exclusions. No essential information is missing for a read-only fetch tool.

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 no parameter semantics to explain. The description's note about environment variables (API key vs campaign ID) adds relevant configuration context beyond the empty 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 opens with a specific verb and resource: "Fetch the team bound to the API key or OAuth connection." This clearly identifies the tool's function and distinguishes it from sibling tools like get_campaign or list_campaigns, even without naming an 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 gives useful context by explaining that verificationStatus must be VERIFIED before a program can email participants, implying when this tool is relevant. It also states the credential requirements (requires API key, not campaign ID), which helps route usage, though it does not explicitly name alternative tools or exclusions.

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

growsurf_grsf_config_snippetGenerate Participant Auto Authentication CodeB
Read-onlyIdempotent
Inspect

Generate the HTML code for GrowSurf Participant Auto Authentication using window.grsfConfig. The generated code belongs in <head>, 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

B3.3/5.0
Behavior3/5

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

Annotations already declare readOnly, idempotent, and non-destructive behavior, so safety is covered. The description adds that the output is generated HTML placed in <head>, which is useful context, but says nothing about why certain flags exist, what the generated code does at runtime, or any auth/rate constraints.

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 tight sentences, no filler, with the core purpose front-loaded and the placement constraint appended where it is most useful.

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?

An output schema exists, so return values need no explanation, and the annotations cover the safety profile. However, for a 7-parameter code generator the description leaves all parameters and most behavioral nuance undocumented, making it only partially 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 0% across 7 parameters, so the schema documents nothing. The description only alludes to window.grsfConfig and never explains hash, email, campaignId, affiliateJoin, useCampaignIdPlaceholder, enableParticipantAutoAuth, or includeAutoAuthCommentHeader, leaving the agent to guess at all inputs.

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?

States a specific verb (Generate) plus resource (HTML code for Participant Auto Authentication) and even names the mechanism (window.grsfConfig). It distinguishes itself from generic snippet siblings by specifying the auto-auth use case, though it does not explicitly name the closest alternatives like 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 Guidelines3/5

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

The placement hint ('belongs in <head>, before the GrowSurf Universal Code') clarifies how the output is consumed but not when to select this tool over the other snippet tools. Usage is only implied through the auto-auth context; there are no explicit when/when-not rules or named alternatives.

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

growsurf_integration_guideIntegration 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.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, which fully cover the safety/mutation profile; the description does not contradict these. The added 'happy-path' qualifier is a useful behavioral signal that this produces a straightforward plan rather than troubleshooting edge cases (unlike growsurf_troubleshoot_referral_tracking). However, the description does not disclose what the plan contains or its limitations, beyond the happy-path scope.

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

Conciseness3/5

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

The single sentence has no wasted words and is well front-loaded. But it is so terse that the tool is under-specified rather than efficiently concise. There is room to add meaningful guidance without sacrificing brevity, so the conciseness is adequate but not exemplary.

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 5 optional parameters, 3 enums, and an output schema, the description is incomplete. It does not explain how the parameters shape the generated plan, what 'happy-path' means operationally, or how this guide differs from the many sibling guide/snippet/advisor tools. The output schema mitigates some return-value uncertainty, but the description leaves too much about behavior and parameter influence unexplained.

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% with 5 parameters, so the description bears the full burden of explaining parameter semantics, but it mentions none of them. While parameter names like programType and singlePageApp are fairly self-explanatory, enum values such as 'signup_plus_qualifying_action' and 'token_in_url' are opaque and unaddressed. The description adds zero value to the input schema at a coverage level where it absolutely must compensate.

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 uses a specific verb ('Generate') with a specific resource ('GrowSurf integration plan') and scopes it as 'guided, happy-path' covering referral and affiliate. This is clear about what the tool produces. However, it does not differentiate from the very similar sibling growsurf_program_design_advisor, which likely also delivers advisory/plan guidance, so an agent could confuse the two.

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 alternatives such as growsurf_program_design_advisor, growsurf_api_library_snippets, or growsurf_client_snippets. No exclusions, prerequisites, or context are given. The description merely states what it does, leaving the agent to infer when 'happy-path integration planning' is the right choice.

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

growsurf_list_campaign_rewardsList Campaign RewardsA
Read-onlyIdempotent
Inspect

List your GrowSurf program's configured Campaign Rewards, including switched-off rewards and rewards whose group is not selected. Deleted rewards are excluded. A reward can be earned only when it also appears in the campaign response's embedded rewards array. These settings do not establish that a participant earned or received a reward; earned reward records belong to the individual participant. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
rewardsNoThe program's configured Campaign Rewards, including switched-off rewards. Deleted rewards are excluded.
rewardEvidenceNoWhat this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds real value beyond them: it discloses inclusion rules (switched-off rewards and unselected-group rewards appear; deleted ones do not) and warns that these settings do not imply a participant earned a reward, which prevents a common misinterpretation.

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 scoping and the inclusion/exclusion rules are front-loaded, and the earned-reward caveat follows immediately. It is a fairly dense multi-sentence block, but each sentence carries distinct information rather than padding.

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 present, return-value detail is unnecessary, and the description fully covers scope, include/exclude semantics, the earned-vs-configured distinction, and targeting behavior. An agent has everything needed to call this correctly.

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%, so the single campaignId parameter and its GROWSURF_CAMPAIGN_ID fallback are already documented in the schema. The description restates that targeting behavior without adding syntax, format, or edge-case detail, so the baseline 3 holds.

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 gives a specific verb (List) and resource (configured Campaign Rewards), then precisely bounds scope: includes switched-off and non-group-selected rewards, excludes deleted rewards. It also disambiguates from a confusingly similar concept (earned reward records on participants), so an agent can distinguish it from siblings like get_participant or the reward CRUD 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 establishes when this tool is the right source (configuration-level reward definitions) and when it is not (earned/received reward records, which belong to the participant). However, it does not explicitly name alternate tools (e.g., growsurf_get_campaign or growsurf_get_participant) that an agent should reach for instead, leaving that routing 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_campaignsList ProgramsA
Read-onlyIdempotent
Inspect

List the GrowSurf programs available to the bound team, including their IDs for program selection. 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.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so safety is covered. The description adds genuinely new behavior: deleted programs are filtered out, IDs are included, and no campaign ID binding is needed. It says nothing about ordering, pagination, or result size limits.

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 short sentences, front-loaded with what is returned and immediately followed by the two facts an agent needs (deleted items excluded, no campaign ID required). No 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?

An output schema exists, so return-shape explanation is unnecessary, and the annotations carry the safety profile. For a zero-parameter list tool the description supplies everything needed to select and 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 tool takes zero parameters, which is the baseline-4 case, and the description correctly signals that no GROWSURF_CAMPAIGN_ID binding is required. There is nothing further for it to add.

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?

States a specific verb+resource ('List the GrowSurf programs') plus the scope ('available to the bound team'), which cleanly separates it from the singular growsurf_get_campaign and the reward/resource list siblings. It does not explicitly name a sibling, and it uses 'programs' while the tool name and the rest of the toolset use 'campaigns', a terminology mismatch an agent must bridge.

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?

'including their IDs for program selection' and 'Does not require GROWSURF_CAMPAIGN_ID' both describe when this tool is the right entry point (discovering a campaign ID before calling the many campaign-scoped tools). No explicit exclusions or named alternatives are given, 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_list_campaign_webhooksList 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. Program IDs also identify newly created programs without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
webhooksNoWebhooks configured for the program.

TDQS

A3.8/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 a genuinely useful behavioral fact beyond that: secrets are never returned, which sets expectations about the payload's sensitivity.

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 short sentences, with the resource and the parenthetical security note front-loaded and the targeting rule following. Every clause carries information; there is 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?

An output schema exists, so return-value detail is unnecessary, and the secret-suppression note covers the one surprising aspect of the response. Nothing an agent needs to call this correctly is missing, though pagination or ordering behavior is not addressed.

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?

With only one parameter and 100% schema description coverage, the schema fully documents campaignId, including the env-var fallback. The description merely restates that same targeting rule, adding no new syntax or format detail beyond structured data.

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 gives a specific verb and resource ('List your GrowSurf program's webhooks') and clarifies the parent-resource relationship, which distinguishes it from the create/update/delete/test webhook siblings. It stops short of explicitly naming those siblings as alternatives.

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 explains the targeting rule (pass campaignId or fall back to GROWSURF_CAMPAIGN_ID) but gives no explicit when-to-use guidance, e.g. 'use before updating/deleting a webhook' or 'use create_campaign_webhook to add one.' Usage is implied by the verb, not stated.

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

growsurf_list_integrationsList IntegrationsA
Read-onlyIdempotent
Inspect

List the integrations available to your GrowSurf program, including Stripe, PayPal, Wise, Mailchimp, Slack, Zapier, and Webhooks. Each entry includes connected (credentials stored), enabled (working), autoDisabled (delivery stopped after repeated failures until the user reconnects), and connectUrl (dashboard connection link). Integrations that do not apply to the program type are omitted, such as Wise on a referral program. Read-only. Account connection takes place in the GrowSurf dashboard and is not available through the API. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
integrationsNoEvery integration this program can connect, in the order the GrowSurf dashboard lists them.

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive), so the bar is lower; the description still adds real behavior detail such as the meaning of `autoDisabled` (delivery stopped after repeated failures until reconnect) and the omission rule for program-type-inapplicable integrations. It does not discuss pagination or failure modes, but the added semantics are substantive.

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 core action and covered integrations, then dense supporting detail. Every sentence carries information (field meanings, omission rule, read-only, connection note, targeting), though it runs a little long for a simple list tool.

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?

An output schema exists, so return-value explanation is not strictly required, and the description still sketches the key fields. Combined with full annotation and schema coverage, an agent has what it needs to call the tool correctly; only explicit sibling routing 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% for the single `campaignId` parameter, so the schema already documents its type and default. The description only restates the fallback to `GROWSURF_CAMPAIGN_ID`, adding no syntax or format detail beyond what the schema provides — baseline 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?

States a specific verb (List) and resource (integrations) plus the exact set covered (Stripe, PayPal, Wise, Mailchimp, Slack, Zapier, Webhooks). It is clearly distinguishable from siblings like growsurf_get_integration_connect_link or growsurf_integration_guide.

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?

Provides useful context (connection happens in the dashboard, not via the API; non-applicable integrations are omitted), which implies the tool's scope. However, it never explicitly states when to use this versus the sibling connect-link or integration-guide tools, leaving selection 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_participantsList 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. Pass metadata to return only participants whose stored metadata matches every given key and value exactly, for example { "customerId": "12345" } to look someone up by your own customer ID; filtered results are ordered by participant ID. Results include participant IDs. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
nextIdNoParticipant ID returned as `nextId` from the previous page.
metadataNoExact-match filter on participant metadata, up to 3 keys, for example `{ "customerId": "12345" }`. Values compare as strings.
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs 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/5.0
Behavior4/5

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

Annotations already declare readOnlyHint/idempotentHint/destructiveHint=false, so safety is covered. The description adds real behavioral context beyond that: newest-page-first ordering, nextId-based paging, metadata-filtered results ordered by participant ID, and the GROWSURF_CAMPAIGN_ID fallback.

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 core listing action, then paging, filtering, and targeting in a logical order. Dense but each clause (defaults, ordering, lookup use case) carries information; slightly long-winded with minor schema overlap.

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?

An output schema exists, so return values need not be spelled out, though the description helpfully notes results include participant IDs. Paging, filtering, defaults, and campaign targeting are all covered; only auth/permission context is unstated.

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 75% and the description adds genuinely new meaning: the `limit` default of 10 (absent from the schema), the AND semantics and exact-string matching of `metadata`, and the campaignId env-var default. It mostly complements rather than repeats 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?

States a specific verb+resource ('List participants in your GrowSurf program') and adds scope details (newest page first, campaign targeting). It is clearly distinguishable from get_participant, but never explicitly names an alternative, so it stops short of the top band.

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 concrete usage contexts: pass response nextId to continue paging, and pass metadata to look up a participant by your own customer ID. No when-not guidance or explicit alt-tool routing is given, so it is clear context without exclusions.

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

growsurf_list_program_resourcesList 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. Program IDs also identify newly created programs without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resourcesNoThe program's resources in participant display order, including drafts.

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, non-destructive and closed-world, so the safety profile is covered. The description adds genuinely new behavioral context beyond the annotations: results include drafts and are returned in display order, which affects how an agent interprets the output.

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, no filler, with the core purpose front-loaded ahead of the targeting rule. Every clause (drafts inclusion, display order, fallback ID) carries actionable information.

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?

An output schema exists, so return values need not be explained, and the description covers scope, ordering, and ID resolution. It is essentially complete for a one-parameter list tool, with only minor gaps such as result volume or pagination hints.

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% for the single campaignId parameter, and the schema already states the GROWSURF_CAMPAIGN_ID default. The description restates that default without adding format, resolution, or precedence detail, so the baseline 3 applies.

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 gives a specific verb and resource ('List the participant resources configured for your GrowSurf program') plus a scope qualifier ('including drafts'), which clearly separates it from the create/update/delete program-resource siblings. It stops short of explicitly naming an alternative tool, so it lands at a clear-but-not-routing 4.

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?

Usage is only implied by the verb 'List' — there is no statement of when to call this versus siblings like growsurf_list_campaign_rewards or the get/update resource tools. The only conditional content ('targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID') is parameter behavior, not when-to-use guidance.

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

growsurf_mobile_sdk_guideMobile SDK GuideC
Read-onlyIdempotent
Inspect

Generate native iOS/Android SDK 0.6.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

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, openWorldHint=false, and destructiveHint=false, so the safety profile is covered. The description adds only the topical scope of the generated output; it says nothing about auth requirements, whether guidance is version-pinned behavior, or any rate/format constraints, so it adds modest 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.

Conciseness4/5

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

A single front-loaded sentence naming the deliverable first and the covered topics second, with no filler. It is tight, though slightly under-specified rather than genuinely concise in the sense of covering what an agent needs.

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?

An output schema exists, so return values need not be explained, but for a 7-parameter tool with zero schema description coverage and no required fields, the description leaves the agent unable to reason about how platform, attributionProvider, participantState, or the boolean flags shape the generated guide.

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% across 7 parameters, and the description explains none of them. 'attribution' loosely hints at attributionProvider, but platform, campaignId, mobilePublicKey, participantState, includeInstallSnippets, and serverVerifiedQualifyingAction receive no meaning from either the schema or the description.

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?

States a specific verb and resource ('Generate native iOS/Android SDK 0.6.0 guidance') and enumerates covered topics (attribution, shareUrl, trackShare, native Window), so the agent knows exactly what content comes back. It does not, however, differentiate itself from similar generation siblings such as growsurf_client_snippets, growsurf_api_library_snippets, or growsurf_integration_guide.

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 when-to-use guidance and no mention of alternatives, even though several sibling tools (client_snippets, api_library_snippets, integration_guide, grsf_config_snippet) plausibly overlap with SDK guidance. The agent must infer the selection condition entirely on its own.

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

growsurf_participant_auth_hashCompute Participant Auth HashC
Read-onlyIdempotent
Inspect

Compute the server-side SHA-256 HMAC for GrowSurf Participant Auto Authentication. affiliateJoin requires permission for this signed-in user to 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

C2.9/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, non-destructive and closed-world, so safety is covered. The description adds that this is a server-side SHA-256 HMAC computation, which is useful context beyond annotations, but it does not explain how the `participantAuthSecret` is handled or where the resulting hash is consumed.

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 short sentences with the core purpose front-loaded and no filler. The second sentence is terse to the point of being ambiguous, but the overall structure is efficient.

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?

An output schema exists so return values need not be described, but the description omits key context for a tool that consumes a secret: required permissions, where the hash is applied, and the meaning of two of three parameters. For a security-adjacent auth tool this is thin.

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 carries the full burden. It only hints at `affiliateJoin` (permission to join the affiliate program directly) and says nothing about `email` or the security-sensitive `participantAuthSecret`, leaving two of three parameters undocumented.

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?

States a specific verb (Compute) and resource (server-side SHA-256 HMAC for GrowSurf Participant Auto Authentication), which is a distinct concept not covered by any sibling tool. The purpose is clear, though it does not explicitly contrast itself with siblings such as growsurf_add_participant or the token/mobile-auth tools.

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 statement of when to call this tool versus alternatives, nor any prerequisites (e.g., that it is a server-side operation requiring the participant auth secret). The second sentence only vaguely ties `affiliateJoin` to joining the affiliate program; an agent must infer the calling context.

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_filePrepare Program Resource FileAInspect

Prepare a local file for a FILE Program Resource. Accepts a safe file name, matching supported MIME type, and padded base64 bytes, up to 10 MB. GrowSurf requests a one-time ticket and uploads only to the secure HTTPS destination selected by GrowSurf. Returns the original uploadTicket and uploadResult required for file resource creation or replacement. Altered upload results are not valid. The tool does not accept upload URLs or credentials and never retries an ambiguous upload. Requires GROWSURF_UPLOAD_ALLOWED_ORIGINS on the server; without it, only LINK and TEXT resources are available. Targets campaignId if supplied, 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. Program IDs also identify newly created programs 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.1/5.0
Behavior5/5

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

The annotations only say not-readOnly, openWorld, non-idempotent, non-destructive; the description adds ticket semantics, that GrowSurf itself selects the secure HTTPS destination, the no-credentials/no-URL constraint, the never-retry-an-ambiguous-upload policy, and the altered-results caveat. These are exactly the operational traits annotations cannot convey.

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-loads the purpose, then layers constraints, security, and return contract in compact sentences with no filler. Dense but every clause carries information; only the env-var and default-campaign notes could be tighter.

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 present there is no need to document the return shape, yet the description still names uploadTicket/uploadResult, and it covers size limits, MIME/extension pairing, security boundaries, retry behavior, and the server-side enablement prerequisite. An agent has everything needed to invoke this correctly rather than guess.

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%, so the schema already documents fileName, mimeType, campaignId, and fileBase64 in detail. The description mostly restates those (safe name, matching MIME, padded base64) and only adds the 10 MB ceiling and campaign-target default behavior; 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?

States a specific verb and resource ('Prepare a local file for a FILE Program Resource') and explains that the output is the uploadTicket/uploadResult needed for file resource creation or replacement, which implicitly distinguishes it from growsurf_create_program_resource and on-the-wire upload tools. It is clear, though it never names the sibling it hands off to.

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 real context for when this applies: only for FILE resources, gated on GROWSURF_UPLOAD_ALLOWED_ORIGINS (otherwise only LINK/TEXT), with an explicit 'does not accept upload URLs or credentials' exclusion. It stops short of stating the sequencing against growsurf_create_program_resource / growsurf_update_program_resource.

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

growsurf_program_design_advisorProgram Design AdvisorA
Read-onlyIdempotent
Inspect

Generate program designs, benchmarks, typical rewards, and metric definitions, including participant-to-referral and lead-to-referral ratios. Read-only. Returns a short draft, complete benchmarkFacts, a proposed configurationPlan, and unresolved decisions. Incentive amounts and qualifying actions remain unresolved unless supplied by the customer. detail: summary returns a configuration draft and reward structure; detail: full adds detailed benchmark tables. Hosted figures describe GrowSurf's high-performing programs; without a bundle, guidance is documentation-based. programType: AFFILIATE selects affiliate advice. industry: other covers local services, pets, hospitality, and 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 advisor goal differs from the program creation goal included in `configurationPlan`.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.1/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description adds value beyond that: it discloses what the tool returns (short draft, complete benchmarkFacts, proposed configurationPlan, unresolved decisions), that incentive amounts stay unresolved without customer input, and that guidance falls back to documentation-based content when no bundle is present.

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?

Purpose and read-only nature are front-loaded, and most sentences carry signal (the decisions caveat, the mode distinction, the AFFILIATE and industry: other behaviors). It is a single dense block with several mode-specific clauses that could be broken into a tighter list, but there is little outright waste.

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 12-parameter, all-optional advisor with an output schema and full annotations, the description covers mode selection, return contents, fallback behavior, and key enum semantics. An agent has enough to call it correctly; only explicit routing against sibling creation tools 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?

With schema description coverage at 92%, the schema already documents nearly all twelve parameters, so the baseline is 3. The description reinforces a few semantics (programType: AFFILIATE selects affiliate advice; industry: other covers local services, pets, hospitality, agencies; currencyISO omits dollar bands for non-USD) but largely restates what the schema provides.

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 set ("Generate program designs, benchmarks, typical rewards, and metric definitions, including participant-to-referral and lead-to-referral ratios") and immediately characterizes the artifact returned. It is clearly an advisory/planning tool, distinguishable from the many sibling mutation tools like growsurf_create_campaign and growsurf_update_campaign_design.

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 explicit mode-selection guidance ("detail: summary returns a configuration draft and reward structure; detail: full adds detailed benchmark tables") and notes that incentive amounts and qualifying actions remain unresolved unless the customer supplies them. It does not explicitly name alternative sibling tools or state when to prefer this over directly creating a program, 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_saleRecord 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. Program IDs also identify newly created programs 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/5.0
Behavior4/5

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

Annotations already declare idempotentHint=true and destructiveHint=false; the description goes further by explaining the de-duplication mechanism (identifier reuse prevents double-paying) and the campaign-targeting fallback, which an agent cannot infer from the schema. It stops short of covering retry/error behavior or auth requirements.

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, each earning its place: purpose first, then the commission/webhook workflow, then the identifier requirement and campaign targeting. No filler 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?

With an output schema present, return values need no explanation, and annotations cover the safety profile. The description covers the critical required-identifier rule and dedup semantics, though it omits participant identification and amount/currency semantics, which is a notable gap for a 28-parameter 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 11% across 28 parameters, so the description must carry the load; it usefully enumerates the seven accepted transaction identifiers and the campaignId default. However, ~25 parameters (currency, grossAmount, participantId/participantEmail, paymentProvider constraints, amount fields) are left to an under-documented 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?

States a specific verb and resource ('Record a sale/transaction for an affiliate program') and scopes it to a program/campaign. It implicitly distinguishes itself from growsurf_refund_transaction by tying the identifier to refunds, but does not name that 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 Guidelines4/5

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

Gives concrete context: use webhooks to learn when commissions are added, at least one transaction identifier is mandatory, reuse the same identifier when refunding, and campaignId falls back to GROWSURF_CAMPAIGN_ID. No explicit when-not or named-alternative routing, but the workflow guidance is clear.

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

growsurf_refund_transactionRecord Affiliate Refund or ChargebackA
DestructiveIdempotent
Inspect

Record a refund, partial refund, or chargeback for a previously recorded affiliate transaction in GrowSurf and reverse or adjust the referrer's commission. This records the amendment without sending a refund through the payment provider. Requires the same transaction identifier as the original sale. Omitted amountRefunded means a full refund. Already-paid commissions are not clawed back and are recorded for tax only. Targets campaignId if supplied, 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. Program IDs also identify newly created programs 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.1/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, and openWorldHint=true, so the safety profile is covered. The description adds genuinely non-derived behavior: already-paid commissions are not clawed back (tax-only recording), omitted amountRefunded implies a full refund, and no money moves through the provider. This meaningfully exceeds what the annotations convey.

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?

Six sentences, front-loaded with the core action, then the provider caveat, prerequisite, and default behaviors. Each sentence carries distinct information; no redundant restatement of the title, though it is on the longer side.

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?

An output schema exists so return values need not be explained. Given the conditional schema and 21 parameters, the description covers the critical prerequisites and default behaviors well, though it does not touch on the error states (e.g. 409 handling) that live in the schema property descriptions.

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 low (29%) across 21 parameters, so the description is expected to compensate but only covers a few: amountRefunded default semantics, the transaction-identifier requirement, and the campaignId fallback. The remaining parameters either carry their own schema descriptions (refundId, refundAmount, refundHistoryComplete) or are undocumented in both places.

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 ('Record a refund, partial refund, or chargeback') and resource ('a previously recorded affiliate transaction in GrowSurf') with the downstream effect ('reverse or adjust the referrer's commission'). An agent can distinguish this from the sibling growsurf_record_sale purely from the description.

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 the key prerequisite ('Requires the same transaction identifier as the original sale') and clarifies the operating context ('without sending a refund through the payment provider'), which tells the agent this is a record-only amendment. It does not explicitly name alternatives or state 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_request_participant_payout_destination_confirmationRequest 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. Program IDs also identify newly created programs 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`, `VENMO`, 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?

Annotations already declare destructiveHint=true, idempotentHint=false, and openWorldHint=true, so the safety profile is covered. The description adds genuine context beyond that: the message is a one-time link, only the participant can open and confirm it, and the call merely triggers the send rather than completing confirmation. This meaningfully clarifies the side-effect semantics.

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?

Content is front-loaded: what it does, how it works, the caveat, the return shape, and campaign targeting. Every sentence carries distinct information and nothing is 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?

Covers the delivery mechanism, the prerequisite (provider enabled), the targeting/default behavior for campaignId, and even the return fields. With an output schema present the return detail is optional but consistent, and no information 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?

Schema coverage is 50%, with participantId and participantEmail undocumented in the schema; the description compensates by stating selection is 'by GrowSurf participant ID or email'. The provider parameter is enum-documented in the schema, and the description reinforces that the provider must be enabled. It adds useful meaning over the schema without fully detailing formats.

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?

States a specific verb and resource: asks a participant to confirm a payout destination. It also clarifies the exact mechanism (sends a one-time confirmation link) and that it only triggers the message rather than performing the confirmation, which distinguishes it from a plain read of destinations. It stops short of naming the sibling growsurf_get_participant_payout_destination, so sibling differentiation relies on the reader.

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 clear context for use (participant must confirm a payout destination for a given provider) and a real prerequisite (the provider must be enabled for the program). It does not state when NOT to use it or name an alternative sibling, so it lacks explicit exclusions.

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

growsurf_request_team_verificationRequest 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.5/5.0
Behavior4/5

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

Annotations already declare destructiveHint=false, openWorldHint=true and idempotentHint=true; the description reinforces idempotency ('calling again while a request is pending does not create a duplicate') and adds real context: it mutates state, requires GROWSURF_API_KEY, does not require GROWSURF_CAMPAIGN_ID, and returns the team with updated verificationStatus. It goes beyond the structured fields, though it doesn't note latency or approval timing.

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?

Four short sentences, front-loaded with the action and condition, then idempotency, then return value and auth requirements. Every sentence adds information; nothing is 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 zero-parameter mutation with a declared output schema, the description covers everything an agent needs: purpose, precondition, idempotency, auth requirements, and return shape. Return-value detail is delegated appropriately to the output schema.

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 takes zero parameters, so the description carries no argument semantics to document and the baseline is 4. It still usefully clarifies the environment-variable prerequisites (API key required, campaign ID not), which are the only inputs relevant to this call.

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 (verify) and resource (the team bound to the API key/OAuth connection), which clearly separates it from siblings like growsurf_get_team or growsurf_resend_team_owner_verification_email. An agent can tell what action this triggers without opening a schema.

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 a concrete precondition — verification is required before a program can email participants — which signals when the tool is needed. It doesn't explicitly name or contrast sibling alternatives (e.g. resend_team_owner_verification_email), so it stops short of full routing guidance.

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_emailResend 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

A3.8/5.0
Behavior4/5

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

The description adds meaningful behavioral details beyond the annotations: requires GROWSURF_API_KEY, does not require GROWSURF_CAMPAIGN_ID, response never reveals owner email, and maps status codes to specific outcomes (sent, already verified, rate-limited). These complement the destructiveHint annotation 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?

The description is concise and front-loaded with the primary action. Each sentence contributes distinct value: the action, privacy guarantee, response code semantics, and authentication requirements. There is no redundant wording.

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 and an output schema exists, the description covers all essential call context: response behavior, authentication needs, and a key privacy constraint. An agent can confidently invoke the tool without additional information.

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 baseline is 4. The description does not need to elaborate on parameters, and no additional meaning is required beyond the empty 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 states a specific action (resend verification email) and target (team's owner), making the purpose clear. However, it does not mention the sibling tool request_team_verification or how this differs, so it misses the 'distinguishes from siblings' criterion for a 5.

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. It does not mention the sibling request_team_verification or any conditions that would select this tool over others. The response codes (400, 429) give some context but do not help with tool selection.

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

growsurf_test_campaign_webhookSend Test 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. Program IDs also identify newly created programs 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.4/5.0
Behavior4/5

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

Annotations already flag readOnly=false, destructive=true, openWorld=true, idempotent=false. The description adds real context beyond that: it clarifies the event is 'live' (not a dry run), discloses the 400 error when no events are enabled, and states it returns both the mock payload and the receiving endpoint's response. It does not cover auth/permission requirements, which is a minor gap.

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 tight sentences, front-loaded with the action, then optional-parameter behavior, then output. No filler; each sentence carries a distinct fact.

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?

An output schema exists, so the return-value explanation is a bonus rather than a necessity, and the safety profile is covered by annotations. The description is nearly complete for a 3-param tool, missing only explicit permission/scope requirements for hitting a live external endpoint.

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 33% schema coverage, the description must compensate, and it does for two of three params: `event` is optional and defaults to the webhook's first enabled event, and `campaignId` falls back to GROWSURF_CAMPAIGN_ID. `webhookId` (the required param) is left to its self-explanatory name and an undescribed schema entry, so it is not fully compensated.

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 ('Send a live test event to a webhook') and scopes it to the GrowSurf program's stored URL and secret. This is clearly distinguishable from siblings such as growsurf_create_campaign_webhook or growsurf_webhook_normalize, which do not send test events.

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?

Explains the operational context: it fires a live event using the stored URL/secret, with `event` optionally selecting the simulated type. It gives defaulting behavior and the 400 failure condition when no events are enabled, but never names an alternative tool or an explicit 'do not use this for X' exclusion.

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

growsurf_trigger_referralTrigger 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. Program IDs also identify newly created programs 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

A4/5.0
Behavior4/5

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

Annotations already declare destructive=true, idempotent=false, and openWorld=true, so the safety profile is covered. The description adds genuinely useful behavior: the delayInDays hold-and-award semantics and its refund-window rationale, plus the campaignId-vs-GROWSURF_CAMPAIGN_ID resolution rule. It stops short of warning that repeated calls are non-idempotent and may double-award credit.

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 tightly packed sentences with zero filler: the action and trigger condition lead, followed by the optional delay behavior and the campaign targeting rule. Every clause carries information needed to invoke the tool correctly.

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?

An output schema exists, so return values need no explanation, and the description covers the destructive/non-idempotent nature plus the delay mechanism adequately for a mutation tool. The remaining gap is the participant identifier requirement and the double-credit risk on repeat calls, which an agent must infer from the schema and annotations.

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 low (25%), so the description must compensate. It successfully explains delayInDays (range, holding semantics) and campaignId targeting, which the schema states only as bounds or a terse note. However, it never clarifies that exactly one of participantId/participantEmail is required to identify the participant, leaving the core identifier semantics to the schema's anyOf.

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?

States a specific verb+resource ('Trigger referral credit for a referred participant') and scopes it to the Sign up + Qualifying Action trigger model, so the agent knows exactly what operation this performs. It does not explicitly distinguish itself from siblings like record_sale or refund_transaction, which process purchase/refund events rather than referral credit awards.

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 a clear precondition ('use when your trigger is Sign up + Qualifying Action'), which tells the agent when this tool applies versus other event tools. It offers no explicit exclusions or named alternatives, and notably never points to the sibling growsurf_cancel_delayed_referral for reversing a delayed award.

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

growsurf_troubleshoot_referral_trackingTroubleshoot Referral TrackingA
Read-onlyIdempotent
Inspect

Diagnose referral tracking and program problems. Accepts a symptom or description without requiring a program or participant ID. Covers referrals not credited, participant emails not sending, rewards not issued, participants not added, Universal Code not detected, integrations or CRMs not syncing, Zapier errors, fraud flags, and analytics discrepancies. Returns ordered diagnostic checks, likely causes, fixes, and documentation links. It does not read program or participant records. Unknown symptom keys return the available symptoms. A description matches only when it contains a symptom 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. Program IDs also identify newly created programs 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.5/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive, closed-world, so the safety profile is covered. The description adds genuinely useful behavior beyond that: unknown `symptom` keys return the symptom list, and `description` only matches when it contains a symptom label or alias verbatim. That fallback/matching semantics is not derivable from annotations or 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?

Five tight sentences, front-loaded with purpose then capability scope, then return shape, then two precise edge-case rules. No filler, no repetition of the title, and the caveats are last where they belong.

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 present, return values need not be explained, yet the description still summarizes them (ordered checks, likely causes, fixes, docs links). Combined with annotations covering safety and full schema coverage of params, nothing an agent needs to invoke this 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?

Schema coverage is 100%, so the schema already documents all five parameters including the GROWSURF_CAMPAIGN_ID default. The description nevertheless adds resolution semantics the schema lacks: the symptom-vs-description fallback path and the verbatim matching rule. That is real added meaning on top of an already-complete 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?

Opens with a specific verb+resource: 'Diagnose referral tracking and program problems.' It also draws an explicit boundary ('does not read program or participant records'), which separates it from the many read-oriented siblings like growsurf_get_participant and growsurf_get_campaign. An agent can route to it 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 Guidelines4/5

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

It states the input flexibility ('accepts a symptom or description without requiring a program or participant ID') and enumerates the symptom domains it covers, which implies when it applies. It also gives a negative scoping statement about record reads. However, it never names an alternative tool for cases outside its scope (e.g., integration_guide or client_snippets), so the routing is inferred rather than explicit.

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

growsurf_update_campaignUpdate ProgramA
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. Program IDs also identify newly created programs without restarting the server.
companyNameNo
companyLogoImageUrlNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, and openWorldHint=true, so the safety profile is covered. The description adds genuine context beyond that: partial-update semantics ('only the fields you send are changed'), immutability of type/urlId/currencyISO, and the fact that COMPLETE ends the program. It stops short of explicitly warning that ending a program is irreversible, which keeps it from a 5.

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?

Front-loaded with the core purpose, then layered with status semantics, partial-update behavior, exclusions, and targeting. Every sentence carries actionable information; there is no filler or repetition of the title.

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?

An output schema exists, so return values need not be explained, and the annotations carry the destructive/idempotent profile. What remains — mutable fields, status transitions, immutability constraints, sibling routing, and target resolution — is all present, leaving no gap an agent would need to guess at.

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 names all four mutable fields, explains the status enum transitions (IN_PROGRESS publishes/resumes, COMPLETE ends), and calls out three fields the tool deliberately rejects. The campaignId fallback to GROWSURF_CAMPAIGN_ID is also stated, though the description largely mirrors the schema's own note.

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 (GrowSurf program/campaign), enumerates the exact mutable fields, and explicitly separates itself from the editor-tab config tools handled by dedicated sub-resource siblings. An agent can distinguish it from growsurf_update_campaign_design/emails/options/installation without opening any schema.

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 scopes when to use it (identity and lifecycle fields) and when not to (design, emails, options, installation go to the config sub-resource tools). It also explains the conditional behavior of the status parameter, giving the agent a decision rule rather than leaving it to inference.

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

growsurf_update_campaign_designUpdate Program 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, the website widget under widget (button or card, placement, timing, and visible pages), the participant Traffic report under trafficInsights, participant sign-in copy under login, and payout-destination confirmation page copy under payoutDestinationConfirmation. trafficInsights.isPublicDisplayed controls visibility; its labels cannot be blank. participantAvatarStyle accepts CHARACTERS, INITIALS, ANIMALS, or GRADIENT. Only supplied fields change; omitted fields retain their existing content and arrays replace wholesale. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsYes
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare destructiveHint, idempotentHint, readOnly=false and openWorld, so the safety profile is covered. The description still adds real value beyond them: partial-update semantics ('only supplied fields change; omitted fields retain their existing content and arrays replace wholesale') and the constraint that trafficInsights labels cannot be blank. It stops short of describing auth/permission 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?

A single dense paragraph, front-loaded with the action and scope; every sentence carries information (field names, enum values, mutation semantics, targeting). It is long but not padded, though it could be broken into shorter units for scanability.

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 nested-object mutation with an output schema present, the description supplies the field inventory, enum values, update semantics and target resolution — enough to invoke correctly. It omits permission/auth context and any pointer to get_campaign_design for inspecting current values.

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% (the free-form 'fields' object is undocumented in the schema), so the description must compensate, and it does: it names the nested keys, gives the four allowed participantAvatarStyle enum values, and states the non-blank label rule. It is not exhaustive about every nested widget/timing option, so not a 5.

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 verb (update) and resource (program design configuration) and then enumerates the exact sub-sections affected (participantAvatarStyle, widget, trafficInsights, login, payoutDestinationConfirmation), which separates it cleanly from siblings like update_campaign_emails or update_campaign_options.

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?

Usage is implied by the field list and the campaignId/GROWSURF_CAMPAIGN_ID targeting rule, but there is no explicit statement of when to choose this tool over alternatives such as get_campaign_design or the other update_campaign_* tools, and no prerequisites are mentioned.

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

growsurf_update_campaign_emailsUpdate Program EmailsA
DestructiveIdempotent
Inspect

Update writable Emails tab fields for your GrowSurf program under fields, in their existing nested shape. settings.sender.fromEmail is read-only; sender address changes require domain verification in the dashboard. settings.sender.fromName and settings.sender.replyToEmail are writable. The invite and transactional email isEnabled toggles are read-only. Email bodies require their template links and footer tokens. Omitted fields retain their existing content; arrays replace wholesale. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsYes
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.

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?

Adds substantive behavior beyond the annotations (destructiveHint=true, idempotentHint=true): omitted fields retain existing content, arrays replace wholesale, sender address changes require dashboard domain verification, and email bodies require template links and footer tokens. This tells the agent exactly what is preserved vs destroyed, which the annotations alone cannot.

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?

Front-loads the core action and scope, then layers constraints and targeting in dense but non-redundant sentences. No sentence merely restates the schema or title.

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 nested patch mutation with an output schema present, the description covers the essential gaps: patch semantics, per-field writability, array replacement behavior, and target resolution via campaignId or GROWSURF_CAMPAIGN_ID. Return values need not be described given the output schema.

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 50% schema description coverage, the description compensates by naming writable vs read-only subfields (fromName/replyToEmail writable, fromEmail read-only) and by pointing to the existing nested shape. It still leaves the full shape of `fields` to be learned elsewhere, but adds real meaning over 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?

States a specific verb (Update) and resource (writable Emails tab fields for a GrowSurf program), and immediately scopes it to the `fields` object. It is clearly distinguishable from the read-only `growsurf_get_campaign_emails` sibling and from the broader `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?

Gives clear context for use (patch only writable fields, omit to retain) and implicitly routes read-only fields (fromEmail, invite/transactional toggles) to the dashboard instead. It stops short of naming an alternative sibling tool or stating explicit when-not conditions for the whole tool.

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

growsurf_update_campaign_installationUpdate Program InstallationA
DestructiveIdempotent
Inspect

Update the Installation tab configuration for your GrowSurf program under fields. Only supplied fields change; omitted fields retain their existing values and arrays replace wholesale. allowedUrls includes permitted browser origins such as http://localhost:3000. An origin missing from both shareUrl and allowedUrls can return 403. Referral links already shared point at the current shareUrl. Replacing an existing Share URL requires the customer's explicit approval and replaceExistingShareUrl: true; otherwise the patch is refused. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsYesInstallation fields to patch. Common keys include `shareUrl`, `allowedUrls`, `signupEvent`, `referralTrigger`, `signup`, and `instructionSelections`. Arrays replace wholesale.
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs 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.6/5.0
Behavior5/5

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

Annotations already declare destructive/idempotent/openWorld, and the description adds real behavioral context on top: merge-vs-replace patch semantics, the 403 outcome when an origin is missing from shareUrl/allowedUrls, the effect on already-shared referral links, and the explicit-approval guard that causes the patch to be refused. This is materially more than the annotations convey.

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 core purpose, then each subsequent sentence carries a distinct constraint (merge semantics, origin rules, 403, approval guard, targeting default) with no filler. Slightly dense, but nothing is redundant.

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 nested-object patch tool with an output schema already covering return values, the description supplies everything an agent needs: mutation semantics, the approval gate, error conditions, and default targeting. No meaningful gap remains.

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 100%, so the baseline is 3, but the description adds meaning beyond the schema: allowedUrls origins with a concrete example, the 403 consequence of omitting an origin, the wholesale array-replacement rule, and the campaignId fallback to GROWSURF_CAMPAIGN_ID.

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 ('Update the Installation tab configuration for your GrowSurf program under `fields`'), and the scoping to the Installation tab cleanly separates it from siblings like growsurf_update_campaign_options, growsurf_update_campaign_design, and the read-only growsurf_get_campaign_installation.

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 clear operational conditions: only supplied fields change, arrays replace wholesale, and replacing a Share URL requires customer approval plus `replaceExistingShareUrl: true` or the patch is refused. It does not explicitly point to alternatives such as the get_campaign_installation reader, 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_update_campaign_optionsUpdate Program OptionsA
DestructiveIdempotent
Inspect

Update the Options tab configuration for your GrowSurf program under fields, in its existing nested shape. Only supplied fields change; omitted fields retain their existing values and arrays replace wholesale. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsYes
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.

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?

Annotations already declare destructiveHint=true and idempotentHint=true, but the description adds the crucial merge semantics: only supplied fields change, omitted fields are retained, and arrays replace wholesale. The wholesale array replacement is exactly the destructive behavior the annotation hints at, so this meaningfully enriches understanding beyond the structured flags.

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?

Three tight sentences, front-loaded with the action and followed by merge semantics and targeting rule. No filler; every sentence carries actionable 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?

An output schema exists, so return values need no explanation, and the merge/destruction behavior plus targeting default are covered. What remains thin is the internal shape of the `fields` payload, which given its nested and opaque nature would benefit from more detail.

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 50% (only campaignId is documented in-schema; fields is an opaque object). The description adds some value by explaining the `fields` nested shape mirrors existing config and that campaignId defaults to GROWSURF_CAMPAIGN_ID, but it does not enumerate valid nested keys or structure, so the opaque fields object remains largely undocumented.

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: updating the Options tab configuration of a GrowSurf program via the `fields` object. This cleanly distinguishes it from sibling read-tool growsurf_get_campaign_options and from the other update_* tools targeting design/emails/installation.

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?

Usage is implied by the update semantics and the targeting language, but the description never states when to prefer this tool or points to growsurf_get_campaign_options for reading current values. There is no explicit when/when-not guidance or named 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_rewardUpdate Campaign RewardB
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. Program IDs also identify newly created programs 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

B3.1/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, destructiveHint=true, idempotentHint=true, and openWorldHint=true, so the safety profile is covered. The description adds two genuinely useful facts (reward type is immutable; target resolution defaults), but for a 23-param destructive mutation it never states partial-update vs. replace semantics or what happens to omitted 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?

Three short sentences, front-loaded with the operation, then the key param, then targeting behavior. No filler, though it is arguably too terse for the surface area it covers.

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?

An output schema exists so return values need not be described, but a destructive 23-parameter mutation with 22% schema coverage and no partial-update semantics, prerequisites, or field-level guidance leaves the agent under-informed about how to call it safely.

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% across 23 parameters, so the description must compensate and largely does not. It explains campaignRewardId (the reward key) and campaignId, but says nothing about the many undocumented fields (limit, order, title, isVisible, numberOfWinners, etc.) or the distinction between value/referredValue sides.

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?

States a specific verb+resource ('Update an existing campaign reward (reward config)') that clearly separates it from the create/list/delete reward siblings. It does not name an alternative, but the verb alone makes the intent 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 clarifies how the target program is resolved (campaignId else GROWSURF_CAMPAIGN_ID) and that type is immutable, which is useful context. However there is no explicit when-to-use guidance, no prerequisite/permission notes, and no differentiation from growsurf_create_campaign_reward beyond the verb.

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

growsurf_update_campaign_webhookUpdate 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. Program IDs also identify newly created programs without restarting the server.
payloadUrlNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior4/5

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

Annotations already declare destructiveHint, idempotentHint, and openWorldHint. The description adds genuine value beyond them: patch semantics ('Only the fields you send are changed'), the write-only, never-returned nature of `secret`, and the special 'primary' webhook id. It does not explain permission needs or why the update is flagged destructive, keeping it from a 5.

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, front-loaded with the core action before the special-case notes. Each sentence carries distinct information (patch semantics, write-only secret, campaign targeting) with 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?

An output schema exists, so return values need no explanation, and annotations carry the safety profile. The description covers the tricky special cases (primary id, patch behavior, env fallback), leaving only the self-evident events/isEnabled/payloadUrl fields unaddressed.

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 33%, so the description must compensate. It adds meaning for webhookId ('primary'), secret (write-only), and campaignId (env fallback), but leaves events, isEnabled, and payloadUrl undocumented and does not explain the anyOf at-least-one-field requirement.

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?

States a specific verb+resource: 'Update a webhook on your GrowSurf program by id'. An agent can tell this is the mutation counterpart to the create/delete/list/test webhook siblings. It stops short of explicitly naming those alternatives, so it is clear but not fully sibling-differentiated.

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 gives no when-to-use guidance, prerequisites, or named alternatives among the webhook siblings (create/delete/test/list). Usage is only implied by the verb 'Update', with no exclusions or conditions stated.

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

growsurf_update_participantUpdate 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. Program IDs also identify newly created programs 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.1/5.0
Behavior5/5

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

Annotations only give the safety profile (destructive, idempotent, non-read-only); the description adds real behavior: read-only fields (counters, isAffiliate, origin, fraud state) are rejected with a 400, affiliate enrollment cannot be removed through REST, APPROVED enrolls a non-affiliate while SUSPENDED/BANNED require an existing affiliate, and notes are internal-only. No contradiction with 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?

A dense but well-ordered block: update scope first, then field rejection, then affiliate semantics, then targeting resolution. Every sentence carries information, though for 13 parameters the wall of prose could be broken into clearer segments.

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?

An output schema exists so return values need no explanation, and the description covers the genuinely tricky parts (partial update, read-only rejection, affiliate transitions, campaign targeting). It remains silent on roughly half the writable parameters, which for a 13-param tool is the main remaining gap.

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 31%, so the burden falls on the description, but it mostly repeats what the schema already documents for affiliateStatus, notes, email and campaignId. It never explains the undocumented parameters (metadata, referredBy, vanityKeys, unsubscribed, referralStatus, firstName/lastName), though the 400-rejection note does clarify which fields are effectively off-limits.

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?

States a specific verb and resource ('Update a participant') plus the two accepted lookup keys (participant ID or email), so an agent knows exactly what entity is being modified. It never names a sibling (e.g. add_participant vs update_participant), but the update-vs-create distinction is unambiguous from the verb.

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 concrete selection context: partial-update semantics ('only the fields you send are changed'), which operation targets campaignId vs GROWSURF_CAMPAIGN_ID, and when affiliateStatus values are legal. It stops short of naming alternative tools or explicitly stating when NOT to use this tool (e.g. use add_participant for new records).

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

growsurf_update_program_resourceUpdate Program ResourceA
DestructiveIdempotent
Inspect

Update at least one participant resource field, or move it to a zero-based position. Only supplied fields change. A replacement FILE requires a one-time uploadTicket and the unmodified uploadResult from GrowSurf's secure upload flow. API reference: https://docs.growsurf.com/developer-tools/rest-api/api-reference. Targets campaignId if supplied, 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. Program IDs also identify newly created programs 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

A3.6/5.0
Behavior4/5

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

Annotations already declare write/destructive/idempotent/openWorld, so the safety profile is covered. The description adds genuine context beyond them: partial-update behavior ("Only supplied fields change"), the one-time uploadTicket plus unmodified uploadResult requirement for FILE replacement, and campaign targeting via campaignId or the GROWSURF_CAMPAIGN_ID env var.

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?

Three tight sentences, front-loading the update/partial semantics before the conditional FILE caveat and the targeting rule. The API-reference URL is useful rather than filler; no redundancy against structured fields.

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 gated by a complex conditional schema (if/then upload pairing, anyOf requiring at least one updatable field), the description covers the key interactions and an output schema exists so return values need not be explained. The one gap is the absence of any usage routing relative to sibling resource tools.

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 description coverage at only 42%, the description must compensate, and it does for the non-obvious params: position is zero-based, FILE needs uploadTicket + the unmodified uploadResult from the secure upload flow, and campaignId defaults to GROWSURF_CAMPAIGN_ID. Self-evident params (title, description, isPublished) are left to the schema, which is reasonable.

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?

States a specific verb+resource ("Update ... participant resource field, or move it to a zero-based position") and clarifies partial-update semantics with "Only supplied fields change." It is clear what the tool does, though it never names or distinguishes itself from the sibling create/delete/list program-resource tools.

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 says what can be updated (at least one field, or position) but gives no when-to-use guidance, no exclusions, and no routing to alternatives such as growsurf_create_program_resource or growsurf_delete_program_resource. An agent gets no help deciding between this and its siblings.

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

growsurf_update_teamUpdate 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/5.0
Behavior3/5

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

Annotations indicate destructiveHint=true and readOnlyHint=false, implying mutation. The description states it updates the display name, which aligns, but doesn't escalate the destructive nature—e.g., no warning that changing name may affect existing references. It adds value by clarifying scope but doesn't go 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?

Two concise sentences: first states the action and scope, second lists exclusions and requirements. No fluff, front-loads the core action, and packs useful constraints efficiently.

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 tool's simplicity (1 param, no nested objects) and presence of output schema, the description covers essential usage. It clarifies auth requirements, exclusions, and the single editable field. Slight gap: doesn't mention potential side effects or irreversible changes, but given simple scope, it's 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 input schema already provides 100% coverage for the single parameter 'name' with a description. The description adds no extra syntax or format details beyond schema, so baseline 3 is appropriate. It does not complement the schema, but doesn't need to.

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?

Clearly states it updates the team's display name, specifying the scope (team bound to API key or OAuth connection). It distinguishes from other team-related tools like growsurf_get_team and growsurf_request_team_verification, though it doesn't explicitly name them. The verb 'update' and resource 'team' are 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?

Explicitly notes what is NOT editable (personal profiles, billing, ownership), giving clear boundaries. It also states the required environment variable and that campaign ID is not needed, which helps agent decide when to use this tool. These details provide strong usage context.

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

growsurf_webhook_normalizeNormalize Webhook PayloadA
Read-onlyIdempotent
Inspect

Validate/normalize a GrowSurf webhook payload and generate a best-effort idempotency key for dedupe.

ParametersJSON Schema
NameRequiredDescriptionDefault
payloadYesJSON value to validate. A valid webhook envelope is an object with `event`, `createdAt`, and `data`. Other JSON values return `ok: false`.

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.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so safety is covered. The description adds one genuinely new behavioral fact - that an idempotency key is generated on a best-effort basis - but says nothing about normalization rules, determinism of the key, or failure behavior (the schema covers the ok:false case).

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 dense sentence with zero filler; the core action and the extra idempotency-key behavior are both front-loaded. Nothing could be removed without losing information.

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?

With an output schema present and annotations covering safety, the description does not need to explain returns. However, for a tool whose name promises normalization, it never says what normalization entails or which fields are canonicalized, leaving a meaningful gap in an otherwise simple definition.

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 single `payload` parameter is documented thoroughly in the schema (accepted types, required envelope fields, ok:false fallback). The description adds no parameter-level detail beyond that, so the baseline of 3 applies.

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?

States a specific verb pair (validate/normalize) on a specific resource (GrowSurf webhook payload) plus a concrete secondary output (idempotency key). It is clearly distinct from the webhook CRUD siblings (list/create/update/delete/test_campaign_webhook), though it never names or contrasts with any 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 Guidelines3/5

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

Usage is only implied: the mention of 'dedupe' hints that this is for inbound webhook handling, but there is no explicit when-to-use, when-not-to-use, or alternative tool named. An agent must infer the scenario.

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. 48 tool updatesv0.19.9
    • Changedgrowsurf_add_participant1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_bulk_delete_participants1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_cancel_delayed_referral1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_capture_referral_flow_screenshots1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_clone_campaign1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_create_campaign1 field changed
      • changedInput schema / properties / goal / description
        Previous value: -"What the program is for, which seeds the share buttons and the starter rewards that suit that audience. Programs whose participants refer other businesses (`CUSTOMERS`, `USERS`, `B2B_SAAS_SELF_SERVICE`, `B2B_SAAS_ENTERPRISE`, `HEALTHCARE_PROVIDERS`) start with the LinkedIn share button visible. Consumer, financial, education, insurance, telehealth, newsletter, and waitlist programs (`B2C_SUBSCRIPTIONS`, `FINANCIAL_SERVICES`, `ONLINE_EDUCATION`, `INSURANCE`, `ONLINE_INSURANCE`, `TELEHEALTH`, `SUBSCRIBERS`, `WAITLIST`) start with it hidden. On a referral program, each goal also sets the rest of its share buttons to suit that audience — a telehealth program keeps the public feeds off, a consumer subscription turns Pinterest and Reddit on; an affiliate program has its own share defaults, so only the LinkedIn default applies to one. When you create a referral program without `rewards`, the goal also decides the starter rewards: most goals get one double-sided reward, `HEALTHCARE_PROVIDERS` gets a single-sided reward, `SUBSCRIBERS` gets a four-step milestone ladder, and `WAITLIST` gets a leaderboard. Every starter reward arrives switched off with a placeholder name, so the program awards nothing until the customer sets the amount and turns one on. `TELEHEALTH` is for consumer telehealth and wellness subscriptions, where patients refer friends; `HEALTHCARE_PROVIDERS` is for provider networks and clinician-facing products, where practices refer peer practices. `INSURANCE` replaces `ONLINE_INSURANCE`, which is still accepted and behaves identically. 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."New value: +"What the program is for, which seeds the share buttons and the starter rewards that suit that audience. Programs whose participants refer other businesses (`CUSTOMERS`, `USERS`, `B2B_SAAS_SELF_SERVICE`, `B2B_SAAS_ENTERPRISE`, `HEALTHCARE_PROVIDERS`) start with the LinkedIn share button visible. Consumer, financial, education, insurance, telehealth, newsletter, and waitlist programs (`B2C_SUBSCRIPTIONS`, `FINANCIAL_SERVICES`, `ONLINE_EDUCATION`, `INSURANCE`, `ONLINE_INSURANCE`, `TELEHEALTH`, `SUBSCRIBERS`, `WAITLIST`) start with it hidden. On a referral program, each goal also sets the rest of its share buttons to suit that audience — a telehealth program keeps the public feeds off, a consumer subscription turns Pinterest and Reddit on; an affiliate program has its own share defaults, so only the LinkedIn default applies to one. When you create a referral program without `rewards`, the goal also decides the starter rewards: most goals get one double-sided reward, `HEALTHCARE_PROVIDERS` gets a single-sided reward, `SUBSCRIBERS` gets a four-step milestone ladder, and `WAITLIST` gets a leaderboard. Every starter reward arrives switched off with a placeholder name, so the program awards nothing until the customer sets the amount and turns one on. `TELEHEALTH` is for consumer telehealth and wellness subscriptions, where patients refer friends; `HEALTHCARE_PROVIDERS` is for provider networks and clinician-facing products, where practices refer peer practices. `INSURANCE` replaces `ONLINE_INSURANCE`, which is still accepted and behaves identically. Omit `goal` and every share button keeps its standard default. Sharing settings remain editable after creation. The goal itself is set only at creation."
    • Changedgrowsurf_create_campaign_reward1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_create_campaign_webhook1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_create_mobile_participant_token1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_create_program_resource1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_delete_campaign_reward1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_delete_campaign_webhook1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_delete_program_resource1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_email_participant1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_campaign1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_campaign_activation_analytics1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_campaign_analytics1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_campaign_design1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_campaign_emails1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_campaign_installation1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_campaign_options1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_participant1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_participant_activity_logs1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_participant_analytics1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_participant_payout_destination1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_list_campaign_rewards1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_list_campaign_webhooks1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_list_integrations1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_list_participants1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_list_program_resources1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_prepare_program_resource_file1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_program_design_advisor1 field changed
      • changedInput schema / properties / goal / description
        Previous value: -"What 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`."New value: +"What 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 advisor goal differs from the program creation goal included in `configurationPlan`."
    • Changedgrowsurf_record_sale1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_refund_transaction1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_request_participant_payout_destination_confirmation1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_test_campaign_webhook1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_trigger_referral1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_troubleshoot_referral_tracking1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_campaign1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_campaign_design1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_campaign_emails1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_campaign_installation1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_campaign_options1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_campaign_reward1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_campaign_webhook1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_participant1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_program_resource1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target 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."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_webhook_normalize2 fields changed
      • addedInput schema / properties / payload / description
        Added value: +"JSON value to validate. A valid webhook envelope is an object with `event`, `createdAt`, and `data`. Other JSON values return `ok: false`."
      • addedInput schema / properties / payload / type
        Added value: +[
        +  "object",
        +  "array",
        +  "string",
        +  "number",
        +  "boolean",
        +  "null"
        +]
  2. 8 tool updatesv0.19.8
    • Changedgrowsurf_create_campaign_reward6 fields changed
      • changedInput schema / properties / couponCode / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / imageUrl / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / nextMilestonePrefix / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / nextMilestoneSuffix / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / referralCouponCode / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / referralDescription / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
    • Changedgrowsurf_get_campaign_analytics5 fields changed
      • addedInput schema / allOf
        Added value: +[
        +  {
        +    "if": {
        +      "required": [
        +        "startDate"
        +      ]
        +    },
        +    "then": {
        +      "required": [
        +        "endDate"
        +      ]
        +    }
        +  },
        +  {
        +    "if": {
        +      "required": [
        +        "endDate"
        +      ]
        +    },
        +    "then": {
        +      "required": [
        +        "startDate"
        +      ]
        +    }
        +  }
        +]
      • changedInput schema / properties / endDate / description
        Previous value: -"End of the timeframe, Unix timestamp in ms."New value: +"End of the timeframe, positive Unix timestamp in milliseconds. Supply `startDate` too; `endDate` must be >= `startDate` and at most 1825 days later."
      • addedInput schema / properties / endDate / minimum
        Added value: +1
      • 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 timeframe, positive Unix timestamp in milliseconds. Supply `endDate` too; the window must span at most 1825 days."
      • addedInput schema / properties / startDate / minimum
        Added value: +1
    • Changedgrowsurf_get_campaign_emails2 fields changed
      • changedOutput schema / description
        Previous value: -"A program's email configuration. Each template property is an object with `subject`, `preheader`, `body` (HTML), and `isEnabled` (plus `useCompanyReplyTo` on the invite email). The templates available depend on the program type. `GET` returns the full object; `PATCH` back only the fields you want to change."New value: +"A program's email configuration. Each template property is an object with `subject`, `preheader`, `body` (HTML), and `isEnabled` (plus `useCompanyReplyTo` on the invite email). The templates available depend on the program type. `GET` includes read-only fields; `PATCH` only the writable fields you want to change. The `invite` and transactional email `isEnabled` toggles cannot be changed here."
      • addedOutput schema / properties / settings / properties
        Added value: +{
        +  "sender": {
        +    "properties": {
        +      "fromEmail": {
        +        "description": "Read-only sender email address. Change it in the dashboard after domain verification; omit it from an email configuration update.",
        +        "readOnly": true,
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "fromName": {
        +        "description": "Sender name, or null before one is configured. A new value must not be an email address.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "replyToEmail": {
        +        "description": "Email address that receives replies, or null before one is configured.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "type": "object"
        +  }
        +}
    • Changedgrowsurf_get_campaign_installation1 field changed
      • changedOutput schema / properties / allowedUrls / description
        Previous value: -"Every 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`."New value: +"Every 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`. Known shared-platform root domains, such as `github.io`, do not grant access. Add your site's hostname, such as `https://piedpiper.github.io`, or a domain you own. Path-based shared hosts, such as `unbouncepages.com`, require a domain you own."
    • Changedgrowsurf_get_participant_analytics5 fields changed
      • addedInput schema / allOf
        Added value: +[
        +  {
        +    "if": {
        +      "required": [
        +        "startDate"
        +      ]
        +    },
        +    "then": {
        +      "required": [
        +        "endDate"
        +      ]
        +    }
        +  },
        +  {
        +    "if": {
        +      "required": [
        +        "endDate"
        +      ]
        +    },
        +    "then": {
        +      "required": [
        +        "startDate"
        +      ]
        +    }
        +  }
        +]
      • changedInput schema / properties / endDate / description
        Previous value: -"End of the optional-data timeframe, Unix timestamp in ms. Use with `startDate`."New value: +"End of the optional-data timeframe, positive Unix timestamp in milliseconds. Supply `startDate` too; `endDate` must be >= `startDate` and at most 1825 days later."
      • addedInput schema / properties / endDate / minimum
        Added value: +1
      • changedInput schema / properties / startDate / description
        Previous value: -"Start of the optional-data timeframe, Unix timestamp in ms. Use with `endDate` instead of `days`."New value: +"Start of the optional-data timeframe, positive Unix timestamp in milliseconds. Supply `endDate` too; the window must span at most 1825 days."
      • addedInput schema / properties / startDate / minimum
        Added value: +1
    • Changedgrowsurf_update_campaign_emails1 field changed
      • addedInput schema / properties / fields / properties
        Added value: +{
        +  "settings": {
        +    "additionalProperties": true,
        +    "properties": {
        +      "sender": {
        +        "additionalProperties": true,
        +        "description": "Patch `fromName` or `replyToEmail`. Change the read-only `fromEmail` in the dashboard after domain verification.",
        +        "not": {
        +          "required": [
        +            "fromEmail"
        +          ]
        +        },
        +        "properties": {
        +          "fromName": {
        +            "type": "string"
        +          },
        +          "replyToEmail": {
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      }
        +    },
        +    "type": "object"
        +  }
        +}
    • Changedgrowsurf_update_campaign_installation1 field changed
      • changedInput schema / properties / fields / properties / allowedUrls / description
        Previous value: -"Every browser origin allowed to use the program, including local and staging origins. Send the full array because arrays replace wholesale."New value: +"Every browser origin allowed to use the program, including local and staging origins. Send the full array because arrays replace wholesale. Known shared-platform root domains, such as `github.io`, do not grant access. Add your site's hostname, such as `https://piedpiper.github.io`, or a domain you own. Path-based shared hosts, such as `unbouncepages.com`, require a domain you own."
    • Changedgrowsurf_update_campaign_reward6 fields changed
      • changedInput schema / properties / couponCode / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / imageUrl / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / nextMilestonePrefix / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / nextMilestoneSuffix / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / referralCouponCode / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / referralDescription / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
  3. 4 tool updatesv0.19.7
    • Changedgrowsurf_get_campaign_installation1 field changed
      • addedOutput schema / properties / instructionSelections
        Added value: +{
        +  "description": "Saved choices shown in the Program Editor installation guide.",
        +  "properties": {
        +    "mobileAttributionProvider": {
        +      "description": "Mobile attribution provider selected for the guide.",
        +      "enum": [
        +        "branch",
        +        "appsflyer",
        +        "adjust",
        +        "singular",
        +        "other"
        +      ],
        +      "type": "string"
        +    },
        +    "platform": {
        +      "description": "Platform shown in step 1.",
        +      "enum": [
        +        "web",
        +        "ios",
        +        "android"
        +      ],
        +      "type": "string"
        +    },
        +    "stepProviders": {
        +      "description": "Selected method for each installation step; affiliate and referral choices depend on program type.",
        +      "properties": {
        +        "step2Affiliate": {
        +          "description": "Affiliate step 2 method.",
        +          "enum": [
        +            "stripe",
        +            "chargebee",
        +            "recurly",
        +            "restApi"
        +          ],
        +          "type": "string"
        +        },
        +        "step2Referral": {
        +          "description": "Referral step 2 method.",
        +          "enum": [
        +            "restApi",
        +            "zapier",
        +            "stripe",
        +            "chargebee",
        +            "recurly",
        +            "paypal",
        +            "hubspot",
        +            "salesforce"
        +          ],
        +          "type": "string"
        +        },
        +        "step2Signup": {
        +          "description": "Signup method shown in step 2.",
        +          "enum": [
        +            "restApi",
        +            "javascript"
        +          ],
        +          "type": "string"
        +        },
        +        "step3Affiliate": {
        +          "description": "Affiliate payout method shown in step 3.",
        +          "enum": [
        +            "paypal",
        +            "wise"
        +          ],
        +          "type": "string"
        +        },
        +        "step3Referral": {
        +          "description": "Referral reward method shown in step 3.",
        +          "enum": [
        +            "webhooks",
        +            "zapier",
        +            "paypal",
        +            "tangocard",
        +            "stripe",
        +            "chargebee",
        +            "recurly"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedgrowsurf_get_participant_payout_destination3 fields changed
      • changedOutput schema / properties / activeProvider / description
        Previous value: -"The payout provider currently selected, or `null` until the participant confirms one. Provider identifiers are open-ended; current examples include `PAYPAL` and `WISECOM`."New value: +"The payout provider currently selected, or `null` until the participant confirms one. Provider identifiers are open-ended; current examples include `PAYPAL`, `VENMO`, and `WISECOM`."
      • changedOutput schema / properties / destinations / items / properties / provider / description
        Previous value: -"The payout provider identifier for this entry. Values are open-ended; current examples include `PAYPAL` and `WISECOM`."New value: +"The payout provider identifier for this entry. Values are open-ended; current examples include `PAYPAL`, `VENMO`, and `WISECOM`."
      • changedOutput schema / properties / enabledProviders / description
        Previous value: -"Payout provider identifiers enabled for this program. Values are open-ended; current examples include `PAYPAL` and `WISECOM`."New value: +"Payout provider identifiers enabled for this program. Values are open-ended; current examples include `PAYPAL`, `VENMO`, and `WISECOM`."
    • Changedgrowsurf_request_participant_payout_destination_confirmation2 fields changed
      • changedInput schema / properties / provider / enum
        Previous value: -[
        -  "PAYPAL",
        -  "WISECOM"
        -]New value: +[
        +  "PAYPAL",
        +  "VENMO",
        +  "WISECOM"
        +]
      • changedOutput schema / properties / provider / description
        Previous value: -"The payout provider identifier the participant was asked to confirm. Values are open-ended; current examples include `PAYPAL` and `WISECOM`."New value: +"The payout provider identifier the participant was asked to confirm. Values are open-ended; current examples include `PAYPAL`, `VENMO`, and `WISECOM`."
    • Changedgrowsurf_update_campaign_installation2 fields changed
      • changedInput schema / properties / fields / description
        Previous value: -"Installation fields to patch. Common keys include `shareUrl`, `allowedUrls`, `signupEvent`, `referralTrigger`, and `signup`. Arrays replace wholesale."New value: +"Installation fields to patch. Common keys include `shareUrl`, `allowedUrls`, `signupEvent`, `referralTrigger`, `signup`, and `instructionSelections`. Arrays replace wholesale."
      • addedInput schema / properties / fields / properties / instructionSelections
        Added value: +{
        +  "additionalProperties": true,
        +  "description": "Guide choices. Send only the choices to change.",
        +  "properties": {
        +    "mobileAttributionProvider": {
        +      "enum": [
        +        "branch",
        +        "appsflyer",
        +        "adjust",
        +        "singular",
        +        "other"
        +      ],
        +      "type": "string"
        +    },
        +    "platform": {
        +      "enum": [
        +        "web",
        +        "ios",
        +        "android"
        +      ],
        +      "type": "string"
        +    },
        +    "stepProviders": {
        +      "additionalProperties": true,
        +      "description": "Selected method for each guide step. Available keys depend on program type.",
        +      "properties": {
        +        "step2Affiliate": {
        +          "enum": [
        +            "stripe",
        +            "chargebee",
        +            "recurly",
        +            "restApi"
        +          ],
        +          "type": "string"
        +        },
        +        "step2Referral": {
        +          "enum": [
        +            "restApi",
        +            "zapier",
        +            "stripe",
        +            "chargebee",
        +            "recurly",
        +            "paypal",
        +            "hubspot",
        +            "salesforce"
        +          ],
        +          "type": "string"
        +        },
        +        "step2Signup": {
        +          "enum": [
        +            "restApi",
        +            "javascript"
        +          ],
        +          "type": "string"
        +        },
        +        "step3Affiliate": {
        +          "enum": [
        +            "paypal",
        +            "wise"
        +          ],
        +          "type": "string"
        +        },
        +        "step3Referral": {
        +          "enum": [
        +            "webhooks",
        +            "zapier",
        +            "paypal",
        +            "tangocard",
        +            "stripe",
        +            "chargebee",
        +            "recurly"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    }
        +  },
        +  "type": "object"
        +}
  4. 2 tool updatesv0.19.1
    • Changedgrowsurf_get_campaign_design1 field changed
      • addedOutput schema / properties / trafficInsights
        Added value: +{
        +  "description": "The Traffic report participants can open from the GrowSurf window: visits to their share link over time and where those visits came from. It starts on for new affiliate programs and hidden for referral programs. Every setting is returned, with the default copy for anything not changed. Labels cannot be blank.",
        +  "properties": {
        +    "allLinksLabel": {
        +      "description": "The share link picker option that combines all of the participant's links.",
        +      "type": "string"
        +    },
        +    "backLinkText": {
        +      "description": "The text of the link back from the report.",
        +      "type": "string"
        +    },
        +    "breakdowns": {
        +      "description": "The tables that show where visits came from: `utm`, `referrer`, `destination`, `geo`, `technology`, and `trigger`. Each has `isVisible` and `label`; some also name their levels under `levels` or their fixed rows under `values`.",
        +      "type": "object"
        +    },
        +    "breakdownsTitle": {
        +      "description": "The heading above the breakdown table.",
        +      "type": "string"
        +    },
        +    "dateRangeLabels": {
        +      "description": "The date range picker labels, keyed by `LAST_7_DAYS`, `LAST_30_DAYS`, `LAST_90_DAYS`, and `ALL_TIME`.",
        +      "type": "object"
        +    },
        +    "defaultDateRange": {
        +      "description": "The date range the report opens with.",
        +      "enum": [
        +        "LAST_7_DAYS",
        +        "LAST_30_DAYS",
        +        "LAST_90_DAYS",
        +        "ALL_TIME"
        +      ],
        +      "type": "string"
        +    },
        +    "emptyState": {
        +      "description": "The message shown before the participant's link has any visits. Can be empty.",
        +      "type": "string"
        +    },
        +    "isPublicDisplayed": {
        +      "description": "Whether participants can open the Traffic report.",
        +      "type": "boolean"
        +    },
        +    "messages": {
        +      "description": "Messages shown when the report cannot show everything: `error`, `unavailable`, `partial`, `partialFrom` (`{{date}}` is replaced with the first available date), `breakdownPartial`, and `breakdownEmpty`.",
        +      "type": "object"
        +    },
        +    "metrics": {
        +      "description": "The two visit counts at the top of the report, `visits` and `uniqueVisitors`, each with `isVisible`, `label`, and `helperText`.",
        +      "type": "object"
        +    },
        +    "notSetLabel": {
        +      "description": "The row name for visits that have no value for the chosen breakdown.",
        +      "type": "string"
        +    },
        +    "title": {
        +      "description": "The report heading.",
        +      "type": "string"
        +    },
        +    "trafficForLabel": {
        +      "description": "The label in front of the share link picker.",
        +      "type": "string"
        +    },
        +    "viewTrafficInsightsLinkText": {
        +      "description": "The text of the row or tab that opens the report.",
        +      "type": "string"
        +    },
        +    "visitsOverTimeTitle": {
        +      "description": "The heading above the visits chart.",
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedgrowsurf_list_campaign_rewards1 field changed
      • changedOutput schema / properties / rewards / description
        Previous value: -"The program's active, visible, and enabled reward configs."New value: +"The program's configured Campaign Rewards, including switched-off rewards. Deleted rewards are excluded."
  5. 3 tool updatesv0.18.1
    • Changedgrowsurf_create_campaign2 fields changed
      • changedInput schema / properties / goal / description
        Previous value: -"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."New value: +"What the program is for, which seeds the share buttons and the starter rewards that suit that audience. Programs whose participants refer other businesses (`CUSTOMERS`, `USERS`, `B2B_SAAS_SELF_SERVICE`, `B2B_SAAS_ENTERPRISE`, `HEALTHCARE_PROVIDERS`) start with the LinkedIn share button visible. Consumer, financial, education, insurance, telehealth, newsletter, and waitlist programs (`B2C_SUBSCRIPTIONS`, `FINANCIAL_SERVICES`, `ONLINE_EDUCATION`, `INSURANCE`, `ONLINE_INSURANCE`, `TELEHEALTH`, `SUBSCRIBERS`, `WAITLIST`) start with it hidden. On a referral program, each goal also sets the rest of its share buttons to suit that audience — a telehealth program keeps the public feeds off, a consumer subscription turns Pinterest and Reddit on; an affiliate program has its own share defaults, so only the LinkedIn default applies to one. When you create a referral program without `rewards`, the goal also decides the starter rewards: most goals get one double-sided reward, `HEALTHCARE_PROVIDERS` gets a single-sided reward, `SUBSCRIBERS` gets a four-step milestone ladder, and `WAITLIST` gets a leaderboard. Every starter reward arrives switched off with a placeholder name, so the program awards nothing until the customer sets the amount and turns one on. `TELEHEALTH` is for consumer telehealth and wellness subscriptions, where patients refer friends; `HEALTHCARE_PROVIDERS` is for provider networks and clinician-facing products, where practices refer peer practices. `INSURANCE` replaces `ONLINE_INSURANCE`, which is still accepted and behaves identically. 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."
      • changedInput schema / properties / goal / enum
        Previous value: -[
        -  "CUSTOMERS",
        -  "USERS",
        -  "SUBSCRIBERS",
        -  "WAITLIST",
        -  "B2B_SAAS_SELF_SERVICE",
        -  "B2B_SAAS_ENTERPRISE",
        -  "B2C_SUBSCRIPTIONS",
        -  "FINANCIAL_SERVICES",
        -  "ONLINE_EDUCATION",
        -  "ONLINE_INSURANCE"
        -]New value: +[
        +  "CUSTOMERS",
        +  "USERS",
        +  "SUBSCRIBERS",
        +  "WAITLIST",
        +  "B2B_SAAS_SELF_SERVICE",
        +  "B2B_SAAS_ENTERPRISE",
        +  "B2C_SUBSCRIPTIONS",
        +  "FINANCIAL_SERVICES",
        +  "ONLINE_EDUCATION",
        +  "INSURANCE",
        +  "ONLINE_INSURANCE",
        +  "TELEHEALTH",
        +  "HEALTHCARE_PROVIDERS"
        +]
    • Changedgrowsurf_get_campaign_design2 fields changed
      • addedOutput schema / properties / theme / properties / widget
        Added value: +{
        +  "description": "Paid-plan color settings for the website widget.",
        +  "properties": {
        +    "backgroundColor": {
        +      "description": "Fill color of the button, and of the card's own button.",
        +      "maxLength": 255,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "borderRadius": {
        +      "description": "Corner rounding, as a CSS length such as `12px`.",
        +      "maxLength": 255,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "color": {
        +      "description": "Text and drawing color on the button, and on the card's own button.",
        +      "maxLength": 255,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / widget
        Added value: +{
        +  "description": "The website widget — the invite that sits in a corner of the customer's own site. It renders as a button or as a card, and its card folds back into the button when a visitor closes it. Both audience switches start off, so a program shows nothing until one is turned on.",
        +  "properties": {
        +    "appearance": {
        +      "description": "`BUTTON` is a single button in the corner. `CARD` is a small card with a heading, a line of text, and a button, which a visitor can close.",
        +      "enum": [
        +        "BUTTON",
        +        "CARD"
        +      ],
        +      "type": "string"
        +    },
        +    "artImageUrl": {
        +      "description": "The picture shown at the top of the card.",
        +      "maxLength": 500,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "buttonText": {
        +      "description": "The label on the card's button, which opens the program.",
        +      "maxLength": 100,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "icon": {
        +      "description": "An uploaded image instead of a `markKey` drawing. `CUSTOM` uses `iconImageUrl`; `NONE` shows no image. `DEFAULT` is the old GrowSurf image: a program already set to it keeps it and can read it back, but it cannot be set. Requires a paid plan.",
        +      "enum": [
        +        "CUSTOM",
        +        "NONE",
        +        "DEFAULT"
        +      ],
        +      "type": "string"
        +    },
        +    "iconImageUrl": {
        +      "description": "The uploaded image, used when `icon` is `CUSTOM`. Requires a paid plan.",
        +      "maxLength": 500,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "isArtShown": {
        +      "description": "Whether the card shows a picture above its text. Ignored by the button.",
        +      "type": "boolean"
        +    },
        +    "isHiddenOnMobile": {
        +      "description": "Whether to leave phones alone. On small screens the card fills the bottom of the page.",
        +      "type": "boolean"
        +    },
        +    "isShownToNewVisitors": {
        +      "description": "Whether people who have not joined the program see the widget.",
        +      "type": "boolean"
        +    },
        +    "isShownToParticipants": {
        +      "description": "Whether people who have already joined see the widget.",
        +      "type": "boolean"
        +    },
        +    "markKey": {
        +      "description": "The small drawing on the widget. It takes the colour chosen for the widget, so it matches on any background. `null` for no drawing.",
        +      "enum": [
        +        "GIFT",
        +        "TICKET",
        +        "DISCOUNT",
        +        "CASH",
        +        "PERK",
        +        "SHARE",
        +        "LINK",
        +        "INVITE",
        +        "FRIENDS",
        +        "THANKS",
        +        null
        +      ],
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "newVisitorDescription": {
        +      "description": "The line under the heading for people who have not joined. Card only.",
        +      "maxLength": 255,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "newVisitorText": {
        +      "description": "What people who have not joined read. It is the button's label, and the card's heading.",
        +      "maxLength": 100,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "offsetEdge": {
        +      "description": "How far in from the top or bottom edge, in pixels, following `placement`. Raise it to clear a chat button that already sits in that corner.",
        +      "maximum": 400,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "offsetSide": {
        +      "description": "How far in from the left or right edge, in pixels, following `placement`. For a centered placement it becomes an even gap on both sides.",
        +      "maximum": 400,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "pageRules": {
        +      "description": "Which pages the widget appears on. This controls the widget only — referral tracking, embedded elements, and opening the window from the site's own code keep working on every page where GrowSurf is installed.",
        +      "properties": {
        +        "mode": {
        +          "description": "`ALL` shows it everywhere. `ONLY` shows it just on the listed pages. `EXCEPT` shows it everywhere but the listed pages. With no pages listed, `ONLY` and `EXCEPT` behave as `ALL`.",
        +          "enum": [
        +            "ALL",
        +            "ONLY",
        +            "EXCEPT"
        +          ],
        +          "type": "string"
        +        },
        +        "patterns": {
        +          "description": "The pages to match. Use `*` to stand in for anything, as in `/portal/*`. A path on its own, such as `/pricing`, matches that path on every installed domain.",
        +          "items": {
        +            "maxLength": 500,
        +            "type": "string"
        +          },
        +          "maxItems": 20,
        +          "type": "array"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "participantDescription": {
        +      "description": "The line under the heading for people who have already joined. Card only.",
        +      "maxLength": 255,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "participantText": {
        +      "description": "What people who have already joined read. It is the button's label, and the card's heading.",
        +      "maxLength": 100,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "placement": {
        +      "description": "Which corner or edge of the page the widget sits against.",
        +      "enum": [
        +        "TOP_LEFT",
        +        "TOP_CENTER",
        +        "TOP_RIGHT",
        +        "BOTTOM_LEFT",
        +        "BOTTOM_CENTER",
        +        "BOTTOM_RIGHT"
        +      ],
        +      "type": "string"
        +    },
        +    "returnAfterDays": {
        +      "description": "Days before the card is offered again to someone who closed it. Until then they keep the button, so they can still open the program. `0` never offers it again.",
        +      "maximum": 365,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "reveal": {
        +      "description": "When the card appears: right away, after `revealDelaySeconds`, or once the visitor scrolls halfway down the page. The button always appears right away.",
        +      "enum": [
        +        "IMMEDIATE",
        +        "DELAY",
        +        "SCROLL"
        +      ],
        +      "type": "string"
        +    },
        +    "revealDelaySeconds": {
        +      "description": "Seconds to wait before showing the card, when `reveal` is `DELAY`.",
        +      "maximum": 120,
        +      "minimum": 0,
        +      "type": "integer"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedgrowsurf_get_participant1 field changed
      • addedOutput schema / properties / leadCount
        Added value: +{
        +  "description": "Pending referrals that have not converted yet.",
        +  "type": "integer"
        +}
  6. 1 tool updatev0.16.0
    • Changedgrowsurf_list_participants1 field changed
      • addedInput schema / properties / metadata
        Added value: +{
        +  "additionalProperties": {
        +    "type": "string"
        +  },
        +  "description": "Exact-match filter on participant metadata, up to 3 keys, for example `{ \"customerId\": \"12345\" }`. Values compare as strings.",
        +  "maxProperties": 3,
        +  "minProperties": 1,
        +  "type": "object"
        +}
  7. 1 tool updatev0.15.1
    • Changedgrowsurf_bulk_delete_participants2 fields changed
      • changedOutput schema / description
        Previous value: -"Bulk delete outcome. A `200` response can still include `NOT_FOUND` or `ERROR` rows, so check the summary."New value: +"Bulk delete outcome. A `202` response includes `analyticsErasure` when analytics erasure is pending. Both `200` and `202` responses can include `NOT_FOUND` or `ERROR` rows, so check the summary."
      • addedOutput schema / properties / analyticsErasure
        Added value: +{
        +  "description": "Analytics erasure is pending. Reports can retain removed participants until erasure completes. Do not repeat successful deletions.",
        +  "properties": {
        +    "operationId": {
        +      "description": "Opaque reference for support inquiries about this analytics erasure.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "Erasure has been accepted but is not confirmed complete.",
        +      "enum": [
        +        "pending"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
  8. 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
  9. 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

B3.2/5.0

Scored across 63 tools

Disambiguation3/5

Most tools target distinct resources and actions, and the detailed descriptions help distinguish similar operations. However, the large set contains several overlapping generative/helper tools (integration guide, design advisor, agent eval, snippets, SDK guide) and recurring campaign-vs-program terminology that can make selection ambiguous.

Naming Consistency3/5

All names use a consistent growsurf_ prefix and snake_case, which aids scanning. But the set mixes verb-first action names (get_campaign, create_campaign_reward) with noun-phrase helpers (integration_guide, program_design_advisor, participant_auth_hash) and uses campaign and program inconsistently for the same core object.

Tool Count1/5

At 63 tools, the surface is far beyond a well-scoped set and creates significant selection overhead for an agent. Many documentation/snippet/advisor tools could be consolidated or omitted, and the rubric treats 50+ tools as an extreme mismatch.

Completeness4/5

Coverage is broad across programs, participants, rewards, webhooks, integrations, analytics, payouts, auth, and mobile SDK flows. Minor gaps remain, such as no campaign deletion (only status completion), no single-participant delete (bulk only), and no explicit reward-fulfillment tool, but core lifecycle operations are well represented.

Maintenance

ActivityActive
ResponsivenessUnresponsive

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
    34 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