GrowSurf MCP Server
OfficialGrowSurf MCP Server is an official CLI and MCP server for building and managing GrowSurf referral and affiliate programs through AI agents, with guided steps and safe REST API wrappers.
Create a GrowSurf account and API key, and manage team details and verification.
Create, list, get, update, and clone referral or affiliate programs (campaigns).
Configure programs: rewards, resources, design, emails, options, installation settings, and capture preview screenshots.
Manage participants: add, list, get, update, bulk delete, email, read analytics/activity logs, and request payout destination confirmation.
Perform referral and affiliate actions: trigger or cancel delayed referrals, record sales, and refund or chargeback transactions.
Manage webhooks: list, create, update, delete, test, and normalize payloads with idempotency keys.
Read analytics: program totals, time series, email metrics, engagement, activation cohorts, and participant analytics.
Discover and connect integrations; get dashboard connect links.
Generate guidance and snippets: integration plans, mobile SDK, API libraries, client/embeddable code, auto-auth, design advice, troubleshooting, and eval prompts.
Generate participant auth HMAC hashes and create mobile participant tokens.
Run as a local stdio CLI (npx) or MCP server with full or compact tool surface.
Provides native Android SDK implementation guidance for integrating GrowSurf referral tracking, including attribution, shareUrl sharing, trackShare, and the native GrowSurf Window.
Provides native iOS SDK implementation guidance for integrating GrowSurf referral tracking, including attribution, shareUrl sharing, trackShare, and the native GrowSurf Window.
Supports connecting Mailchimp to GrowSurf for syncing signups and contacts, with integration status and a dashboard connect link.
Supports connecting PayPal to GrowSurf for payouts and payment processing, with integration status and a dashboard connect link.
Supports connecting Resend to GrowSurf for email delivery, with integration status and a dashboard connect link.
Supports connecting Stripe to GrowSurf for payment processing and referral-related payment data, with integration status and a dashboard connect link.
Supports connecting Wise to GrowSurf for affiliate payouts, with integration status and a dashboard connect link.
Supports connecting Zapier to GrowSurf for workflow automation, with integration status and a dashboard connect link.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@GrowSurf MCP ServerCreate a referral program for my fitness app with a 20% discount reward."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
GrowSurf MCP Server
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.
Learn more about GrowSurf at https://growsurf.com
Start with direct REST at https://growsurf.com/agent-start.md
Read the OpenAPI contract at https://growsurf.com/openapi.json
Read the Arazzo workflow at https://growsurf.com/arazzo.yaml
Learn about optional MCP setup at https://docs.growsurf.com/build-with-ai#optional-connect-mcp
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 and React Native 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-toolkitSteering 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
Choosing a tool
Use program and participant tools to read or change records. Guidance tools return advice or code for you to apply:
Task | Tool |
Choose a program design and reward structure |
|
Plan a web integration |
|
Get browser JavaScript examples |
|
Get one embeddable element's HTML |
|
Generate page-level participant auto authentication code |
|
Get backend REST API library examples |
|
Integrate a native iOS, Android, or React Native app |
|
Diagnose a program problem |
|
Generate checks for an agent's program-creation workflow |
|
Published tool names and fields use campaign for a program, including campaignId. These identifiers remain supported. Display titles use program terminology; Campaign Reward remains the name for a reward configuration.
To delete one participant, pass one ID or email in participants to growsurf_bulk_delete_participants. The same permanent-deletion warnings apply. A separate single-participant tool is not needed. Program deletion and explicit reward fulfillment are outside this MCP tool set; completing a program is not deletion, and configuring a reward is not proof that it was delivered.
Optional compact connection
The default connection lists all 63 tools. Add --compact to select 32 tools for program setup, installation, participant management, referral tracking, rewards, and analytics. Your credential permissions can reduce the visible set further.
npx -y @growsurfteam/growsurf-mcp --compactIn a stdio client configuration, append "--compact" to the package's args array. Server integrations can call createGrowSurfMcpServer({ toolSurface: "compact" }). Omit the option to keep the full catalog.
Compact combines related guidance and settings tools:
Tool | Selection | Arguments |
|
| Put the selected guide's existing arguments under |
|
| Put |
| The same | Put |
For example, read a program's installation settings:
{
"name": "growsurf_get_program_settings",
"arguments": { "section": "installation", "input": { "campaignId": "YOUR_PROGRAM_ID" } }
}Program recommendations and troubleshooting keep their own tools. Participant reads, updates, deletion, referral actions, and sale or refund actions remain separate. Compact prompts, resources, guidance, and proposed configuration calls use the compact tool names and arguments.
Use the full connection for account creation, team administration, program cloning, participant resources, webhook creation/updates/deletion/tests, participant emails, payout destinations, and webhook normalization. Remove --compact and reconnect. These operations remain available with their existing contracts on the full connection; compact rejects calls to tools outside its catalog. The tool-selection table above describes the full connection.
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_IDas the default, pass acampaignIdargument to target a specific program, or callgrowsurf_list_campaignsto find available programs. For a newly created program, pass theidreturned bygrowsurf_create_campaignto the other tools.Static guidance/snippet tools can run without credentials
Exception:
growsurf_create_accountneeds 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 connecthttps://mcp.growsurf.comand 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-mcpThe 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 --versionSupported 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
Open or create Cursor's global MCP configuration at
~/.cursor/mcp.json.Add a server named
growsurfwith 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 growsurfFor 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-mcpAntigravity
Open Antigravity.
Click the … menu in the panel to the right and select MCP Servers.
Click Manage MCP Servers > View raw config.
Recommended: in the
mcp_config.jsonfile, add the hosted OAuth endpoint:
{
"mcpServers": {
"growsurf": {
"serverUrl": "https://mcp.growsurf.com"
}
}
}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 growsurfOr 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-mcpConfiguration
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'scampaignIdargument overrides it, so a single server can operate on any of your programs)GROWSURF_API_BASE_URL(optional; defaults tohttps://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)
The hash helper requires an explicit participantAuthSecret argument and never uses GROWSURF_PARTICIPANT_AUTH_SECRET. Use a test secret for MCP examples; authenticate users and sign with production secrets on your backend.
For webhooks, configure a signing secret and verify GrowSurf-Signature on your backend. GROWSURF_WEBHOOK_TOKEN is no longer used; keep secrets out of webhook URLs.
Run with npx
After publishing this package, customers can run:
npx @growsurfteam/growsurf-mcpFor local development in this repo:
npm install
npm run build
node dist/cli.jsMCP 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_guideStep-by-step guidance for implementing a GrowSurf referral or affiliate program.growsurf_mobile_sdk_guideNative iOS/Android or React Native SDK guidance for attribution,shareUrl,trackShare, and the native GrowSurf Window. Setplatformtoreact_nativefor the React Native SDK.growsurf_api_library_snippetsOfficial REST API library snippets for TypeScript, Python, PHP, Ruby, and Java.growsurf_list_integrationsList every integration the program can connect, each withconnected,enabled,autoDisabled, and the dashboardconnectUrl. Check this before acting on an integration.growsurf_get_integration_connect_linkGet 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_advisorReturns a short first draft by default. Setdetail: "full"for the complete report, including reward, sharing, and integration figures.benchmarkFactscarries 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, aconfigurationPlanwith exact tool arguments, anddecisionswith the qualifying action and unresolved customer choices. Call it before proposing rewards. Preserve the returned call shapes; the advisor and program-creation tools use differentgoalenums. Replace each<new-program-id>with theidreturned by program creation. Drafts leave reward amounts and commission terms open until the customer chooses them; a budget is a limit, not an incentive. SetsalesMotiontosales_ledfor demos or negotiated contracts, orself_servicefor 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_trackingSymptom-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 asymptomkey, or adescriptionthat names the symptom.
Client & UI Snippets
growsurf_client_snippetsJavaScript SDK, GrowSurf Window, and embeddable examples. Includes a reminder to use a frontend design workflow when placing or styling embeddable UI.growsurf_embeddable_element_snippetHTML snippet for a specific GrowSurf embeddable element.growsurf_grsf_config_snippet<head>snippet for configuringwindow.grsfConfigand participant auto-auth.
Account onboarding
growsurf_create_accountCreate a GrowSurf account and get an API key. This is the only tool that does not requireGROWSURF_API_KEY. The returned key is shown once and locked (403EMAIL_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_teamFetch the team bound to the API key or OAuth connection, including its GrowSurf verification state.growsurf_update_teamUpdate the bound team's display name.growsurf_request_team_verificationAsk GrowSurf to verify the bound team, which is required before a program can email participants.growsurf_resend_team_owner_verification_emailResend the verification email to the bound team's owner without revealing their email address.
API & Tracking
growsurf_get_campaignFetch campaign configuration.growsurf_list_campaignsList programs available to the credential. Use this to find acampaignIdbefore calling campaign-scoped tools.growsurf_get_campaign_analyticsFetch program analytics, with optional per-periodseries, comparison, status, rate, email metrics viainclude=email, and participant activity-period engagement viainclude=engagement.growsurf_get_campaign_activation_analyticsFetch eligible-participant activation cohorts with a fixed 7- or 30-day observation window. Referral programs group byenrolledAsAdvocateAt; affiliate programs group byapprovedAsAffiliateAt. ReadcoverageStartAt,state, andreasonbefore interpreting zeroes or nulls.growsurf_create_campaignCreate a new program (campaign) with type-appropriate starter content and optional inline rewards (only needsGROWSURF_API_KEY, notGROWSURF_CAMPAIGN_ID). Review the seeded Design, Emails, Options, Installation, rewards, and GrowSurf Window content before patching.growsurf_agent_program_creation_evalGenerate 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_campaignUpdate the program's identity and lifecycle: name, company branding, and status (only the fields you send are changed).growsurf_clone_campaignClone the program into a newDRAFTprogram (integrations and credentials are not copied).growsurf_list_campaign_rewardsList the program's configured rewards.growsurf_create_campaign_rewardCreate a campaign reward.growsurf_update_campaign_rewardUpdate a campaign reward by its reward key.growsurf_delete_campaign_rewardDelete a campaign reward by its reward key.growsurf_list_program_resources/growsurf_create_program_resource/growsurf_update_program_resource/growsurf_delete_program_resourceManage ordered participant resources. LINK uses HTTPS and TEXT uses plain text.growsurf_prepare_program_resource_fileRequest 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_designRead or patch design configuration, including the Program Editor Design tab and payout-destination confirmation page copy.growsurf_get_campaign_emails/growsurf_update_campaign_emailsRead or patch the Program Editor Emails tab config.growsurf_get_campaign_options/growsurf_update_campaign_optionsRead or patch the Program Editor Options tab config, including the program'slanguages.growsurf_get_campaign_installation/growsurf_update_campaign_installationRead or patch the Program Editor Installation tab config.growsurf_capture_referral_flow_screenshotsCapture 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_webhooksList the program's webhooks (secrets are never returned).growsurf_create_campaign_webhookAdd a webhook to the program (with events and a write-only signing secret).growsurf_update_campaign_webhookUpdate a webhook by id (primaryfor the program's primary webhook).growsurf_delete_campaign_webhookRemove a webhook by id.growsurf_test_campaign_webhookSend a live test event to a webhook using its stored URL and secret.growsurf_add_participantAdd a participant (or referred participant) during signup.growsurf_list_participantsList participants in the current program, paginated bynextId. Passmetadata(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_participantFetch one participant by GrowSurf participant ID or email address.growsurf_update_participantUpdate a participant by ID or email (including internalnotesand the participant'slanguage).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-rowDELETED/NOT_FOUND/DUPLICATE/ERRORresults. Irreversible — removes the participants' referrals, rewards, commissions, and payout records.growsurf_email_participantEmail a participant using a configured template or a free-form subject/body.growsurf_get_participant_analyticsFetch one participant's engagement, rank, share, affiliate revenue, commission, payout, optional email metrics, and covered first milestones. Useinclude=activationfor milestones such asfirstPortalViewedAtandfirstShareChannel; addseriesfor coveredportalViewsandshareActions. An unavailable null is unknown, not proof that the action never happened.growsurf_get_participant_activity_logsList a participant's activity logs (offset/limit paginated).growsurf_trigger_referralTrigger referral (for referral programs only). Optionally passdelayInDays(1-90) to hold the credit for N days before awarding it (e.g. to cover a refund window).growsurf_cancel_delayed_referralCancel a pending delayed referral trigger before the delay elapses (e.g. on refund/cancellation).growsurf_get_participant_payout_destinationGet 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_confirmationAsk a participant to confirm their payout destination for a provider — sends them a one-time confirmation link (only the participant can confirm).growsurf_record_saleRecord affiliate sales or transactions (for affiliate programs only).growsurf_refund_transactionRecord an amendment (refund, partial refund, or chargeback) against a recorded transaction; reverses or adjusts the referrer's commission (for affiliate programs only). The inverse ofgrowsurf_record_sale.growsurf_create_mobile_participant_tokenCreate or fetch a participant, then create a participant-scoped mobile SDK token for a signed-in mobile user.
Helpers
growsurf_participant_auth_hashGenerate participant auto-auth HMAC hashes (to authenticate participants automatically).growsurf_webhook_normalizeNormalize 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
secreton the webhook and verify theGrowSurf-Signatureheader on receiptValidate 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 testAdditional Resources
Read developer docs at the following:
JavaScript SDK reference: https://docs.growsurf.com/developer-tools/javascript-sdk/api-reference
REST API reference: https://docs.growsurf.com/developer-tools/rest-api/api-reference
REST API libraries: https://docs.growsurf.com/developer-tools/rest-api/api-libraries
Native mobile guide: https://docs.growsurf.com/getting-started-for-mobile
Android SDK: https://docs.growsurf.com/developer-tools/android-sdk
React Native SDK: https://docs.growsurf.com/developer-tools/react-native-sdk
Getting Started with GrowSurf: https://docs.growsurf.com/getting-started
The GrowSurf MCP server helps GrowSurf customers implement referral programs and affiliate programs quickly.
Available Tools
63 toolsgrowsurf_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.
| Name | Required | Description | Default |
|---|---|---|---|
| Yes | |||
| language | No | The language of the participant's portal and program emails. Must be one of the program's languages (`languages` in `growsurf_get_campaign_options`); any other code returns a `400`. Applies only when this call creates the participant. Omit it or send `null` to use the program's base language. Supported codes: `en`, `es`, `fr`, `de`, `it`, `pt-BR`, `nl`, `pl`, `sv`, `tr`, `ja`, `ko`, `zh-CN`, `id`, `da`, `nb`, `nn`, `fi`, `is`, `cs`, `sk`, `hu`, `ro`, `hr`, `sl`, `et`, `lv`, `lt`, `el`, `bg`, `uk`, `ru`, `pt-PT`, `ca`, `vi`, `ms`, `fil`, `af`, `sw`. | |
| lastName | No | ||
| metadata | No | ||
| firstName | No | ||
| ipAddress | No | ||
| campaignId | Yes | 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. | |
| referredBy | No | ||
| fingerprint | No | ||
| isAffiliate | No | Affiliate 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. | |
| referralStatus | No | ||
| mobileInstanceId | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the generic safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false, openWorldHint=false), so the description carries real added value: it discloses that existing participants are returned unchanged, that enrollment bypasses affiliate review, and that a new participant may be silently created with affiliateStatus: APPROVED. It does not mention auth/permission requirements or rate limits, keeping it out of the top tier.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is a dense but front-loaded paragraph that leads with the core add-or-fetch behavior and then layers the conditional enrollment rules in a logical order. Sentences are long and information-packed rather than padded, with no filler, though the final conditional sentence is somewhat convoluted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 documented, and the description handles the campaignId default and enrollment branching well. Still, for a 12-parameter mutation tool at 25% schema coverage, several parameters (referralStatus, fingerprint, mobileInstanceId) and any permission/scope requirements remain undocumented, leaving gaps an agent may hit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 25% across 12 parameters, and the description compensates well for the hardest ones (isAffiliate, referredBy, campaignId fallback to GROWSURF_CAMPAIGN_ID, email as the lookup key). But it leaves metadata, firstName, lastName, ipAddress, fingerprint, mobileInstanceId, and the referralStatus enum entirely unexplained, so it only partially fills the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource and a lookup key: 'Add or fetch a participant by email,' and immediately clarifies upsert semantics ('Existing participants are returned unchanged'), which behaviorally distinguishes it from growsurf_get_participant and growsurf_update_participant. It stops short of naming a sibling or stating the read-only alternative, so it falls just below the top tier.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit routing context for the tricky cases: 'trusted direct enrollment and bypasses the public application review flow for affiliates,' plus conditional rules for isAffiliate and referredBy. However, it never says when to prefer this tool over growsurf_get_participant (pure read) or growsurf_update_participant (modify existing), leaving the main sibling-selection decision to inference.
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_evalGenerate Program Creation ChecksARead-onlyIdempotentInspect
Generate Markdown prompts and acceptance checks for evaluating an agent's program-creation workflow: starter content, rewards, configuration, and frontend installation. Does not create a program or run the checks. Use growsurf_program_design_advisor to choose a program design, or growsurf_integration_guide to plan its web integration.
| Name | Required | Description | Default |
|---|---|---|---|
| programType | No | both | |
| includeOneShotPrompts | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
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 facts: the output is Markdown prompts/acceptance checks and nothing is created or executed, which a name like 'eval' would otherwise imply. It stops short of describing depth/format of the generated checks, but that is partly covered by the output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler: the deliverable and scope come first, the non-goal and sibling routing second. Every clause carries information an agent needs for selection.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return-value detail is not required, and annotations cover the read-only/idempotent nature. The only meaningful hole is parameter meaning, which the description does not address; otherwise it is complete for a two-parameter generation tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for two parameters, and the description mentions neither programType nor includeOneShotPrompts. The enum values (referral/affiliate/both) and the boolean's name are partly self-explanatory, but there is no explanation of how programType narrows the generated checks or what 'one-shot prompts' produce, so the description fails to compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and artifact ('Generate Markdown prompts and acceptance checks') plus the exact evaluation scope (starter content, rewards, configuration, frontend installation). It also names two siblings and what they are for, so an agent can separate it from growsurf_program_design_advisor and growsurf_integration_guide 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: use program_design_advisor to pick a design, or integration_guide to plan web integration. It also states a negative boundary in plain terms ('Does not create a program or run the checks'), which prevents mistaking it for growsurf_create_program_resource.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_api_library_snippetsGenerate REST API Library SnippetsARead-onlyIdempotentInspect
Generate Markdown code examples for the official backend REST API libraries in TypeScript, Python, PHP, Ruby, and Java. Select language and workflow; both default to all. Covers setup, program lookup, participant creation, referral credit, sales, and mobile participant tokens. Returns code without executing API calls. Use growsurf_client_snippets for browser JavaScript or growsurf_mobile_sdk_guide for native or React Native app setup.
| Name | Required | Description | Default |
|---|---|---|---|
| No | |||
| language | No | all | |
| workflow | No | all | |
| campaignId | No | ||
| referredBy | No | ||
| participantIdOrEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the full safety profile (readOnlyHint, idempotentHint, destructiveHint=false, openWorldHint=false), so the bar is lower. The description usefully adds that it returns code without executing API calls, clarifying this is pure generation, but offers nothing on output shape or limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then selection parameters, coverage, the no-execution constraint, and finally sibling routing. Four sentences with no padding; each adds distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 the safety profile. The only real gap is the four context parameters (email, campaignId, referredBy, participantIdOrEmail) that an agent gets no guidance on anywhere.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 load. It explains `language`, `workflow`, their `all` defaults, and what the workflow values cover, but leaves `email`, `campaignId`, `referredBy`, and `participantIdOrEmail` entirely undocumented in both schema and description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb (Generate) plus resource (Markdown code examples for official backend REST API libraries) with the target languages enumerated. It clearly separates itself from snippet-producing siblings by naming backend REST libraries versus browser/native SDKs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing conditions: use `growsurf_client_snippets` for browser JavaScript and `growsurf_mobile_sdk_guide` for native/React Native setup. It also states the tool returns code without executing API calls, so there is no ambiguity about side effects.
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 ParticipantsADestructiveIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. | |
| participants | Yes | GrowSurf participant IDs and/or email addresses to delete (1-200 entries; mixed lists allowed). |
Output Schema
| Name | Required | Description |
|---|---|---|
| results | No | One entry per submitted identifier, in request order. |
| summary | No | Counts across all submitted entries. |
| analyticsErasure | No | Analytics erasure is pending. Reports can retain removed participants until erasure completes. Do not repeat successful deletions. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Excellent transparency beyond annotations: explicitly states deletion is permanent and irreversible, lists cascading effects (referrals, rewards, commissions, payout records removed), explains status codes, and clarifies the 202 analyticsErasure behavior and that repeating rows won't finish erasure. Adds significant actionable context not captured in annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and critical destructive warning, then efficiently covers chunking, return values, and edge cases. Slightly dense with detail but every sentence serves a purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the 2-parameter schema with full coverage, output schema existence, and the tool's destructive nature, the description covers everything needed: immutability warning, cascading effects, chunking guidance, status semantics, and analytics erasure nuances. No critical gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so parameter documentation is already thorough. The description adds clarification that mixed lists are allowed and re-iterates the 200-entry limit, but does not provide additional semantic depth beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (delete) and resource (participants) with explicit scope (bulk, one request, from your GrowSurf program). Clearly distinguished from siblings like list_participants 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains chunking for lists over 200 entries and mentions campaignId defaulting behavior, but does not explicitly state when to use this tool versus alternatives (e.g., single participant deletion via update_participant). Usage context 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_cancel_delayed_referralCancel Delayed ReferralADestructiveIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. | |
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| message | No | Human-readable result message. Present when credit was not awarded immediately. |
| success | No | Whether referral credit was awarded, scheduled, or cancelled. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, so the safety profile is covered. The description adds the meaningful effect (a pending trigger is removed, and only before the delay elapses), but says nothing about permissions, what happens if no trigger is pending, or error behaviour.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, front-loaded with the action and its timing constraint. The trailing 'Returns { success, message }' is largely redundant given an output schema exists, which keeps it out of 5 territory.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema and rich annotations, the missing pieces are narrower: the participant-identifier choice and the no-pending-trigger / error case. For a destructive mutation tool, that leaves an agent guessing on inputs even though the effect and safety profile are covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 33% and the description does not compensate: it never explains the participantId/participantEmail anyOf, which is the key input decision. The campaignId fallback it restates is already worded in the schema itself, so it adds no new meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: cancelling a pending delayed referral trigger, with the timing constraint ('before the delay elapses'). The 'delayed referral trigger' framing distinguishes it from the sibling growsurf_trigger_referral, which creates rather than cancels triggers.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives one motivating scenario ('e.g. on refund/cancellation'), which implies when to reach for it, but names no alternatives, prerequisites, or when-not conditions. An agent still has to infer the boundary between this and growsurf_refund_transaction or growsurf_trigger_referral.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| expiresAt | No | When the signed URLs stop working (ISO 8601). |
| generatedAt | No | When the screenshots were captured (ISO 8601). |
| screenshots | No | One entry per captured view. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations covering the safety profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false), the description still adds real value: short-lived URLs with an UTC expiresAt, screenshots reflect the saved program at capture time, and installation on the customer's site is not verified. The note that 'a failed inline image alone does not establish that the URL expired' is an unusually useful failure-mode disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Six sentences but each carries distinct information: purpose, return shape, capture semantics, non-verification caveat, failure-mode caveat, boundary exclusions, and targeting rule. It is front-loaded and free of filler, though slightly denser than needed for a one-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though an output schema exists (so return values need not be explained), the description still characterizes the returned URLs and their expiry, plus capture semantics and failure modes. An agent has everything required to decide when to call it and how to interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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' merely restates the schema default, though it is worth noting the schema marks campaignId required while both sources describe an omitted-parameter default.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb+resource ('Capture temporary GrowSurf preview screenshots') and states the precondition ('after a draft program is saved'). No sibling tool produces screenshots, and the scoping to the referrer Window and referred-friend experience makes the output concrete.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly states the triggering context ('after a draft program is saved') and draws explicit negative boundaries ('does not accept arbitrary URLs, HTML, JavaScript, or external screenshot targets'). It does not name an alternative sibling, but no sibling performs this function, so the routing gap is minor.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_client_snippetsGenerate Browser JavaScript SnippetsARead-onlyIdempotentInspect
Generate Markdown browser JavaScript and CSS examples for referral tracking, embeddable elements, and the GrowSurf Window, with placement guidance. Does not install code or change a program. Use growsurf_embeddable_element_snippet for one HTML element, growsurf_grsf_config_snippet for window.grsfConfig, or growsurf_api_library_snippets for backend REST code.
| Name | Required | Description | Default |
|---|---|---|---|
| programType | No | both | |
| singlePageApp | No | ||
| referralTrigger | No | signup_plus_qualifying_action | |
| includeUnreadBadge | No | ||
| includeGrowSurfWindow | No | ||
| participantAuthEnabled | No | ||
| includeEmbeddableElements | No | ||
| includeEventSubscriptions | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
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 still adds real value by negating side effects ("Does not install code or change a program") and by disclosing the output form (Markdown) and that placement guidance is included. It does not describe pagination or output length, but this is a generator tool where that matters little.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, both front-loaded: the capability first, then the explicit sibling routing. No filler, no repetition of the title, and every clause carries selection-relevant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 what the tool produces, what it deliberately does not do, and how it differs from its neighbors. The one gap is that the 8 optional configuration parameters are left entirely to the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% across 8 parameters, so the description is the only place parameter meaning could be conveyed, and it says nothing about programType, singlePageApp, referralTrigger, or the various include* toggles. Two enums are self-explanatory and the boolean names are semi-descriptive, which keeps this above a 1, but the description does no compensating work for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (generate Markdown browser JavaScript and CSS examples) and enumerates the covered domains: referral tracking, embeddable elements, and the GrowSurf Window. It also names the three sibling snippet tools it is not, so an agent can distinguish it 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing: use growsurf_embeddable_element_snippet for a single HTML element, growsurf_grsf_config_snippet for window.grsfConfig, and growsurf_api_library_snippets for backend REST code. Each alternative is paired with the condition that selects it, leaving nothing to inference.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false), and the description adds genuinely non-derivable behavior: what is copied (active rewards) versus what is not (integrations, credentials), plus the fact that the output is a DRAFT. It stops short of noting that repeated calls create duplicates (non-idempotency) 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, result state front-loaded, then the copy semantics, then the parameter resolution rule. No hedging or filler; every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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, and the description covers the operation's key semantics and the single parameter's resolution. Minor gaps remain around error/conflict behavior and explicit sibling routing, but nothing needed to invoke it correctly is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter and schema description coverage is 100%, so the schema already documents campaignId, its fallback to GROWSURF_CAMPAIGN_ID, and the ID-reuse behavior. The description restates the fallback rather than adding syntax or format detail, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb (clone) plus resource (GrowSurf program/campaign) and a concrete outcome: a new DRAFT program. It also disambiguates GrowSurf's 'program = campaign' terminology, which matters given both growsurf_create_campaign and growsurf_clone_campaign exist as siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: clone duplicates an existing campaign's configuration rather than building a new one from scratch, which contrasts with growsurf_create_campaign. However no sibling is named and no explicit when-to-use/when-not-to-use condition is stated.
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 AccountADestructiveInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| Yes | |||
| company | No | ||
| lastName | No | ||
| firstName | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| No | Email address for the new account. | |
| apiKey | No | An 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. |
| verificationStatus | No | Team verification state for the new account. |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| goal | No | 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. | |
| name | No | ||
| type | Yes | ||
| rewards | No | 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. | |
| companyName | No | ||
| currencyISO | No | ||
| companyLogoImageUrl | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | ||
| event | No | 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. | |
| limit | No | ||
| order | No | ||
| title | No | ||
| value | No | Tax 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`. | |
| imageUrl | No | ||
| metadata | No | ||
| isVisible | No | ||
| campaignId | Yes | 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. | |
| couponCode | No | ||
| description | No | ||
| isUnlimited | No | ||
| limitDuration | No | ||
| referredValue | No | Tax 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. | |
| numberOfWinners | No | ||
| referralCouponCode | No | ||
| commissionStructure | No | 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. | |
| conversionsRequired | No | ||
| nextMilestonePrefix | No | ||
| nextMilestoneSuffix | No | ||
| referralDescription | No | ||
| referredRewardUpfront | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safety profile (not read-only, not idempotent, not destructive), lowering the bar. The description adds a genuine behavioral constraint the annotations don't carry: type/program compatibility (AFFILIATE-only for affiliate programs) and the campaignId defaulting rule. It stops short of auth requirements or failure modes, but this is solid added context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, purpose first, then the type-compatibility rule, then the targeting rule. Nothing is redundant, though the constraint sentence is somewhat dense for the space it gets.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The output schema exists so return values needn't be explained, and the program-type rule is the single most important piece of context for this tool. But for a 23-parameter mutation tool with nested objects, the description is far from complete — it omits required pairings, the meaning of the many optional fields, and error behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 23 parameters at only 22% schema description coverage, the description must carry the semantic load and does not. It explains only `type` and `campaignId`, leaving 21 parameters (including the nested value/referredValue/commissionStructure objects) undocumented in prose, so an agent gets little beyond the raw schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (create) plus resource (campaign reward / reward config) and names the parent program scope. It is trivially distinguishable from siblings like update_campaign_reward, delete_campaign_reward, and list_campaign_rewards.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives real routing context: `type` must match the program type, and campaignId falls back to GROWSURF_CAMPAIGN_ID. However it never names the sibling tools an agent might confuse it with (update/delete/clone reward), so the when-not guidance is only implicit.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| events | No | ||
| secret | No | Write-only. Signs deliveries; never returned. | |
| isEnabled | No | ||
| campaignId | Yes | 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. | |
| payloadUrl | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the mutation profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false, openWorldHint=true). The description adds genuinely non-obvious behavior: secret is write-only, is never returned, and is used to produce the GrowSurf-Signature HMAC header on deliveries. It does not disclose rate limits or repeated-call behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five information-dense sentences, purpose front-loaded, each clause carrying real semantics (write-only secret, signature header, env-var fallback). Slight redundancy in restating that payloadUrl is required, which the schema already marks.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 annotations carry the safety profile. The description covers the mutation semantics an agent needs, with the only real gap being the isEnabled flag and any note on how to verify the webhook afterward.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With only 40% schema description coverage, the prose compensates well for four of five parameters (payloadUrl required, events omitted means no subscriptions, secret write-only signing semantics, campaignId defaulting to the env var). isEnabled is left entirely undocumented in both schema and description, so it is not fully covered.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Add a webhook to your GrowSurf program'), which cleanly separates it from the update/delete/test webhook siblings by verb alone. It does not name any sibling explicitly, so it falls short of the top mark.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the campaignId fallback to GROWSURF_CAMPAIGN_ID and the 'omit events to subscribe to no events' note give context for calling it, but there is no explicit when-to-use guidance or steering toward growsurf_update_campaign_webhook / delete siblings.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| Yes | |||
| language | No | The language of the participant's portal and program emails. Must be one of the program's languages (`languages` in `growsurf_get_campaign_options`); any other code returns a `400`. Applies only when this call creates the participant. Omit it or send `null` to use the program's base language. Supported codes: `en`, `es`, `fr`, `de`, `it`, `pt-BR`, `nl`, `pl`, `sv`, `tr`, `ja`, `ko`, `zh-CN`, `id`, `da`, `nb`, `nn`, `fi`, `is`, `cs`, `sk`, `hu`, `ro`, `hr`, `sl`, `et`, `lv`, `lt`, `el`, `bg`, `uk`, `ru`, `pt-PT`, `ca`, `vi`, `ms`, `fil`, `af`, `sw`. | |
| lastName | No | ||
| metadata | No | ||
| firstName | No | ||
| ipAddress | No | ||
| campaignId | Yes | 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. | |
| referredBy | No | ||
| fingerprint | No | ||
| isAffiliate | No | Sets whether the participant is an affiliate. Use `true` only for trusted direct enrollment. Public applicants should follow the program's configured application flow. | |
| referralStatus | No | ||
| mobileInstanceId | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| isNew | No | Whether this request created a new participant. |
| expiresIn | No | Token lifetime in seconds. |
| participant | No | The participant record (same shape as the `growsurf_get_participant` result). |
| participantToken | No | Participant-scoped bearer token for GrowSurf mobile SDK participant endpoints. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations already declaring readOnlyHint=false, idempotentHint=false and destructiveHint=false, the description still adds meaningful behavior: it creates *or* fetches a participant, performs trusted direct enrollment that skips review, and resolves the target campaign from `GROWSURF_CAMPAIGN_ID` when not passed. It omits token lifetime/scope, what happens on repeat calls, and any auth/permission requirements for the mutation side.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, with the core action front-loaded before the trust/flow caveat and the campaign-resolution detail. Minor filler ('via GrowSurf REST') could be cut, but nothing is bloated or buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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, and the description does cover the dual create-or-fetch nature and trusted-enrollment semantics. For a 12-parameter, nested-object tool it still leaves too much unaddressed: no permissions/auth needs, no note on what fetching an existing participant means for the other parameters, and no token characteristics.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 25% across 12 parameters, so the description carries the compensation burden and largely fails to meet it. Its only parameter-relevant statements ('targets campaignId', 'trusted direct enrollment' for isAffiliate) restate what the schema's own `campaignId` and `isAffiliate` descriptions already say, leaving metadata, referralStatus, mobileInstanceId, ipAddress, fingerprint and the rest undocumented in both places.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific compound operation: create/fetch a participant, then mint a participant-scoped mobile SDK token 'via GrowSurf REST'. That is far more specific than the title alone and distinguishes it from plain participant tools. It stops short of explicitly contrasting itself with the closest sibling, growsurf_participant_auth_hash, so an agent still has to infer which token mechanism applies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a real usage condition — participant creation here is 'trusted direct enrollment' that 'bypasses the public application review flow' — which tells the agent this is not the path for public applicants. However, it never names an alternative tool or states when to prefer growsurf_add_participant, growsurf_participant_auth_hash, or the public application flow; the routing 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_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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Used only with `LINK`. | |
| text | No | Used only with `TEXT`. | |
| type | Yes | ||
| title | Yes | ||
| category | No | ||
| campaignId | Yes | 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. | |
| description | No | ||
| isPublished | No | ||
| uploadResult | No | The unmodified result returned by the secure upload flow. Used only with `FILE`. | |
| uploadTicket | No | The one-time upload ticket. Used only with `FILE`. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the mutation profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false), yet the description adds real value beyond them: resources default to draft unless isPublished is set, files are capped at 10 MB, and the uploadTicket is one-time with an unmodified uploadResult. Auth requirements and rate limits are unaddressed, keeping this below 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the type distinctions before the flow/default details, then closes with the reference link and campaign targeting. It is a dense single paragraph with no redundancy, though the API reference URL and the closing targeting sentence are slightly less essential than the type constraints.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 the safety profile. The description supplies the type-specific constraints and default-publish behavior, but omits the prerequisite step of obtaining the upload ticket, which an agent calling the FILE branch would need.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50% over 10 params; the schema already documents url, text, uploadTicket, uploadResult, and campaignId with essentially the same wording the description repeats. The description does add the isPublished default semantics, but leaves title, category, and description unexplained, and its "campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID" claim sits awkwardly against a schema where campaignId is required.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ("Create") and resource ("a FILE, LINK, or TEXT resource for participants") and immediately distinguishes the three variants. An agent can tell this apart from growsurf_update_program_resource or growsurf_list_program_resources 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear per-type conditions (LINK requires an HTTPS url, TEXT requires text, FILE requires uploadTicket + uploadResult) and states the draft-vs-published behavior. It never names the sibling alternatives it interacts with, notably growsurf_prepare_program_resource_file for the FILE flow, so the routing guidance is implicit 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_delete_campaign_rewardDelete Campaign RewardADestructiveIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. | |
| campaignRewardId | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | The deleted campaign reward id. |
| success | No | Whether the campaign reward was deleted. |
TDQS
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 genuinely useful extra context: the reward is deactivated, dropped from the reward set, and connected upfront-discount coupons are cascaded-cleaned. That cascade is a non-obvious side effect an agent needs before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the action and its side effects, then parameter and return notes. Nothing is wasted or buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive mutation with an output schema already covering the { id, success } return and annotations covering the safety profile, the description supplies the missing pieces: cascading cleanup behavior and the campaign target resolution rule.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
campaignRewardId has no schema description, and the text compensates by identifying it as the reward key. campaignId's fallback to GROWSURF_CAMPAIGN_ID is repeated from the schema, and the phrasing 'if you pass it' implies optionality while the schema marks it required, a minor ambiguity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (delete) and resource (campaign reward / reward config) plus the program scope. An agent can distinguish it from siblings like growsurf_update_campaign_reward and growsurf_delete_campaign_webhook 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description never explicitly says when to delete vs. update or deactivate a reward, nor when not to use it. Usage is implied by the verb and the campaignId targeting note, which is enough to function but leaves the alternatives to inference.
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 WebhookADestructiveIdempotentInspect
Remove a webhook from your GrowSurf program by id. Returns { id, success }. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| webhookId | Yes | ||
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | Id of the webhook that was deleted. |
| success | No | Whether the webhook was deleted. |
TDQS
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 the response shape ({ id, success }) and the environment-variable fallback for targeting, which goes beyond the annotations, though it omits irreversibility/confirmation guidance.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, no filler: action and scope first, then return value, then targeting rule. Every sentence carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists and annotations cover the destructive/idempotent semantics, so the description is nearly sufficient for a two-parameter delete. The one gap is that it does not reconcile its 'otherwise GROWSURF_CAMPAIGN_ID' defaulting language with the schema's requirement that campaignId be passed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50% (campaignId documented, webhookId bare), so the baseline is 3. The description adds the GROWSURF_CAMPAIGN_ID fallback for campaignId, but it also implies campaignId is optional while the schema marks it required, which muddies rather than clarifies the parameter contract.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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') and scopes it by id, which clearly separates it from list_campaign_webhooks, create_campaign_webhook, update_campaign_webhook, and test_campaign_webhook. An agent can pick this tool 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explains which program the call targets (explicit campaignId vs GROWSURF_CAMPAIGN_ID fallback), which is useful context, but it never states when to use this tool versus its webhook siblings or any prerequisite such as resolving a webhook id first. Usage is implied by the name 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_program_resourceDelete Program ResourceADestructiveIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. | |
| resourceId | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | The deleted resource id. |
| success | No | Whether the resource was deleted. |
TDQS
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 new behavioral context by specifying that the reusable Media Center asset survives the delete, which is exactly the kind of collateral-damage clarification a destructive tool needs, though it omits auth requirements and reversibility.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler, with the primary action front-loaded and the two clarifications (asset preservation, target resolution) following in priority order. Nothing is redundant with the title or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 destructiveness/idempotency. For a two-parameter destructive call the description covers the essential risk caveat and target resolution; only auth/permission expectations and the undocumented resourceId remain thin.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50% – campaignId is fully documented in the schema (including the GROWSURF_CAMPAIGN_ID default and the note about new programs), while resourceId has no description at all. The description partially compensates by explaining campaignId targeting and by characterizing resourceId as a participant resource, but it gives no format, ID source, or lookup hint.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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 clarifies scope by noting the reusable Media Center asset is not removed, which disambiguates it from asset-level deletion. Siblings like create_program_resource / update_program_resource / list_program_resources are never named, so routing relies on the reader inferring the CRUD pattern.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the verb "delete" and the resource it targets, but there is no explicit when-to-use vs when-not, no named alternative, and no prerequisites (permissions, confirmations). The only actionable guidance is the campaignId resolution rule, which is targeting mechanics rather than usage policy.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_email_participantEmail ParticipantADestructiveInspect
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). For programs with settings.design.layoutMode set to INLINE, body must include {{emailFooter}}; {{emailHeader}} is optional. 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 Program 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.
| Name | Required | Description | Default |
|---|---|---|---|
| body | No | Free-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). | |
| subject | No | Free-form subject. Supports dynamic text (`{{...}}` tokens), the same as the body. | |
| emailType | No | The 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. `welcomeNonReferred` can only be sent to advocates or approved, enrolled affiliates in a program that has not ended. Referral programs: `welcomeNonReferred`, `referralLinkViewedFirstTime`, `referralLinkUsed`, `referredSignup`, `welcomeReferred`, `goalAchieved`, `campaignEndedWinners`, `campaignEndedNonWinners`, `progressUpdateMonthly`. Affiliate programs: `welcomeNonReferred`, `referralLinkViewedFirstTime`, `referredSignup`, `commissionGenerated`, `commissionAdjusted`, `payoutPending`, `payoutSentSuccess`, `progressUpdateMonthly`. | |
| preheader | No | ||
| campaignId | Yes | 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. | |
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | No | The email was accepted for delivery. |
| success | No | Whether the email request was accepted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only give generic flags (destructive, openWorld, non-idempotent); the description adds real operational context: auto-injected compliance footer, suppression of unsubscribed participants, the team-verification / verified-domain prerequisite, and that HTTP 400 is returned until verification exists. It also discloses the async nature ("accepted for delivery"), which the annotations do not.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then progressively adds constraints and prerequisites. It is dense and long, but nearly every sentence carries actionable constraint information; the inline enumeration of email types is verbose yet genuinely useful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 restated, and the description still explains the delivery semantics and 400-failure condition. Gaps are minor: it never warns that retries may produce duplicate sends (consistent with idempotentHint=false), nor how participantId vs participantEmail resolve when both are passed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 57%, and the description meaningfully compensates: `emailType` must be the camelCase key, valid values are enumerated per program type, `body` must include `{{emailFooter}}` under INLINE layout mode, and `campaignId` defaults to `GROWSURF_CAMPAIGN_ID`. It does not clarify precedence if both participantId and participantEmail are supplied.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Starts with a specific verb+resource: "Send an email to a participant (by GrowSurf participant ID or email)." This clearly distinguishes it from config-oriented siblings like get_campaign_emails and update_campaign_emails, which manage templates rather than send mail.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states the two mutually exclusive modes ("Provide EITHER `emailType` ... OR `subject` + `body`") and enumerates when each applies. It also lists which template types cannot be sent and the `welcomeNonReferred` eligibility rule, so an agent knows the boundaries before invoking.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_embeddable_element_snippetGenerate Embeddable Element HTMLARead-onlyIdempotentInspect
Generate one embeddable element's HTML as Markdown. Choose element; optionally include participant authentication attributes. Does not install the element or change a program. Use growsurf_client_snippets for a broader browser integration or growsurf_grsf_config_snippet for page-level participant auto authentication.
| Name | Required | Description | Default |
|---|---|---|---|
| element | Yes | ||
| participant | No | ||
| withAuthAttributes | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds useful context that it produces code and does not install anything or mutate a program, reinforcing the non-destructive nature beyond the annotation defaults.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the core action, then the constraint, then the sibling routing. No filler, and each sentence adds a distinct decision-relevant fact.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only code-generation tool with an output schema, the description covers purpose, scope limits, and alternatives adequately. The remaining gap is that the nested participant/auth parameter details are left entirely to a schema that has no per-field descriptions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It signals the two meaningful inputs ('Choose `element`' and 'optionally include participant authentication attributes'), which maps to the enum and the withAuthAttributes/participant params, but it does not document the enum options, the required email inside the nested participant object, or the default of withAuthAttributes.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Generate one embeddable element's HTML as Markdown') and explicitly distinguishes itself from two named siblings. An agent can identify the tool's role 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It names the alternatives and the conditions that select them ('growsurf_client_snippets for a broader browser integration or growsurf_grsf_config_snippet for page-level participant auto authentication') and clarifies the negative case ('Does not install the element or change a program').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_campaignGet ProgramARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | The program's unique id. |
| name | No | The program name (internal only, never shown to participants). |
| type | No | The program type. |
| status | No | The program status. |
| rewards | No | The program's reward configs (`CampaignReward`). Item shape is documented on the `growsurf_list_campaign_rewards` tool. |
| currencyISO | No | The program currency as an ISO 4217 code (e.g. `USD`). |
| inviteCount | No | Total invites sent by participants. |
| winnerCount | No | Participants with at least one approved reward. |
| referralCount | No | Total referrals. |
| rewardEvidence | No | What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere. |
| impressionCount | No | Total referral-link views across participants. |
| participantCount | No | Total participants. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, and closed-world, so safety is covered. The description adds genuine value beyond that: the warning that embedded reward settings do not imply a reward was earned/approved/delivered, and that earned-reward records belong to the participant — a real semantic caveat that prevents 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core fetch action and targeting rule, followed by the reward caveat. The caveat is slightly tangential to a get-details call but is compact and defensible; nothing is padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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, and the reward-semantics caveat covers the main interpretive risk. Combined with annotations, the description is sufficient for correct invocation, though a note on relation to list_campaigns would make it airtight.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema description coverage and a single parameter, the schema already explains campaignId, its default, and its behavior for newly created programs. The description's restatement of the same campaignId/GROWSURF_CAMPAIGN_ID fallback adds nothing beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb ('fetch') plus resource ('campaign/program details') makes the operation clear, and clarifying that 'campaign' equals 'program' helps terminology mapping. It does not, however, explicitly differentiate from the sibling growsurf_list_campaigns, so an agent must infer the single-vs-many distinction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description says how to target a campaign but never states when to use this tool versus alternatives like growsurf_list_campaigns, growsurf_get_campaign_design, or growsurf_update_campaign. No when-not conditions or prerequisites are given.
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 AnalyticsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| cohortTo | No | Exclusive eligibility-cohort end, Unix timestamp in ms. Must be greater than `cohortFrom`. | |
| timezone | No | IANA timezone used to advance cohort boundaries. Defaults to `UTC`. | |
| campaignId | Yes | 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. | |
| cohortFrom | No | Inclusive eligibility-cohort start, Unix timestamp in ms. Use with `cohortTo`. | |
| cohortInterval | No | Bucket size for `cohorts`. Defaults to `day`. | |
| observationWindowDays | No | Days after eligibility in which stages can count. Defaults to `30`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cohorts | No | Selected range split into exact half-open eligibility-cohort buckets. |
| timezone | No | IANA timezone used to advance cohort boundaries. |
| aggregate | No | Strict activation metrics for one exact enrollment cohort. |
| programType | No | Program eligibility model. |
| cohortInterval | No | Bucket size for `cohorts`. |
| coverageStartAt | No | Earliest expected complete activation capture time (Unix ms), or `null` until coverage begins. |
| portalViewedLabel | No | Program-specific display label for the stable `PORTAL_VIEWED` stage. |
| metricContractVersion | No | Shared activation and engagement metric version. |
| observationWindowDays | No | Days after eligibility in which stages count. |
| portalViewedHelperText | No | Display definition for a qualifying signed-in portal view. |
TDQS
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 substantive behavior: the fixed stage order, advocate vs affiliate cohort grouping fields, the per-participant observation window, and a critical caveat that zero/null may reflect unavailable history rather than no action.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but well ordered: purpose first, then grouping semantics, stage list, defaults, interpretation caveat, and targeting last. Every sentence carries operational weight, though the enum-heavy middle sentence is a little packed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 unnecessary, and the description covers the remaining gaps an agent needs: cohort defaults, stage ordering, observation window, and how to read null/zero results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds semantics the schema does not: what happens when both cohort bounds are omitted, which field cohorts group on per program type, and the campaignId/GROWSURF_CAMPAIGN_ID fallback.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Fetch strict activation ... in one enrollment cohort') and scopes it tightly enough to separate it from the broader get_campaign_analytics and get_participant_analytics siblings. It never names an alternative tool explicitly, so it stops short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete usage guidance: omit both cohort bounds for the latest fully matured cohort, each participant gets the chosen 7- or 30-day window, and read coverageStartAt/state/reason before interpreting nulls. It lacks explicit when-to-use-this-instead-of-X routing against sibling analytics tools.
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 AnalyticsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| endDate | No | End of the timeframe, positive Unix timestamp in milliseconds. Supply `startDate` too; `endDate` must be >= `startDate` and at most 1825 days later. | |
| include | No | Comma-separated optional data: `previousPeriod`, `statusCounts`, `rates`, `email`, and `engagement`. Combine values when the question needs more than one view. | |
| interval | No | day/week/month adds a per-period `series`; total (default) returns totals only. | |
| platform | No | Client-platform filter for engagement. Defaults to `ALL`. | |
| timezone | No | IANA timezone for engagement interval and distinct-day calculations. Used with `include=engagement`. | |
| startDate | No | Start of the timeframe, positive Unix timestamp in milliseconds. Supply `endDate` too; the window must span at most 1825 days. | |
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| No | Sent, delivered, opened, clicked, bounced, and spam complaint metrics for program emails in the requested window. | |
| rates | No | Derived referral rates, each a ratio from 0 to 1. Present only when `include` contains `rates`. |
| series | No | Per-period totals in ascending order. Present only when `interval` is `day`, `week`, or `month`. |
| endDate | No | End of the analytics timeframe, as a Unix timestamp in milliseconds. |
| analytics | No | Analytics 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`. |
| startDate | No | Start of the analytics timeframe, as a Unix timestamp in milliseconds. |
| engagement | No | Opt-in participant engagement grouped by when activity occurred. |
| statusCounts | No | Status-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`. |
| previousPeriod | No | Totals for the equal-length window immediately before the requested one (`analytics`, `startDate`, `endDate`). Present only when `include` contains `previousPeriod`. |
TDQS
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 behavioral context the annotations cannot: engagement coverageStartAt/state/reason distinguish measured zeroes from partial or unavailable history, and it discloses defaults and limits (days default 365, max 1825, timezone/platform scoped to engagement only).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A dense but well-ordered paragraph: scope first, then interval, then include values, then timeframe constraints, then targeting. Nearly every sentence carries information, though the date/timestamp constraint is restated in both the prose and the schema, adding a little redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 covers defaults, limits, enum usage, engagement-only parameters, and campaignId fallback to GROWSURF_CAMPAIGN_ID. Nothing an agent needs to invoke this 8-parameter tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is high (88%), so the baseline is 3, but the description adds cross-parameter semantics the schema does not: timezone and platform apply only to engagement, engagement requires include=engagement, and the startDate/endDate pairing constraints (both positive ms timestamps, endDate >= startDate, 1825-day span) are spelled out as a coherent rule set.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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 your GrowSurf program') and enumerates the metric families returned (participants, referrals, impressions, shares, affiliate revenue/commission/payout). An agent can tell it is a program-level analytics read, though it never names the closest sibling (growsurf_get_campaign_activation_analytics) or explains how the two differ.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description teaches *how* to drive the tool (interval for a series, comma-separated include values, days vs. explicit dates, campaignId fallback) but never states when this tool should be chosen over activation analytics or participant analytics. Usage context is implied rather than explicit, so the agent must infer the routing decision.
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 DesignBRead-onlyIdempotentInspect
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, country-name overrides under countryLabels, and the participant Settings panel under participantSettings (its languageSectionTitle and languageSectionInstructionsText label the language picker shown when the program has more than one language). 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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| login | No | The returning-participant sign-in form plus its success, resend, validation, and error text. |
| share | No | Share channels, invite settings, and share-button styling. |
| stats | No | The participant's referral-progress stats panel. Only `title` is editable. |
| theme | No | Visual theme styling (colors, shadows, and similar). |
| header | No | Header content for participants (`postText`) and non-participants (`preText`). |
| signup | No | Signup form fields, GDPR consent, and button and login text. |
| widget | No | 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. |
| window | No | Layout of the GrowSurf window (`navigationMode`: `TABS` or `LIST`). |
| payouts | No | Affiliate programs only. The Payouts section of the participant portal. |
| rewards | No | Heading, icon, and empty-state text of the rewards panel. |
| resources | No | 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. |
| commissions | No | Affiliate programs only. The Commissions section of the participant portal. |
| leaderboard | No | The leaderboard section: labels, selectors, and name masking. |
| landingPages | No | Portal and landing pages: company info, `content`, `styles`, third-party script ids, and SEO meta tags. |
| countryLabels | No | Participant-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. |
| referralStatus | No | The section listing who a participant invited and each invite's progress. `revealInviteEmails` lets a signed-in participant see original invitation addresses when disclosure permission was recorded. Private invites and full email masking keep addresses hidden. Other referral addresses stay masked. `revealInviteEmailText` supplies the sign-in prompt; `loadErrorMessage` is shown when the list cannot load; `followUp` supplies the invitation follow-up labels and messages. |
| referralSummary | No | Referral programs only. The participant's row of summary tiles (clicks, leads, referrals, rewards). |
| trafficInsights | No | 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. |
| affiliateSummary | No | Affiliate programs only. The affiliate's row of summary tiles (clicks, revenue, payouts). |
| referredExperience | No | 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. |
| participantSettings | No | The participant's account settings area (logout, language picker, PayPal and Wise payout confirmation/status messages, tax details). `languageSectionTitle` and `languageSectionInstructionsText` (up to 500 characters each) are the title and help text of the language row, shown when the program has more than one language. `taxSection.instructionsText` and `taxSection.residencyLabel` show when tax forms are required; `taxSection.vatOnlyInstructionsText` and `taxSection.vatOnlyResidencyLabel` show instead when an affiliate program collects VAT numbers without requiring tax forms. |
| participantAvatarStyle | No | How participant avatars appear in the GrowSurf Window. New programs use `CHARACTERS`; missing or unknown stored values return `INITIALS`. |
| payoutDestinationConfirmation | No | Customizable 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
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/closed-world, but the description adds real behavioral detail: unknown or missing `participantAvatarStyle` resolves to `INITIALS`, the confirmation section is omitted when no confirmation fields are stored, stored `null` is returned as `null` while omitted values use localized defaults, and `trafficInsights` defaults differ by program type. These fallback/omission semantics are useful, though they describe the payload rather than the call itself.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first clause, but the body is a single run-on sentence of roughly 180 words enumerating every returned design field group — content an existing output schema already carries. With an output schema present, this enumeration is largely redundant padding that buries the few genuinely useful sentences about defaults and omission.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool with rich annotations and an output schema, the definition covers purpose, targeting, and fallback semantics adequately; return values need not be explained given the output schema. The remaining gap is the absence of any routing guidance relative to the many sibling read tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single parameter with 100% schema description coverage, so the schema already documents `campaignId`. The description's 'Targets `campaignId` if you pass it, otherwise GROWSURF_CAMPAIGN_ID' essentially restates the schema rather than adding format, constraint, or resolution detail beyond it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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', then enumerates the design areas involved (window content, colors, sharing, avatars, widget, traffic insights, login, payout confirmation). It does not, however, differentiate itself from the closest read siblings such as growsurf_get_campaign, growsurf_get_campaign_options, or growsurf_get_campaign_installation, so an agent must infer the boundary from naming alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description is entirely about what is returned and how defaults resolve; it never states when to call this versus alternatives (e.g., use get_campaign for general settings, update_campaign_design to change design). There is no exclusion or prerequisite guidance, leaving the agent to infer that this is the read counterpart of growsurf_update_campaign_design.
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 EmailsARead-onlyIdempotentInspect
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. Sender fields can be null before configuration. When updating, omit unchanged sender fields; fromName and replyToEmail cannot be cleared with null. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| invite | No | The invitation email a participant sends to friends. `useCompanyReplyTo` sets who receives replies. |
| settings | No | Sender (`sender`), physical contact address (`contact`), and shared design (`design`) settings. The design object includes `unsubscribeAffiliateInvite` for direct affiliate invitation emails. Its read-only `layoutMode` is `INLINE` for new programs: bodies require `{{emailFooter}}` and may include `{{emailHeader}}`. Older programs omit `layoutMode` and keep their existing layout. |
| loginLink | No | One-time sign-in link for returning participants. Transactional; its toggle cannot be changed. |
| goalAchieved | No | Sent when a participant unlocks a reward. Referral programs only. |
| offerClaimed | No | Sent when a referred visitor saves an offer through the Claim Offer Popup. Referral and affiliate programs. Promotional; its toggle can be changed. |
| payoutPending | No | Sent when a payout is on the way. Affiliate programs only. |
| referredSignup | No | Sent to a referrer each time someone signs up using their link. Referral and affiliate programs. |
| taxInfoMissing | No | Asks a participant to submit required tax information. Transactional; its toggle cannot be changed. |
| inviteAffiliate | No | Invites a prospective affiliate to join the program. Its body must keep `{{affiliateInviteLink}}`. Affiliate programs only. Promotional; its toggle can be changed. |
| taxInfoApproved | No | Tells a participant their tax form is complete and approved. Transactional; its toggle cannot be changed. |
| taxInfoReceived | No | Confirms submitted tax information was received. Transactional; its toggle cannot be changed. |
| taxInfoRejected | No | Tells a participant their tax information needs to be resubmitted. Transactional; its toggle cannot be changed. |
| welcomeReferred | No | Welcome email for someone who signs up through a referral link. Referral programs only. |
| followUpReminder | No | Optional reminder to the referrer about directly invited contacts who have not signed up after `delayDays` (integer 2–30, default 3). Existing reminder dates stay unchanged. Disabled by default. Only new invitations created while this email is enabled qualify automatically. A later offer claim preserves invitation eligibility; popup-only claims never qualify. Each contact is included once. Referral and affiliate programs. |
| referralLinkUsed | No | Sent to a referrer when they earn referral credit. Referral programs only. |
| payoutSentSuccess | No | Sent when a payout completes. Affiliate programs only. |
| commissionAdjusted | No | Sent when a commission is adjusted after a refund or chargeback. Affiliate programs only. |
| welcomeNonReferred | No | Welcome email for a participant who joins without being referred. Referral and affiliate programs. |
| commissionGenerated | No | Sent to an affiliate when they earn a new commission. Affiliate programs only. |
| campaignEndedWinners | No | Sent to reward winners when the program ends. Referral programs only. |
| progressUpdateMonthly | No | Month-end progress recap for participants. Referral and affiliate programs. |
| campaignEndedNonWinners | No | Sent to non-winners when the program ends. Referral programs only. |
| payoutDestinationChanged | No | Tells a participant their payout destination changed. Its body must keep `{{payoutDestinationMaskedEmail}}`. Referral and affiliate programs. Transactional; its toggle cannot be changed. |
| affiliateApplicationDenied | No | Tells an applicant their affiliate application was not approved. Affiliate programs only. Transactional; its toggle cannot be changed. |
| referralLinkViewedFirstTime | No | Sent the first time a participant's referral link is viewed. Referral and affiliate programs. |
| affiliateApplicationApproved | No | Tells an applicant their affiliate application was approved. Affiliate programs only. Transactional; its toggle cannot be changed. |
| affiliateApplicationReceived | No | Confirms an affiliate application was received and is under review. Affiliate programs only. Transactional; its toggle cannot be changed. |
| payoutDestinationConfirmation | No | Asks 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. |
| affiliateApplicationStatusLink | No | Sends an applicant a secure link to view their application status. Its body must keep `{{applicationStatusLink}}`. Affiliate programs only. Transactional; its toggle cannot be changed. |
| affiliateEmailChangeVerification | No | Asks an affiliate to confirm a new account email address. Its body must contain `{{identityVerificationLink}}`. Affiliate programs only. Transactional; its toggle cannot be changed. |
| affiliateApplicationEmailCorrection | No | Asks an applicant to confirm a corrected email address. Its body must contain `{{identityVerificationLink}}`. Affiliate programs only. Transactional; its toggle cannot be changed. |
TDQS
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 genuinely useful behavioral context beyond that: sender.fromEmail is read-only and only changeable in the dashboard after domain verification, sender fields may be null before configuration, and fromName/replyToEmail cannot be nulled out. Some of this is oriented toward the update flow rather than describing this read call's own behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose in the first clause, followed by compact technical details. Four sentences mostly earn their place, though the update-oriented caveats sit oddly in a getter's description and slightly dilute the focus.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists and annotations cover the read-only/idempotent profile, so return-value and safety disclosure are not needed here. The description supplies the extra semantics an agent needs (null handling, read-only fields, target defaulting), leaving only minor gaps around when to prefer this tool over its siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With a single parameter at 100% schema description coverage, the schema already documents campaignId, its minLength, and the GROWSURF_CAMPAIGN_ID default. The description restates the same targeting/default behavior without adding format or edge-case detail, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Fetch the Emails tab configuration for your GrowSurf program") and enumerates what is included (participant/admin templates, settings, read-only fields), which distinguishes it from siblings like growsurf_get_campaign_design or growsurf_get_campaign_options. It never explicitly names the update sibling, so the get-vs-update boundary is only implied.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description spends its guidance on update semantics ("When updating, omit unchanged sender fields") rather than stating when an agent should call this read tool versus alternatives. The campaignId fallback to GROWSURF_CAMPAIGN_ID is stated, but there is no explicit trigger condition or exclusion relative to growsurf_get_campaign.
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 InstallationARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| mobile | No | GrowSurf iOS and Android SDK settings. |
| signup | No | Custom signup-form settings (used with `FORM_DETECTION`). |
| shareUrl | No | The landing page referred friends reach from a referral link. Set this before adding other origins to `allowedUrls`. |
| allowedUrls | No | 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. |
| signupEvent | No | The signup tracking method: automatic form detection, or participants added via the SDKs and REST API. |
| referralTrigger | No | Referral programs only. `ON_SIGNUP` counts a referral as soon as the friend signs up; `CUSTOM` also requires a qualifying action. |
| instructionSelections | No | Saved choices shown in the Program Editor installation guide. |
| useGrowSurfHostedLinks | No | Use GrowSurf-hosted referral links that route clicks by the visitor's device. Mainly for mobile apps. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive, so safety is covered. The description adds genuine value beyond that: it discloses the return payload is the complete object with every field's current value and that it round-trips with the update call, plus the campaign-ID fallback. Minor gaps only (no note on whether a missing program errors).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences, front-loaded with the resource, then the return contract, then the targeting rule. No filler, though the parenthetical scope gloss and trailing default could be trimmed slightly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 doesn't need to enumerate return fields, yet the round-trip note is useful orientation. Combined with the annotation-covered safety profile and the fully specified parameter, an agent has enough to call this correctly; only the error/edge behavior for an unresolvable program is unmentioned.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single parameter is fully documented in the schema, including the GROWSURF_CAMPAIGN_ID default, so the description's restatement 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.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Fetch) and a specific resource (the Installation tab configuration: embed/installation and tracking setup) scoped to a GrowSurf program. This clearly separates it from sibling readers like get_campaign_design, get_campaign_emails, and get_campaign_options without needing to open schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives the target-selection rule ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID') and implicitly positions the tool as the read counterpart to update_campaign_installation via 'the same shape you send back on update'. It lacks an explicit statement of when to prefer it over adjacent readers, 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_get_campaign_optionsGet Program OptionsARead-onlyIdempotentInspect
Fetch the Options tab configuration for your GrowSurf program (referral triggers, anti-fraud lists and toggles, affiliate enrollment and application review, notifications, the program's languages under languages, 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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| fraud | No | Anti-fraud settings: `blockedEmails`/`blockedIps`/`blockedCountries` and matching allow lists, `blockBurnerEmails`, `blockDataCenterIps`, `blockHighRiskReferrers`, `autoBlockHighRiskIps`, per-IP signup rate limits, and `recaptcha`. |
| languages | No | The languages the program runs in. Participants see the portal and program emails in their language. Turning on additional languages, and any change while they are on, requires the Business plan or higher. Translations are managed in the dashboard. |
| autoBlockFraud | No | Automatically block signups flagged as high fraud risk. |
| rewardEvidence | No | What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere. |
| payoutThreshold | No | Affiliate programs only. Minimum payout in minor currency units (e.g. cents). `0` or `null` means no minimum. |
| taxDocumentation | No | Affiliate programs only. Company billing details (name, address, VAT number) used on affiliate payout invoices and for VAT handling. |
| autoFulfillRewards | No | Referral programs only. Automatically mark earned rewards as fulfilled. `false` permits manual fulfillment and does not establish a delivery failure. |
| notificationEmails | No | Owner notification settings: `recipients` plus per-event `events` toggles. |
| blockPaidAdsTraffic | No | Do not attribute referrals from visitors who arrived through paid ads. |
| enforceGdprCompliance | No | Store only the minimum participant data (no IP addresses, fingerprints, or mobile instance ids). |
| requireParticipantAuth | No | Require returning participants to authenticate. Affiliate programs require `true`. |
| affiliateApplicationMode | No | Affiliate 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. |
| referralCookieWindowDays | No | How long a referral-link click is remembered in the visitor's browser, in days. |
| referralCreditWindowDays | No | How long a referred friend has to complete the qualifying action, in days. `null` means the credit never expires. |
| requireManualFraudApproval | No | Flag suspected fraud for review instead of blocking signups automatically. |
| requireManualRewardApproval | No | Referral programs only. Hold each earned reward for manual approval before it unlocks. |
| affiliateReapplicationPolicy | No | Affiliate 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. |
| affiliateReapplicationCooldownDays | No | Affiliate 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`. |
| affiliateApplicationReviewEstimateBusinessDays | No | Affiliate programs only. Optional review-time expectation shown to pending applicants, in business days (1-60). `null` clears it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly/idempotent/non-destructive, so the bar is lower, and the description adds real value beyond them: it promises the full object with every field and current value, states it round-trips with the update call, and pre-empts a likely misinterpretation of autoFulfillRewards:false. It does not cover auth/permission needs 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose, then the return shape, then the caveat and the targeting rule. Every clause carries information an agent needs; the parenthetical enumeration is dense but earns its space by naming the configurable sub-areas.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 describe return values, yet it helpfully states the shape is write-back compatible. Target selection and default are covered. Only minor gaps remain (auth requirements, whether a program must already exist), and none would block a correct call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single campaignId parameter is fully documented in the schema, including the GROWSURF_CAMPAIGN_ID default. The description restates the same targeting rule ('Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID') without adding syntax or format detail, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb ('Fetch') plus specific resource ('Options tab configuration for your GrowSurf program'), and it enumerates the sub-areas the Options tab covers (triggers, anti-fraud, affiliate enrollment, notifications, languages). This distinguishes it clearly from siblings like growsurf_get_campaign and growsurf_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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: 'the same shape you send back on update' anchors it as the read-side partner of growsurf_update_campaign_options, and the autoFulfillRewards note warns against a wrong inference. But there is no explicit when-to-use/when-not guidance or named alternative for cases where a different getter is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_integration_connect_linkGet Integration Connect LinkARead-onlyIdempotentInspect
Return a dashboard link to an integration's connect panel in the GrowSurf Program Editor (Options > Integrations). Connecting Stripe, PayPal, Wise, or another account requires the user to complete the dashboard flow; the API cannot connect an account on their behalf. integration accepts supported keys, including camelCase keys such as constantContact and helpScout. The result reports whether the integration is connected, enabled, or autoDisabled. If the program check cannot run, programVerified is false and the result still includes a production dashboard link. Tango Card, Tremendous, and Bask Health apply only to referral programs. Wise applies only to affiliate programs. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | No | Target program for the link. Defaults to GROWSURF_CAMPAIGN_ID. | |
| integration | Yes | The integration to connect. Must exactly match one of the supported keys (for example `wisecom`; some are camelCase, e.g. `constantContact`, `campaignMonitor`, `helpScout`, `pabblyConnect`, `baskHealth`). |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | Dashboard link that opens the integration's connect panel. |
| note | No | Instructions to relay to the user. |
| label | No | Human-readable integration name. |
| enabled | No | Whether the integration is switched on and currently working. Present only when `programVerified` is `true`. |
| category | No | The integration's category. |
| connected | No | Whether the program has stored credentials for this integration. Present only when `programVerified` is `true`. |
| integration | No | The integration key that was requested. |
| autoDisabled | No | Whether GrowSurf switched the integration off after repeated delivery failures. Present only when `programVerified` is `true`. |
| referralOnly | No | `true` when the integration applies to referral programs only. |
| affiliateOnly | No | `true` when the integration applies to affiliate programs only. |
| programVerified | No | `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`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only/idempotent safety, yet the description adds substantial behavioral detail: the dashboard-completion requirement, the connected/enabled/autoDisabled result fields, the programVerified=false fallback that still returns a production link, and program-type applicability rules. This is rich context beyond structured data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense prose that front-loads the purpose and the API-cannot-connect caveat. Every sentence carries useful information, though the program-type and result-field details are somewhat packed together rather than scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter read tool this is fully covered: connection semantics, edge cases (programVerified false), result flags, and program-type caveats are all addressed, and an output schema exists so return structure need not be re-explained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema coverage the baseline is 3, but the description adds genuine meaning beyond the schema: camelCase key examples, the program-type restrictions (Tango Card, Tremendous, Bask Health referral-only; Wise affiliate-only), and the campaignId fallback behavior. It does not add syntax or validation detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: return a dashboard link to an integration's connect panel in the GrowSurf Program Editor. It also clarifies the critical constraint that the API cannot connect accounts itself, distinguishing this tool from connect/action tools and from growsurf_list_integrations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context for use: the user must complete the dashboard flow, so this tool is the hand-off point. However, it does not explicitly name sibling alternatives (e.g. growsurf_list_integrations or growsurf_integration_guide) or state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_participantGet ParticipantARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. | |
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | The participant's unique id. |
| rank | No | All-time leaderboard rank. |
| No | The participant's email address. | |
| isNew | No | `true` when the request created the participant. Returned by participant creation calls. |
| notes | No | Internal notes. Never shown to participants. |
| rewards | No | Rewards the participant has earned. |
| isWinner | No | `true` once the participant has earned at least one reward. |
| language | No | The language code of the participant's portal and program emails, such as `es`. The program's base language unless the participant (or you) picked another of the program's languages. |
| lastName | No | The participant's last name. |
| metadata | No | Custom key/value metadata (single level). |
| referrer | No | Summary of the participant's referrer (same core fields as a participant). Present only when the participant was referred. |
| shareUrl | No | The participant's unique referral link. Omitted for affiliate program participants who are not approved affiliates. |
| createdAt | No | When the participant joined, as a Unix timestamp in milliseconds. |
| firstName | No | The participant's first name. |
| ipAddress | No | IP address recorded for the participant, or `null`. |
| leadCount | No | Pending referrals that have not converted yet. |
| referrals | No | Ids of participants they successfully referred (100 most recent). |
| referredBy | No | Id of the referrer. Present only when the participant was referred. |
| shareCount | No | Share counts keyed by channel (e.g. `email`, `facebook`, `twitter`, `copyRefLink`, `iosNativeShare`). |
| vanityKeys | No | The participant's vanity keys. |
| fingerprint | No | Browser identifier recorded for the participant, or `null`. |
| inviteCount | No | Invites sent by the participant. |
| isAffiliate | No | Affiliate programs only. Whether this participant is an enrolled affiliate. A referred customer who has not joined the program is `false`. |
| monthlyRank | No | Current-month leaderboard rank (resets monthly). |
| unsubscribed | No | `true` if the participant unsubscribed from program emails. |
| referralCount | No | All-time referrals credited to the participant. |
| fraudRiskLevel | No | The participant's fraud risk level. |
| payoutSettings | No | Actions the participant must complete before a payout can be released. Always present. |
| referralSource | No | How the participant joined the program. |
| referralStatus | No | The referrer's credit status for this participant. Present only when the participant was referred. |
| rewardEvidence | No | What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere. |
| affiliateStatus | No | Affiliate programs only. The enrolled affiliate's status (`APPROVED`, `SUSPENDED`, or `BANNED`). `null` for participants who are not affiliates. |
| fraudReasonCode | No | Reason code behind `fraudRiskLevel` (e.g. `UNIQUE_IDENTITY`, `DUPLICATE_EMAIL`, `MANUAL_UPDATE`). |
| impressionCount | No | Total views of the participant's referral link. |
| prevMonthlyRank | No | Previous-month leaderboard rank. |
| mobileInstanceId | No | App-install scoped identifier supplied by a native app, or `null`. |
| monthlyReferrals | No | Ids of participants they successfully referred this month (100 most recent). |
| paypalEmailAddress | No | PayPal email address on file, used for affiliate or PayPal reward payouts. |
| unreadPayoutsCount | No | Payouts the participant has not yet viewed. Affiliate programs only. |
| monthlyReferralCount | No | Referrals credited this month (resets monthly). |
| allMatchingFraudsters | No | Other participants flagged as matching this participant during anti-fraud checks. |
| uniqueImpressionCount | No | Unique views of the participant's referral link. |
| unreadCommissionsCount | No | Commissions the participant has not yet viewed. Affiliate programs only. |
| prevMonthlyReferralCount | No | Referrals credited the previous month. |
| affiliateEnrollmentSource | No | Affiliate programs only. How the affiliate enrolled (`OPEN_ENROLLMENT`, `APPLICATION`, `PARTICIPANT_AUTH`, `INVITE`, `REST_API`, `CSV`, or `DASHBOARD`). `null` when not recorded. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/non-destructive, so the bar is lower, and the description adds genuine value beyond them: the campaignId fallback to GROWSURF_CAMPAIGN_ID, and non-obvious field interpretation ('zero referralCount is consistent with CREDIT_AWARDED', fulfillment flags are not delivery confirmation). It still omits auth/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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and lookup keys are front-loaded, and the dense backtick-heavy clauses about referralStatus, referralCount, and rewards each carry distinct semantic meaning. It is compact for the amount of interpretation it conveys, though the field-semantics run-on could be trimmed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 goes further and disambiguates the trickiest output fields. Purpose, lookup keys, and campaign targeting are all covered; only permissions and rate/auth context are absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 33%, so participantId and participantEmail have no schema descriptions. The description partially compensates by establishing that either identifier is accepted and that campaignId falls back to an env default, but adds no format hints for the email/ID and does not restate the anyOf alternation beyond 'ID or email'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Fetch a single participant') plus the two lookup keys, which implicitly separates it from list_participants. It never names a sibling explicitly, so the differentiation is inferred rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description establishes lookup context ('by participant ID or email address') and targeting rules, but never says when to reach for this tool versus list_participants or get_participant_analytics, nor any exclusions or prerequisites.
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 LogsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No | ||
| campaignId | Yes | 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. | |
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| limit | No | Number of activity logs returned per page. |
| offset | No | Offset for the next page, or `null` when there are no more logs. |
| activityLogs | No | Activity log entries for the participant. |
TDQS
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 useful behavioral context: sort order (most recent first), pagination mechanics, and that the response offset is the next-page cursor (null at end). However, it doesn't cover auth requirements 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences, appropriately front-loaded with the core action and lookup keys, then pagination details, then campaign targeting. Every sentence carries useful information, though the pagination and targeting could be marginally tighter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a paginated read tool with an output schema and full annotation coverage, the description suffices: it explains ordering, pagination cursor semantics, lookup keys, and campaign targeting defaults. It needn't detail return values since an output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 20% (only campaignId is documented), so the description must compensate. It does: it explains limit range (1-100, default 20), offset semantics (skips logs), and the campaignId fallback to GROWSURF_CAMPAIGN_ID. It adds real meaning beyond the bare schema types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: 'List a participant's activity logs' with the lookup key (participant ID or email) and ordering. This clearly distinguishes it from siblings like growsurf_get_participant or growsurf_get_participant_analytics, which return different data about the same entity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage through the ID-or-email lookup and campaign targeting, but it never states when to use this tool versus gets like get_participant or get_participant_analytics. It provides context but no explicit exclusions or alternatives.
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 AnalyticsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | Number of days for optional `series` and `email` analytics. Does not filter the all-time base response. | |
| endDate | No | End of the optional-data timeframe, positive Unix timestamp in milliseconds. Supply `startDate` too; `endDate` must be >= `startDate` and at most 1825 days later. | |
| include | No | Comma-separated optional data. Current values are `series`, `email`, and `activation`; the API returns `400` for unknown values. | |
| interval | No | Bucket size for `series` and email series. Defaults to `day`. | |
| startDate | No | Start of the optional-data timeframe, positive Unix timestamp in milliseconds. Supply `endDate` too; the window must span at most 1825 days. | |
| campaignId | Yes | 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. | |
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| No | Sent, delivered, opened, clicked, bounced, and spam complaint metrics for program emails in the requested window. | |
| ranks | No | Leaderboard ranks for this participant. |
| series | No | This participant's per-period activity. Present when `include` contains `series`. |
| endDate | No | Window end (Unix ms). Present with `series` or `email`. |
| analytics | No | All-time participant analytics totals. Date-window parameters do not filter these fields. |
| startDate | No | Window start (Unix ms). Present with `series` or `email`. |
| activation | No | Opt-in covered eligibility and first-milestone analytics for one participant. |
| shareCount | No | Per-channel share counts (e.g. `email`, `facebook`, `twitter`). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare a safe read (readOnly, idempotent, non-destructive, closed-world), yet the description adds substantial behavior: what the base response contains, what `activation` unlocks, the 1825-day cap, and the crucial null-milestone interpretation rule. It also warns that date params do not filter the base response or milestones.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core purpose and then layers optional behavior; nearly every sentence carries non-obvious rules. It is dense and slightly long, but no sentence is pure filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite 8 parameters and conditional (anyOf/allOf) schema constraints, the description covers the base vs optional response split, include semantics, date-window rules, and the null-milestone caveat. With an output schema present, no return-format explanation is needed, so nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, so the schema already documents most parameters. The description still adds integration-level meaning: that date params do not filter the base response, that `endDate` must be >= `startDate` within 1825 days, and the campaignId targeting fallback to GROWSURF_CAMPAIGN_ID.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Fetch) and resource (analytics for one participant) plus the two identification keys (participant ID or email). The 'one participant' scoping cleanly distinguishes it from the campaign-level siblings like get_campaign_analytics and 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit conditional guidance: add `activation` for eligibility/milestones, request both `activation` and `series` for covered buckets, and how to bound ranges with `days` or `startDate`/`endDate`. It lacks explicit routing against adjacent siblings (get_participant, get_participant_activity_logs), 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_get_participant_payout_destinationGet Payout DestinationARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. | |
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| destinations | No | One entry per enabled payout provider describing the participant's destination for it. |
| activeProvider | No | The payout provider currently selected, or `null` until the participant confirms one. Provider identifiers are open-ended; current examples include `PAYPAL`, `VENMO`, and `WISECOM`. |
| enabledProviders | No | Payout provider identifiers enabled for this program. Values are open-ended; current examples include `PAYPAL`, `VENMO`, and `WISECOM`. |
TDQS
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 structurally. The description adds genuine behavioral context beyond that: per-provider status fields, the meaning of `activeProvider` (the provider that currently gets paid, or null until the participant confirms one), and the appearance of a repair reason when a delivery bounced or a recipient was invalidated. That is real semantics 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core capability and the provider enumeration, then moves to return semantics, then the campaignId fallback, in a sensible order. It is somewhat dense with em-dashes and backticked field names, but 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.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the description need not enumerate return values, yet it still summarizes the important ones (status, confirmed email, recipient type, repair reason, activeProvider), which is helpful for selecting the tool. Combined with the identifier and campaignId fallback notes, the definition covers what an agent needs to invoke it correctly; a minor gap is the absence of guidance on combining participantId and participantEmail.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 33% — participantId and participantEmail have no schema descriptions at all. The description compensates by explaining that lookup is 'by GrowSurf participant ID or email' and that campaignId is optional and falls back to GROWSURF_CAMPAIGN_ID, which clarifies the anyOf/required structure the schema encodes only mechanically. It does not, however, add format examples or say what happens if both identifiers are supplied.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ('Get a participant's payout-destination status') and scopes it across every enabled payout provider (PayPal and/or Wise), which clearly separates it from the write-side sibling growsurf_request_participant_payout_destination_confirmation. It also enumerates the fields returned, so an agent knows exactly what question this tool answers.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied — you call it to inspect payout-destination state — and the description does tell the agent it can look up by either participant ID or email, which is a routing hint. However, it never explicitly says when to use this versus the sibling confirmation-request tool, nor when the lookup is not appropriate. Implied rather than stated guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_get_teamGet TeamARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | The team's display name. |
| verificationStatus | No | Team verification state. `VERIFIED` is required before a program can send participant emails. |
| verificationRequestedAt | No | When verification was last requested, as a Unix timestamp in milliseconds. |
TDQS
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.
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.
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.
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.
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.
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 CodeBRead-onlyIdempotentInspect
Generate the HTML code for GrowSurf Participant Auto Authentication using window.grsfConfig. The generated code belongs in <head>, before the GrowSurf Universal Code.
| Name | Required | Description | Default |
|---|---|---|---|
| hash | No | ||
| No | |||
| campaignId | No | ||
| affiliateJoin | No | ||
| useCampaignIdPlaceholder | No | ||
| enableParticipantAutoAuth | No | ||
| includeAutoAuthCommentHeader | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
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.
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.
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.
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.
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.
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_guidePlan Program IntegrationARead-onlyIdempotentInspect
Plan a web integration for a referral or affiliate program. Returns Markdown steps for installing the Universal Code, identifying participants, tracking referrals or sales, and verifying webhooks. Does not inspect or change a program. Use growsurf_client_snippets for browser JavaScript examples, growsurf_api_library_snippets for backend code, or growsurf_mobile_sdk_guide for native or React Native apps.
| Name | Required | Description | Default |
|---|---|---|---|
| programType | No | both | |
| singlePageApp | No | ||
| referralTrigger | No | signup_plus_qualifying_action | |
| webhookSecurity | No | Always recommends signature verification. Legacy values are accepted for compatibility and cannot disable verification. | signature |
| participantAuthEnabled | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, and closed-world, so the safety burden is largely carried. The description adds the meaningful clarification that this is a planning/advisory tool producing Markdown rather than performing inspection or mutation, which sharpens the agent's mental model beyond the flags.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tightly written sentences with zero filler; purpose and output are front-loaded, the negative scope comes second, and the sibling routing closes it out. Nothing repeats.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Safety is covered by annotations and return shape by the output schema, so those needn't be in prose. The remaining gap is the five parameters, four of which are undocumented in both schema and description — adequate overall but not fully complete for a tool with this many inputs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 20% (just webhookSecurity), and the description says nothing about the five inputs — programType, singlePageApp, referralTrigger, participantAuthEnabled are left entirely to bare enum names and defaults. The description does not compensate for the coverage gap, so an agent gets little help interpreting or selecting these parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Plan a web integration for a referral or affiliate program') and goes on to name the concrete outputs (Markdown steps for Universal Code, participant identification, referral/sale tracking, webhook verification). It also explicitly scopes what the tool is not ('Does not inspect or change a program'), letting an agent separate it from the many mutating siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent to alternatives by condition: `growsurf_client_snippets` for browser JavaScript, `growsurf_api_library_snippets` for backend code, `growsurf_mobile_sdk_guide` for native/React Native. This is exactly the when-to-use-a-sibling guidance most definitions omit.
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 RewardsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| rewards | No | The program's configured Campaign Rewards, including switched-off rewards. Deleted rewards are excluded. |
| rewardEvidence | No | What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive. Description adds valuable semantics beyond that: deleted rewards excluded, switched-off/ungrouped included, and the subtle point that config presence does not mean a reward was earned. This is meaningful context for 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads scope, then qualifications about inclusion/exclusion and the config-vs-earned distinction. A bit dense with semicolons but every clause adds signal.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return values needn't be described. The description covers scoping, defaults, exclusions, and the important semantic caveat about earned vs configured rewards. Nothing an agent needs is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3 arguable. The description adds the fallback behavior (GROWSURF_CAMPAIGN_ID when campaignId not supplied), which reinforces the schema and clarifies precedence ordering for the single param.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (Campaign Rewards) with precise scope: includes switched-off rewards and rewards whose group is not selected, excludes deleted ones. Distinguishable from gets/updates and from participant earned-reward records.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clearly frames what the tool returns and clarifies the crucial distinction that earned reward records belong to the participant, implying this tool is for configuration listing. It doesn't explicitly name sibling alternatives like get_participant, but the boundary is clear from context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_list_campaignsList ProgramsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| campaigns | No | Programs available to the API key's bound team. |
TDQS
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.
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.
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.
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.
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.
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 WebhooksARead-onlyIdempotentInspect
List your GrowSurf program's webhooks (secrets are never returned). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| webhooks | No | Webhooks configured for the program. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint=true, idempotentHint=true and destructiveHint=false, so safety is covered. The description adds a genuinely useful behavioral detail beyond that: secrets are never returned, which tells the agent the output is sanitized. It stops short of noting pagination or result limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the action and scope, with no filler. The second sentence duplicates what the schema already says about campaignId fallback, so it is slightly redundant, but the cost is small.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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, and annotations carry the safety profile. Combined with the secret-redaction note and targeting rule, an agent has what it needs to call this correctly; only pagination/result-size behavior is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 is fully documented in the schema, including the GROWSURF_CAMPAIGN_ID fallback. The description's 'Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID' largely restates that schema text rather than adding new meaning, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (webhooks) scoped to a GrowSurf program, which cleanly separates it from the create/update/delete/test webhook siblings. The parenthetical about secrets not being returned further sharpens what the tool actually returns.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the verb and the sibling set — an agent can infer this is the read path versus growsurf_create_campaign_webhook or growsurf_delete_campaign_webhook — but the description never says when to prefer it or names any alternative. The only explicit conditional is about which campaign is targeted, not about when to call the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_list_integrationsList IntegrationsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| integrations | No | Every integration this program can connect, in the order the GrowSurf dashboard lists them. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the read-only/idempotent/non-destructive profile, yet the description goes further: it defines each returned field's meaning, including the notable autoDisabled failure behavior, explains omission semantics for inapplicable integrations, and clarifies that connection is dashboard-only. This is genuinely additive 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads purpose and integration names, then layers field semantics, omission rules, API limitation, and targeting. Every sentence carries information, though the field-by-field enumeration partly overlaps the existing output schema, adding slight redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 documentation is not required, and annotations cover the safety profile. The description fills the remaining gaps: what the fields mean, what gets omitted, and how the campaignId is resolved — leaving nothing an agent needs to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 schema already carries the semantics. The description restates the targeting rule (campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID) without adding new syntax or format detail beyond what the schema provides, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the integrations available to your GrowSurf program') and enumerates the concrete integration set (Stripe, PayPal, Wise, Mailchimp, Slack, Zapier, Webhooks). It is clearly distinguishable from siblings like growsurf_integration_guide and growsurf_get_integration_connect_link.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives strong context on what the tool can and cannot do, noting that account connection happens in the dashboard and is not available through the API, and that inapplicable integrations are omitted. It stops short of explicitly naming an alternative sibling (e.g. get_integration_connect_link) for connection flows, so routing is implied rather than spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_list_participantsList ParticipantsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| nextId | No | Participant ID returned as `nextId` from the previous page. | |
| metadata | No | Exact-match filter on participant metadata, up to 3 keys, for example `{ "customerId": "12345" }`. Values compare as strings. | |
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| limit | No | Maximum number of participants requested for this page. |
| nextId | No | Participant id to pass as `nextId` for the next page, or `null` when there are no more results. |
| participants | No | Participants returned for this page. |
| rewardEvidence | No | What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only/idempotent safety, and the description adds real behavioral context: newest-page-first ordering, that filtered results are ordered by participant ID, the paging handshake via nextId, and results carrying participant IDs. That is meaningful beyond the safety flags, though it omits rate limits or result-size expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense paragraph with purpose front-loaded and paging guidance immediately after. A couple of clauses (e.g. the campaignId default) restate the schema verbatim, which is mildly redundant but not wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return-shape explanation is unnecessary, and the description still flags that results include participant IDs for the paging loop. Defaults, filtering semantics, ordering, and the pagination contract are all covered for a 4-param nested-object tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, so the baseline is 3; the description lifts this by supplying the limit default of 10, which the schema does not state, and by explaining how nextId, metadata filtering, and the campaignId fallback interact. The exact-match/string-comparison nuance for metadata duplicates the schema text rather than extending it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List participants in your GrowSurf program') and scopes it with ordering and paging details. It reads distinctly from the singular get_participant sibling by implication, but never names or contrasts 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete usage context: pass the returned nextId to continue paging, and use the metadata filter to look someone up by your own customer ID. It stops short of stating when to prefer this tool over siblings like get_participant or bulk_delete_participants.
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 ResourcesARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| resources | No | The program's resources in participant display order, including drafts. |
TDQS
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 genuine behavioral context beyond them: drafts are included in results and ordering follows display order, plus the campaignId vs. GROWSURF_CAMPAIGN_ID resolution. It does not discuss pagination or result size, hence 4 not 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short, front-loaded sentences with no filler; the core purpose leads. Minor duplication of the environment-variable fallback that already appears in the schema description keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return values need not be explained, and annotations carry the safety profile. For a single-parameter read tool, the description supplies everything an agent needs to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single parameter's fallback semantics are already documented in the schema. The description restates the campaignId/GROWSURF_CAMPAIGN_ID behavior without adding format or constraint detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (participant resources configured for your GrowSurf program), and scopes it further with 'including drafts'. An agent can distinguish this from siblings like growsurf_list_campaign_rewards or growsurf_list_campaigns 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: this is the read operation for program resources, contrasted with the create/update/delete siblings. But the description never says when to reach for it versus alternatives, nor any prerequisites (e.g., that a program must already exist / campaignId must resolve).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_mobile_sdk_guideGet Mobile SDK GuideARead-onlyIdempotentInspect
Get Markdown implementation guidance for native iOS/Android SDK 0.9.0 or React Native SDK 0.1.0, including attribution, shareUrl sharing, trackShare, and the native GrowSurf Window. Choose platform and participantState to tailor the guide; includeInstallSnippets controls installation examples. Does not install an SDK or create a participant token. Use growsurf_client_snippets for browser JavaScript or growsurf_api_library_snippets for backend token-creation code.
| Name | Required | Description | Default |
|---|---|---|---|
| platform | No | `both` renders the native iOS and Android SDKs. `react_native` renders the React Native SDK for bare React Native apps and Expo development builds. | both |
| campaignId | No | ||
| mobilePublicKey | No | ||
| participantState | No | both | |
| attributionProvider | No | all | |
| includeInstallSnippets | No | ||
| serverVerifiedQualifyingAction | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
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 the non-obvious behavior that it produces Markdown guidance rather than performing installs or token creation. It does not discuss guide length, caching, or failure modes, so it stops short of 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the deliverable and SDK versions, then parameters, then non-goals and alternatives in a compact three-sentence block with no filler. The first sentence is dense with topic lists, but every clause is load-bearing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-param, output-schema-backed read tool, the description covers scope, tailoring options, and sibling disambiguation, and an output schema means return values need not be described. The main gap is that several non-enum parameters (campaignId, mobilePublicKey, attributionProvider, serverVerifiedQualifyingAction) are left entirely to inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 14%, so the description carries extra burden; it explains the functional effect of platform ('tailor the guide'), participantState, and includeInstallSnippets, which helps. However campaignId, mobilePublicKey, attributionProvider, and serverVerifiedQualifyingAction receive no explanation beyond their enum values, leaving over half the parameters semantically thin.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get Markdown implementation guidance') and enumerates the covered topics (attribution, shareUrl sharing, trackShare, native GrowSurf Window) with exact SDK versions. It also distinguishes itself from siblings by naming growsurf_client_snippets and growsurf_api_library_snippets as the browser/backend alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: use this for mobile/native/React Native, use growsurf_client_snippets for browser JavaScript and growsurf_api_library_snippets for backend token-creation code. It also states a negative boundary ('Does not install an SDK or create a participant token'), which prevents misuse for install or token work.
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 HashARead-onlyIdempotentInspect
Compute a SHA-256 HMAC using the caller-supplied participantAuthSecret. Server environment secrets are never used. Use a test secret during implementation; keep production signing in your backend. affiliateJoin requires permission for this signed-in user to join the affiliate program directly.
| Name | Required | Description | Default |
|---|---|---|---|
| Yes | |||
| affiliateJoin | No | ||
| participantAuthSecret | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| hash | No | The computed hash. Pass it to the GrowSurf client as the participant's `hash` value. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, closed-world behavior, but the description adds security-critical context the annotations cannot convey: server environment secrets are never used, and the signing secret must come from the caller. It also discloses that affiliateJoin carries a permission prerequisite.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences with no filler; the core computation and the secret-source constraint are front-loaded. The affiliateJoin sentence feels slightly bolted on but still carries useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 the secret-handling model and the one side-effect-ish parameter, which is most of what an agent needs; only the 'email' input lacks any explanation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 documentation burden. It explains participantAuthSecret (caller-supplied, test vs. production usage) and affiliateJoin (requires program-join permission), but the required 'email' parameter is never described or exemplified, leaving one of three parameters undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a precise verb and resource ('Compute a SHA-256 HMAC') and immediately scopes it with 'using the caller-supplied participantAuthSecret'. No sibling tool performs hashing, so this is trivially distinguishable from the rest of the toolset.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives concrete guidance on how to use the tool in practice ('Use a test secret during implementation; keep production signing in your backend') and flags a conditional requirement for affiliateJoin. It does not name an alternative tool, but no plausible alternative exists in the sibling list.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| fileName | Yes | A safe base name with an allowed extension: jpg/jpeg/png/gif/webp/pdf/csv/zip/doc/docx/xls/xlsx/ppt/pptx. | |
| mimeType | Yes | The supported MIME type matching fileName's extension. | |
| campaignId | Yes | 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. | |
| fileBase64 | Yes | Canonical padded base64 file bytes only. Do not include a data-URL prefix or whitespace. |
Output Schema
| Name | Required | Description |
|---|---|---|
| uploadResult | No | The minimal signed upload confirmation. Pass it unchanged to create/update. |
| uploadTicket | No | The one-time GrowSurf ticket. Pass it unchanged to create/update. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial behavioral detail beyond annotations: uploads only to a GrowSurf-selected HTTPS destination, rejects upload URLs/credentials, never retries ambiguous uploads, and notes altered results are invalid. It also discloses the server env-var gate and the campaignId fallback to GROWSURF_CAMPAIGN_ID, none of which 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core purpose, then layers constraints and behavioral notes. Every sentence carries distinct, non-redundant information, though the density is on the heavier side for the tool's scope.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists, return-value detail is optional, yet the description still names the returned fields. Combined with the env-var requirement, size limit, and campaign targeting rules, the definition is complete for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 meaningful constraints not in the schema—the 10 MB size ceiling, that bytes must be padded base64 with no data-URL prefix, and that the file name must be safe with a matching MIME type.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Prepare') and resource ('a local file for a `FILE` Program Resource'), and clarifies it is a prerequisite step producing an upload ticket rather than the resource itself. This distinguishes it from sibling tools like growsurf_create_program_resource.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context: the tool returns uploadTicket/uploadResult 'required for file resource creation or replacement,' and it names the server prerequisite (GROWSURF_UPLOAD_ALLOWED_ORIGINS) whose absence limits you to LINK/TEXT resources. It stops short of explicitly naming the downstream sibling to call next.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_program_design_advisorRecommend Program DesignARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| goal | No | 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`. | other |
| detail | No | Use 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 |
| audience | No | Who refers whom. | |
| industry | No | Closest 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 |
| companyName | No | Used in the heading and proposed program name; omit it when unknown. | |
| currencyISO | No | ISO 4217 code. Non-USD advice omits the dollar reward bands. No exchange rate or equivalent-currency benchmark is available. | |
| programType | No | REFERRAL | |
| salesMotion | No | Use `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. | |
| includeRules | No | Append guidance on applying the recommendations. Off by default. | |
| businessModel | No | One line on what the business sells and how. Also set `salesMotion` when the buying process is known. | |
| qualifyingAction | No | The action a referred friend must complete, in the customer's words. | |
| rewardBudgetPerReferral | No | The 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
| Name | Required | Description |
|---|---|---|
| markdown | No | The requested summary or full advice, including the same configuration calls and their conditions. |
| decisions | No | Use one qualifying action throughout the draft. Unresolved choices require a customer decision before configuration. |
| benchmarkFacts | No | Complete benchmark statements with metric units, median, Q1, Q3, sample, and source. Quote each statement intact. Empty when no suitable figures are available. |
| configurationPlan | No | Proposed 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
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description confirms read-only. Beyond that it discloses meaningful behavior: incentive amounts and qualifying actions remain unresolved unless supplied, the response shape (draft, benchmarkFacts, configurationPlan, decisions), that hosted figures describe GrowSurf's high-performing programs, and that guidance is documentation-based without a bundle. It doesn't mention rate limits or auth, but adds substantial context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded, leading with outputs and read-only status before parameter notes. Most sentences carry distinct information (detail modes, programType, industry:other), though the accumulation of parenthetical notes makes it slightly list-like rather than sharply prioritized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 12-parameter, zero-required advisory tool with an output schema, the description supplies enough: it enumerates the return artifacts, flags unresolved fields (incentive amounts, qualifying actions), and clarifies the detail-mode tradeoff. Since an output schema exists it needn't describe return values in depth, so the added detail is a bonus rather than a gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 92%, so the schema already documents nearly every parameter, including enum meanings for industry and goal. The description mostly restates these (programType AFFILIATE, industry other) rather than adding new semantics, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource set: generate program designs, benchmarks, typical rewards, and metric definitions, including named ratios. It clearly distinguishes itself from the sibling creation/mutation tools (create_campaign, update_campaign, etc.) by being an advisory generator, and specifies the exact output artifacts (benchmarkFacts, configurationPlan, decisions).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete selection guidance: `detail: summary` for a first draft, `detail: full` only for detailed benchmark tables, `programType: AFFILIATE` for affiliate advice, and `industry: other` for local services/pets/hospitality/agencies. It stops short of explicitly stating when to prefer this tool over sibling design tools like get_campaign_design or agent_program_creation_eval, 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_record_saleRecord SaleAIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| paidAt | No | ||
| orderId | No | ||
| chargeId | No | ||
| currency | Yes | ||
| testMode | No | Required with `paymentProvider`: `true` for test or `false` for live. Otherwise omit. | |
| invoiceId | No | ||
| netAmount | No | ||
| paymentId | No | ||
| taxAmount | No | ||
| amountPaid | No | ||
| campaignId | Yes | 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. | |
| customerId | No | ||
| externalId | No | ||
| totalTaxes | No | ||
| description | No | ||
| grossAmount | Yes | ||
| invoiceTotal | No | ||
| amountCashNet | No | ||
| participantId | No | ||
| transactionId | No | ||
| subscriptionId | No | ||
| totalTaxAmount | No | ||
| paymentIntentId | No | ||
| paymentProvider | No | 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. | |
| totalTaxAmounts | No | ||
| participantEmail | No | ||
| invoiceTotalExcludingTax | No | ||
| invoiceSubtotalExcludingTax | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| message | No | Human-readable result message. |
| success | No | `true` when the sale was recorded; `false` when it matched an existing transaction. |
| duplicate | No | `true` when the sale matched an existing transaction. |
| firstSale | No | Whether this was the referred customer's first recorded sale. |
| duplicateFields | No | Identifier fields that matched an existing transaction. |
| commissionsCreated | No | Commissions created by this duplicate request. |
| matchingCommissionIds | No | Commission ids that matched the submitted identifiers. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=true, destructiveHint=false and openWorldHint=true, but the description explains *why* idempotency matters (duplicate calls would double-pay the referrer) and that the same identifier must be reused on refund. It adds the campaignId default-to-env-var fallback, which annotations do not convey. It says nothing about auth/permission requirements 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the action and then the critical identifier requirement before the targeting detail. The enumeration of seven identifier names restates the schema's anyOf and is the only mildly wasteful element.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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, and annotations cover the safety profile. Still, for a 28-parameter mutation tool with nested anyOf/if-then constraints, the description omits the meaning of the amount and invoice fields and the paymentProvider/testMode interaction that the schema only partially documents.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 carries real weight and does explain the dedup-key concept plus the campaignId fallback. However, it leaves the large family of financial fields (grossAmount vs netAmount vs amountPaid vs amountCashNet, invoice totals, tax arrays, paidAt, subscriptionId, customerId) entirely unexplained, which is a significant gap for a money-handling tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Record a sale/transaction for an affiliate program'), which is clear enough to distinguish it from the CRUD-oriented campaign/reward siblings. It also hints at the adjacent refund flow ('reuse the same one when refunding'), but never explicitly names a sibling tool, so it stops short of full differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives real operational context: use webhooks rather than polling to learn when commissions land, and always supply a transaction identifier so repeats de-duplicate instead of double-paying. It does not state when to prefer this tool over alternatives such as trigger_referral or add_participant, so no explicit exclusions are provided.
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 ChargebackADestructiveIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| amount | No | ||
| orderId | No | ||
| chargeId | No | ||
| currency | No | ||
| refundId | No | 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. | |
| testMode | No | Original payment mode: `true` for test or `false` for live. Requires `paymentProvider`. | |
| invoiceId | No | ||
| paymentId | No | ||
| campaignId | Yes | 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. | |
| externalId | No | ||
| description | No | ||
| refundAmount | No | 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. | |
| refundStatus | No | ||
| amendmentType | No | ||
| participantId | No | ||
| transactionId | No | ||
| amountRefunded | No | ||
| paymentIntentId | No | ||
| paymentProvider | No | Connected provider for the original payment. Requires its `transactionId` and `testMode`. This amends GrowSurf records without sending a refund through the provider. | |
| participantEmail | No | ||
| refundHistoryComplete | No | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| deleted | No | Pending commissions deleted by the amendment. |
| matched | No | Commissions found for the provided identifiers. |
| message | No | Human-readable result message. |
| success | No | `true` when the amendment was processed; `false` when no matching transaction was found. |
| adjusted | No | Commissions partially adjusted. |
| notFound | No | Present and `true` when no commission matched the provided identifiers. |
| reversed | No | Commissions reversed (set to zero amount). |
| amendmentType | No | Amendment type that was processed. |
| matchingCommissionIds | No | Commission ids that matched the submitted identifiers. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare write/destructive/idempotent/openWorld, and the description adds real behavioral context beyond them: the amendment is recorded locally without touching the provider, already-paid commissions are not clawed back and are logged for tax only, and an omitted amountRefunded means a full refund. It stops short of surfacing the 409/incomplete-refund-history behavior, which lives only in the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The main action is front-loaded and each of the six sentences contributes a distinct fact (effect, no-provider-refund, identifier requirement, full-refund default, paid-commission handling, campaign targeting). It is dense but not padded, though it could be tightened marginally.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex 21-parameter mutation with conditional requirements, the description covers the key decision points while annotations carry the safety profile and the output schema carries return values. The main omission is the paymentProvider-implies-testMode/transactionId rule and refund-identity rules, which the schema documents instead.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 29% across 21 parameters, so the description must compensate, and it does cover the highest-value semantics: transactionId reuse, amountRefunded defaulting to full refund, and campaignId falling back to GROWSURF_CAMPAIGN_ID. It adds nothing for amendmentType, currency, amount, refundId/refundAmount, or the paymentProvider/testMode conditional, leaving meaningful gaps.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Record a refund, partial refund, or chargeback for a previously recorded affiliate transaction') and names the downstream effect on the commission. No sibling tool covers refunds, so the operation is unambiguously distinguishable from record_sale and the campaign/program management tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear precondition ('for a previously recorded affiliate transaction') and the matching requirement ('Requires the same transaction identifier as the original sale'), plus a scope clarification that no refund is sent through the payment provider. It does not explicitly name an alternative tool or state when not to use this, but the context is strong.
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 ConfirmationADestructiveInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| provider | Yes | The payout provider the participant should confirm a destination for. | |
| campaignId | Yes | 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. | |
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | No | Confirms the message was requested (`CONFIRMATION_REQUESTED`). |
| provider | No | The payout provider identifier the participant was asked to confirm. Values are open-ended; current examples include `PAYPAL`, `VENMO`, and `WISECOM`. |
| expiresAt | No | When the confirmation link expires, as a Unix timestamp in milliseconds. |
| providerDisplayName | No | The customer-facing provider name (e.g. "PayPal", "Wise"). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations present, the description still adds meaningful context beyond them: a one-time link is emailed, the call merely triggers the message, only the participant can open the link, and the provider must be enabled. It also discloses the return shape. The phrase 'this just triggers the message' sits in mild tension with destructiveHint=true, though the emphasis on non-idempotent one-time links is consistent with idempotentHint=false.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then behavior/limits, then return shape and targeting. Dense but each clause carries information; the em-dash asides are slightly heavy but not wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so restating the return fields is a bonus rather than a gap. For a moderate-complexity mutation tool the description covers preconditions, behavior, identifier options, and campaign targeting; only edge behavior (repeat calls invalidating prior links, provider-not-enabled errors) is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 50%, so the description must compensate: it clarifies that participantId/participantEmail are alternative identifiers and explains campaignId targeting and fallback to GROWSURF_CAMPAIGN_ID. Provider values are left to the schema enum, and no format hints for IDs/emails are given.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (ask/request confirmation) and resource (payout destination for a given provider), and explains the two ways to identify the participant (ID or email). It is clearly distinguishable from the adjacent read-only sibling growsurf_get_participant_payout_destination, which retrieves rather than requests.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives real preconditions: the provider must be enabled for the program, the tool only sends the message (it does not confirm on the participant's behalf), and the participant is the only one who can act on the link. It does not explicitly name alternative tools (e.g., checking the existing destination before requesting confirmation), 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_request_team_verificationRequest Team VerificationAIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | The team's display name. |
| verificationStatus | No | Team verification state. `VERIFIED` is required before a program can send participant emails. |
| verificationRequestedAt | No | When verification was last requested, as a Unix timestamp in milliseconds. |
TDQS
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.
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.
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.
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.
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.
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 EmailADestructiveInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| status | No | Status of the verification email request. |
| success | No | Whether the verification email request was accepted. |
TDQS
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.
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.
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.
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.
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.
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 WebhookADestructiveInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| event | No | ||
| webhookId | Yes | ||
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| payload | No | The mock event payload that was sent. |
| success | No | Whether the test webhook request completed. |
| response | No | Response returned by the webhook endpoint during the test. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and openWorldHint=true, so the safety profile is covered. The description adds meaningful context beyond that: it uses the webhook's stored URL and secret, sends a live event, returns the mock payload plus the endpoint's response, and returns 400 when no enabled events exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four front-loaded sentences with no filler; each conveys distinct information (mechanism, event selection, return value, targeting). Slightly verbose but well organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 detailed, yet the description still summarizes them. Error condition and default targeting are covered; only webhookId's role is left implicit, but the annotations carry the safety profile.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 33% (only campaignId documented), so the description must compensate. It does: it explains the `event` parameter (choose event type, defaults to first enabled event) and confirms campaignId defaults to GROWSURF_CAMPAIGN_ID. webhookId semantics are only implied, leaving a minor gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (send a test event), resource (webhook), and scope (on your GrowSurf program using its stored URL and secret). Clearly distinguishes it from sibling webhook CRUD tools like create/update/delete_campaign_webhook.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Establishes context well: simulating an event to exercise a webhook, with the event-type selection described. It does not explicitly name alternative siblings (e.g., list_campaign_webhooks) or when-not-to-use, but the intended scenario is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_trigger_referralTrigger ReferralADestructiveInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | 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. | |
| delayInDays | No | ||
| participantId | No | ||
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| message | No | Human-readable result message. Present when credit was not awarded immediately. |
| success | No | Whether referral credit was awarded, scheduled, or cancelled. |
TDQS
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 mutation/irreversibility profile is covered. The description adds the delay semantics (credit held N days before awarding), but does not disclose auth needs, rate limits, or that the trigger itself cannot be undone beyond what annotations state.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action and condition, three tight sentences with no padding. The final clause on campaignId largely restates the schema's own description of that field, a small redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 is out of scope, and the destructive/idempotency traits are carried by annotations. The description covers purpose, trigger condition, and the two non-obvious parameters, leaving only minor gaps (auth/rate-limit context) for a mutation tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is low (25%), so the description must compensate, and it does for the key params: it explains delayInDays' 1-90 range and effect and campaignId's fallback to GROWSURF_CAMPAIGN_ID. It adds little for participantId vs participantEmail beyond 'referred participant', leaving the anyOf choice to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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 the triggering condition (Sign up + Qualifying Action), so the purpose is unambiguous. It does not name or contrast a sibling (e.g. cancel_delayed_referral), so sibling differentiation relies on the name alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear condition for use ('use when your trigger is Sign up + Qualifying Action') plus guidance on when to pass delayInDays (refund window). It stops short of stating when not to use it or naming the delayed-credit alternative.
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 TrackingARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| symptom | No | The 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. | |
| campaignId | No | 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. | |
| description | No | The problem in the customer's words, when `symptom` is unknown. | |
| participantId | No | Affected participant id, echoed into participant-level checks. | |
| participantEmail | No | Affected participant email, when the id is unknown. |
Output Schema
| Name | Required | Description |
|---|---|---|
| markdown | No | The generated guidance as a markdown document. |
TDQS
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.
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.
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.
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.
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.
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 ProgramADestructiveIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| status | No | Lifecycle transition. IN_PROGRESS publishes/resumes the program; COMPLETE ends it. These are the only accepted targets — DRAFT/PENDING/CANCELLED are rejected by the API. | |
| campaignId | Yes | 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. | |
| companyName | No | ||
| companyLogoImageUrl | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and idempotentHint=true, but the description earns credit by explaining what is actually destroyed: setting status=COMPLETE ends the program while IN_PROGRESS publishes/resumes it. It also discloses PATCH-style semantics ('only the fields you send are changed') and the targeting fallback to GROWSURF_CAMPAIGN_ID, none of which 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The opening clause leads with the action and field list, followed by constraints and routing in descending priority. It is dense with parentheticals but each sentence carries distinct information; only the currency note slightly over-explains an immutable field that is not a parameter at all.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive mutation tool with an output schema (so return values need no explanation) and full annotation coverage, the description covers targeting, partial update, lifecycle side effects, and sibling routing. The one omission is that it never states at least one of the four fields must be supplied, despite the schema's anyOf requirement.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 40%, so the description must carry weight: it names the four mutable fields, clarifies partial-update behavior, and explains why type/urlId/currencyISO are absent. However, the status enum's meaning and the campaignId default are already spelled out in the schema descriptions, so the description mostly repeats rather than extends the structured fields. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Update your GrowSurf program's (campaign's) identity and lifecycle') and enumerates the exact mutable fields. It actively distinguishes itself from siblings by declaring that editor-tab config (design, emails, options, installation) belongs to the dedicated sub-resource tools, so an agent can route without opening other schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the alternative tools for adjacent work ('edited with the dedicated config sub-resource tools, not here') and gives the conditions that select this tool (identity/lifecycle fields, with at least one field supplied). It also states the negative case — immutable fields type/urlId/currencyISO are rejected — which prevents a foreseeable failed call.
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 DesignADestructiveIdempotentInspect
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, payout-destination confirmation page copy under payoutDestinationConfirmation, and the participant Settings panel under participantSettings, such as the language picker's languageSectionTitle and languageSectionInstructionsText (up to 500 characters each). 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.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | Yes | ||
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, yet the description adds meaningful behavior: partial-merge semantics with wholesale array replacement, the constraint that trafficInsights labels cannot be blank, the 500-character limit on language-section copy, and the environment-variable default for campaignId. What it does not add is the concrete destructive consequence of a partial update (what an overwritten array loses) or any auth/permission requirement.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action and scope, and every clause conveys usable information (field names, enums, limits, merge rules) rather than filler. It is a single dense paragraph of long comma-separated lists, however, when bulleted grouping by sub-area would have scanned faster.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a nested, open-ended `fields` payload, the description covers what can be changed, the enum domain, validation limits, array-replacement semantics, and id-vs-env-var targeting. An output schema exists, so return values need no explanation, and nothing required to call the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 50% and the `fields` object is declared as an opaque additionalProperties bag with no documented sub-keys, so the description carries the real burden: it names the accepted shapes, the enum values for participantAvatarStyle (CHARACTERS, INITIALS, ANIMALS, GRADIENT), and the specific nested paths like trafficInsights.isPublicDisplayed and participantSettings.languageSectionTitle. This is far more than the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Update') and resource ('design configuration for your GrowSurf program') and enumerates the exact sub-areas it governs (participantAvatarStyle, widget, trafficInsights, login, payoutDestinationConfirmation, participantSettings), which cleanly separates it from siblings like growsurf_update_campaign_options and growsurf_update_campaign_emails. An agent can identify the tool's domain 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the field-level scope, and merge behavior ('Only supplied fields change; omitted fields retain their existing content') tells the agent how to invoke it, but there is no explicit when-to-use/when-not guidance and no sibling named as the alternative (e.g., get_campaign_design for reading, or the options/emails tools for other program sections).
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 EmailsADestructiveIdempotentInspect
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 accept non-empty strings, not null. Omit either field to keep its current value, including an unset value returned by a read. The invite and transactional email isEnabled toggles are read-only. Email bodies require their template links and footer tokens. When settings.design.layoutMode is INLINE, each body must include {{emailFooter}}; {{emailHeader}} is optional. layoutMode is read-only. Omitted fields retain their existing content; arrays replace wholesale. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | Yes | ||
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite annotations already declaring destructiveHint=true and idempotentHint=true, the description adds substantial non-obvious behavioral detail: `fromEmail` is read-only and requires dashboard domain verification, `fromName`/`replyToEmail` reject null, `invite`/transactional `isEnabled` toggles and `layoutMode` are read-only, arrays replace wholesale, and INLINE layout bodies must include `{{emailFooter}}`. This is exactly the kind of constraint info an agent cannot get 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in the first clause, followed by constraint sentences that each carry distinct information. It is dense rather than padded, though the single long paragraph mixes several constraint families and could be marginally better organized for scanning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, idempotent, nested-object patch tool with an output schema (so return values need no explanation), the description covers the read-only traps, null handling, array replacement, conditional template tokens, and target resolution. An agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With only 50% schema description coverage, the description compensates well: it clarifies which nested fields are writable vs read-only, null-vs-omit behavior for sender fields ('Omit either field to keep its current value, including an unset value returned by a read'), conditional body requirements, and the campaignId default. This meaningfully exceeds what the schema conveys.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource+scope: 'Update writable Emails tab fields for your GrowSurf program under `fields`'. An agent immediately knows this is a patch operation on the emails configuration. It does not explicitly name its read counterpart (growsurf_get_campaign_emails) or otherwise route among siblings, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides operational context (targets `campaignId` if supplied, otherwise `GROWSURF_CAMPAIGN_ID`) and explains omission/retention semantics, which is useful guidance. However, it never states when to reach for this tool versus alternatives like `growsurf_get_campaign_emails` or `growsurf_update_campaign_options`, leaving usage largely implied.
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 InstallationADestructiveIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | Yes | Installation fields to patch. Common keys include `shareUrl`, `allowedUrls`, `signupEvent`, `referralTrigger`, `signup`, and `instructionSelections`. Arrays replace wholesale. | |
| campaignId | Yes | 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. | |
| replaceExistingShareUrl | No | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (destructiveHint, idempotentHint, openWorldHint), it discloses non-obvious behavior: omitted fields are preserved, arrays replace wholesale, an origin absent from both `shareUrl` and `allowedUrls` can yield 403, existing referral links point at the current `shareUrl`, and the patch is refused without confirmation. These are exactly the operational details an agent cannot 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose, then layers the highest-risk rule (Share URL replacement refusal) and side-effect notes. Every sentence carries actionable information, though the paragraph is dense and some `allowedUrls` examples overlap with the schema's own description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, nested-object patch tool with an output schema present, the description covers the patch model, the safety prerequisite, targeting, and the 403 failure mode. Return values are correctly left to the output schema, leaving no material gap for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, and the description adds genuine meaning on top: it clarifies `allowedUrls` semantics (permitted browser origins, e.g. localhost), the refusal consequence of omitting `replaceExistingShareUrl`, and the default-resolution behavior of `campaignId`. It stops short of 5 because much of this overlaps with already-detailed schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and a precisely scoped resource ('Update the Installation tab configuration for your GrowSurf program under `fields`'). This inherently distinguishes it from the many sibling update tools (update_campaign, update_campaign_options, update_campaign_design, update_campaign_emails), which target different program sub-surfaces.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear conditional guidance: patch semantics (only supplied fields change, arrays replace wholesale), the explicit prerequisite that replacing an existing Share URL needs customer approval plus `replaceExistingShareUrl: true`, and targeting via `campaignId` or `GROWSURF_CAMPAIGN_ID`. It does not explicitly name an alternative tool for the cases where a sibling (e.g. update_campaign) would be the right choice, so it stops just short of 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 OptionsADestructiveIdempotentInspect
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. languages.additionalLanguages takes the full list of extra languages; send [] to turn them off. The base language is dropped from that list and duplicates collapse. languages.showFlags shows or hides the flag next to each language name. Turning languages on, and any change while they are on (including turning them off or changing showFlags), requires the Business plan or higher and returns a 403 otherwise. Translations are managed in the GrowSurf dashboard, not through this tool. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | Yes | ||
| campaignId | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructive/idempotent/openWorld, but the description adds substantial behavior beyond them: patch semantics (only supplied fields change, omitted fields retained, arrays replace wholesale), the base-language-drop and duplicate-collapse rules, `[]` to disable languages, and a hard plan gate that returns 403 without the Business plan. That is exactly the kind of auth and mutation detail the annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and target, then dense with only information-bearing sentences about merge behavior, language handling, and the plan gate. It runs long, but nearly every clause carries a rule the agent needs; nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 covers merge semantics, language edge cases, targeting, and plan gating, so return values need not be explained. The one remaining gap is that it never points the agent to `growsurf_get_campaign_options` to discover the available top-level option fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 50% (the `fields` object is undocumented in the schema), so the description must compensate, and it does: it defines `fields` as the existing nested shape and details `languages.additionalLanguages` and `languages.showFlags` semantics. It still does not enumerate the full set of option fields, so it is strong but not exhaustive.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Update the Options tab configuration for your GrowSurf program under `fields`'. This scope implicitly separates it from the many other update_campaign_* siblings (design, emails, installation) and from the generic update_campaign, though no sibling is named explicitly, so it falls 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear when-not-use exclusion: translations are managed in the dashboard, not through this tool. It also frames the targeting rule (`campaignId` else `GROWSURF_CAMPAIGN_ID`). It does not route the agent between this tool and `growsurf_update_campaign` or `growsurf_get_campaign_options`, so it stops short of full alternative guidance.
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 RewardBDestructiveIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| event | No | 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. | |
| limit | No | ||
| order | No | ||
| title | No | ||
| value | No | Tax 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`. | |
| imageUrl | No | ||
| metadata | No | ||
| isVisible | No | ||
| campaignId | Yes | 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. | |
| couponCode | No | ||
| description | No | ||
| isUnlimited | No | ||
| limitDuration | No | ||
| referredValue | No | Tax 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. | |
| numberOfWinners | No | ||
| campaignRewardId | Yes | ||
| referralCouponCode | No | ||
| commissionStructure | No | 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. | |
| conversionsRequired | No | ||
| nextMilestonePrefix | No | ||
| nextMilestoneSuffix | No | ||
| referralDescription | No | ||
| referredRewardUpfront | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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/mutation profile is covered. The description adds genuinely useful context by stating the reward `type` is immutable and explaining the campaign targeting fallback, but it does not disclose what an update overwrites or any 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the core action and followed by the two most decision-relevant facts (key format, immutable type, targeting). No filler, though it is arguably under-developed for a 23-parameter mutation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 immutability and targeting. However, for a 23-parameter destructive update with only 22% schema coverage, the description is thin and leaves the agent to infer which fields are meaningfully updatable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is low at 22%, so the description must compensate. It clarifies `campaignRewardId` (the reward key, e.g. crew_...) and the campaignId targeting rule, but says nothing about the other 21 parameters, leaving most of the surface undocumented outside the schema's own nested-object descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource ('Update an existing campaign reward (reward config)') and adds a clarifying parenthetical. It is distinguishable from create/delete/list reward siblings by the verb, but it never names an alternative or explicitly scopes itself against them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The only routing information is about the target campaign ('Targets `campaignId` if you pass it, otherwise GROWSURF_CAMPAIGN_ID'), which is parameter behavior rather than usage guidance. There is no statement of when to use this tool versus create_campaign_reward or update_campaign, and no 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_update_campaign_webhookUpdate WebhookADestructiveIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| events | No | ||
| secret | No | Write-only. | |
| isEnabled | No | ||
| webhookId | Yes | ||
| campaignId | Yes | 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. | |
| payloadUrl | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true and openWorldHint=true. The description usefully adds the non-obvious behavioral facts that only sent fields change (partial update) and that `secret` is write-only and never returned. It does not, however, explain what the destructive flag actually implies for an agent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the core action, then the fields-sent semantics, then the special id and targeting rules. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 id//primary semantics, partial updates, and write-only secret. The remaining gap is a statement of the destructive/idempotent consequences and any auth requirements.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 33%, so the description must compensate. It does add real value by defining `webhookId` = `primary` and the `campaignId`/GROWSURF_CAMPAIGN_ID fallback, but `events`, `payloadUrl`, and `isEnabled` get no explanation beyond their names and are left undocumented in both places.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Update a webhook on your GrowSurf program by id.' The update verb distinguishes it from the sibling webhook tools (list/create/delete/test), though it does not name an alternative explicitly. Clear but no deliberate sibling routing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies when to use it (you have an existing webhook id and want to change fields) and clarifies the partial-update contract. However, there is no explicit when-not guidance, no mention of prerequisites/permissions, and no comparison against growsurf_create_campaign_webhook or growsurf_delete_campaign_webhook.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_update_participantUpdate ParticipantADestructiveIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| No | Change the participant's email address. | ||
| notes | No | Freeform internal notes (internal only, never exposed to participants). | |
| language | No | The language of the participant's portal and program emails. Must be one of the program's languages (`languages` in `growsurf_get_campaign_options`); any other code returns a `400`. Send `null` or the program's base language to clear it, so the participant follows the base language. Supported codes: `en`, `es`, `fr`, `de`, `it`, `pt-BR`, `nl`, `pl`, `sv`, `tr`, `ja`, `ko`, `zh-CN`, `id`, `da`, `nb`, `nn`, `fi`, `is`, `cs`, `sk`, `hu`, `ro`, `hr`, `sl`, `et`, `lv`, `lt`, `el`, `bg`, `uk`, `ru`, `pt-PT`, `ca`, `vi`, `ms`, `fil`, `af`, `sw`. | |
| lastName | No | ||
| metadata | No | ||
| firstName | No | ||
| campaignId | Yes | 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. | |
| referredBy | No | ||
| vanityKeys | No | ||
| unsubscribed | No | ||
| participantId | No | ||
| referralStatus | No | ||
| affiliateStatus | No | Affiliate 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. | |
| participantEmail | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say mutation/destructive/idempotent; the description goes well beyond by naming exactly which fields are rejected (counters, isAffiliate, origin, fraud state) and with what error, disclosing that SUSPENDED/BANNED require an existing affiliate, that enrollment is not removable via REST, and that notes are never exposed to participants. The destructive hint is also implicitly qualified by the partial-update guarantee.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Roughly six dense sentences, each carrying distinct operational information; the subject and lookup keys come first, followed by mutation semantics and then edge-case rules. No filler or restatement of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 14-parameter mutation tool with an output schema (so return values need not be described) and annotations covering safety, the description is close to complete: partial-update behavior, error conditions, affiliate constraints, and targeting are all covered. Minor gaps remain around auth/permission requirements and the unexplained free-form fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 36% across 14 params, so the description must compensate, and it does for the risky ones: affiliateStatus semantics (enroll vs. requires existing affiliate), notes privacy, and campaignId defaulting to GROWSURF_CAMPAIGN_ID. It leaves referredBy, vanityKeys, unsubscribed, referralStatus, and metadata behavior unexplained, which keeps it below 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Update a participant') plus the two accepted lookup keys (participant ID or email). It is immediately distinguishable from growsurf_get_participant, growsurf_add_participant, and growsurf_bulk_delete_participants 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete usage conditions: partial-update semantics ('only the fields you send are changed'), the 400 rejection for read-only fields, and the affiliate-status rules including that enrollment cannot be removed via REST. It does not explicitly route to sibling tools (e.g. get_participant to read, add_participant to create), so it stops short of 5.
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 ResourceADestructiveIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Used with `LINK`. | |
| text | No | Used with `TEXT`. | |
| type | No | ||
| title | No | ||
| category | No | ||
| position | No | ||
| campaignId | Yes | 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. | |
| resourceId | Yes | ||
| description | No | ||
| isPublished | No | ||
| uploadResult | No | The unmodified result returned by the secure upload flow for a replacement `FILE`. | |
| uploadTicket | No | The one-time upload ticket for a replacement `FILE`. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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 baseline is covered. The description adds genuinely useful behavior beyond that: partial-patch semantics ('Only supplied fields change'), the one-time nature of uploadTicket, the requirement that uploadResult be unmodified, and the campaignId/campaign-env fallback targeting rule.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and patch semantics, followed by the FILE precondition and targeting rule; every sentence carries information. The bare API reference URL is the only slightly wasteful element.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 12-parameter tool with heavy allOf/anyOf conditionals and a nested upload object, the description surfaces the two conditionals an agent most needs (at-least-one-field and FILE pairing) plus targeting. With an output schema present, return values need not be explained. Type-variant semantics (LINK/TEXT/FILE mutual exclusivity) rely on the schema, leaving a small gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With only 42% schema description coverage, the description must compensate and largely does: it explains position is zero-based, that FILE replacement needs the paired uploadTicket+uploadResult, and that campaignId overrides GROWSURF_CAMPAIGN_ID. It still leaves type/title/category/isPublished/description semantics to the schema, so not a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (update a program/participant resource) and adds the key scope constraint that at least one field must change or move position. It does not explicitly contrast with siblings like growsurf_create_program_resource or growsurf_prepare_program_resource_file, so a 4 rather than a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when the tool applies (partial field updates and positional moves) and conditionally gates the FILE path on uploadTicket/uploadResult, but it never states when to choose this over create/delete/list resource siblings or what prerequisites (e.g., the secure upload flow) must be completed first. Usage is implied, not spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
growsurf_update_teamUpdate TeamADestructiveIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The team's display name. |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | The team's display name. |
| verificationStatus | No | Team verification state. `VERIFIED` is required before a program can send participant emails. |
| verificationRequestedAt | No | When verification was last requested, as a Unix timestamp in milliseconds. |
TDQS
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.
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.
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.
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.
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.
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 PayloadARead-onlyIdempotentInspect
Validate/normalize a GrowSurf webhook payload and generate a best-effort idempotency key for dedupe.
| Name | Required | Description | Default |
|---|---|---|---|
| payload | Yes | JSON value to validate. A valid webhook envelope is an object with `event`, `createdAt`, and `data`. Other JSON values return `ok: false`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | No | Whether the payload is a valid GrowSurf webhook envelope. |
| error | No | Why the payload failed validation. Present only when `ok` is `false`. |
| envelope | No | The normalized webhook envelope. Present only when `ok` is `true`. |
| idempotencyKey | No | A deterministic key for ignoring duplicate deliveries. Present only when `ok` is `true`. |
TDQS
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.
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.
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.
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.
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.
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.
47 tool updates
v0.19.15- Changed
growsurf_add_participant3 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / properties / languageAdded value: +{ + "description": "The language of the participant's portal and program emails. Must be one of the program's languages (`languages` in `growsurf_get_campaign_options`); any other code returns a `400`. Applies only when this call creates the participant. Omit it or send `null` to use the program's base language. Supported codes: `en`, `es`, `fr`, `de`, `it`, `pt-BR`, `nl`, `pl`, `sv`, `tr`, `ja`, `ko`, `zh-CN`, `id`, `da`, `nb`, `nn`, `fi`, `is`, `cs`, `sk`, `hu`, `ro`, `hr`, `sl`, `et`, `lv`, `lt`, `el`, `bg`, `uk`, `ru`, `pt-PT`, `ca`, `vi`, `ms`, `fil`, `af`, `sw`.", + "type": [ + "string", + "null" + ] +} - changed
Input schema / requiredPrevious value: -[ - "email" -]New value: +[ + "email", + "campaignId" +]
- Changed
growsurf_bulk_delete_participants2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "participants" -]New value: +[ + "participants", + "campaignId" +]
- Changed
growsurf_cancel_delayed_referral2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_capture_referral_flow_screenshots2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_clone_campaign2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_create_campaign_reward2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "type" -]New value: +[ + "type", + "campaignId" +]
- Changed
growsurf_create_campaign_webhook2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "payloadUrl" -]New value: +[ + "payloadUrl", + "campaignId" +]
- Changed
growsurf_create_mobile_participant_token3 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / properties / languageAdded value: +{ + "description": "The language of the participant's portal and program emails. Must be one of the program's languages (`languages` in `growsurf_get_campaign_options`); any other code returns a `400`. Applies only when this call creates the participant. Omit it or send `null` to use the program's base language. Supported codes: `en`, `es`, `fr`, `de`, `it`, `pt-BR`, `nl`, `pl`, `sv`, `tr`, `ja`, `ko`, `zh-CN`, `id`, `da`, `nb`, `nn`, `fi`, `is`, `cs`, `sk`, `hu`, `ro`, `hr`, `sl`, `et`, `lv`, `lt`, `el`, `bg`, `uk`, `ru`, `pt-PT`, `ca`, `vi`, `ms`, `fil`, `af`, `sw`.", + "type": [ + "string", + "null" + ] +} - changed
Input schema / requiredPrevious value: -[ - "email" -]New value: +[ + "email", + "campaignId" +]
- Changed
growsurf_create_program_resource2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "type", - "title" -]New value: +[ + "type", + "title", + "campaignId" +]
- Changed
growsurf_delete_campaign_reward2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "campaignRewardId" -]New value: +[ + "campaignRewardId", + "campaignId" +]
- Changed
growsurf_delete_campaign_webhook2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "webhookId" -]New value: +[ + "webhookId", + "campaignId" +]
- Changed
growsurf_delete_program_resource2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "resourceId" -]New value: +[ + "resourceId", + "campaignId" +]
- Changed
growsurf_email_participant3 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / properties / emailType / descriptionPrevious value: -"The 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`."New value: +"The 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. `welcomeNonReferred` can only be sent to advocates or approved, enrolled affiliates in a program that has not ended. Referral programs: `welcomeNonReferred`, `referralLinkViewedFirstTime`, `referralLinkUsed`, `referredSignup`, `welcomeReferred`, `goalAchieved`, `campaignEndedWinners`, `campaignEndedNonWinners`, `progressUpdateMonthly`. Affiliate programs: `welcomeNonReferred`, `referralLinkViewedFirstTime`, `referredSignup`, `commissionGenerated`, `commissionAdjusted`, `payoutPending`, `payoutSentSuccess`, `progressUpdateMonthly`." - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_get_campaign2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_get_campaign_activation_analytics2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_get_campaign_analytics2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_get_campaign_design6 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +] - changed
Output schema / properties / participantSettings / descriptionPrevious value: -"The participant's account settings area (logout, PayPal and Wise payout confirmation/status messages, tax details)."New value: +"The participant's account settings area (logout, language picker, PayPal and Wise payout confirmation/status messages, tax details). `languageSectionTitle` and `languageSectionInstructionsText` (up to 500 characters each) are the title and help text of the language row, shown when the program has more than one language. `taxSection.instructionsText` and `taxSection.residencyLabel` show when tax forms are required; `taxSection.vatOnlyInstructionsText` and `taxSection.vatOnlyResidencyLabel` show instead when an affiliate program collects VAT numbers without requiring tax forms." - changed
Output schema / properties / referralStatus / descriptionPrevious value: -"The section listing who a participant invited and each invite's progress."New value: +"The section listing who a participant invited and each invite's progress. `revealInviteEmails` lets a signed-in participant see original invitation addresses when disclosure permission was recorded. Private invites and full email masking keep addresses hidden. Other referral addresses stay masked. `revealInviteEmailText` supplies the sign-in prompt; `loadErrorMessage` is shown when the list cannot load; `followUp` supplies the invitation follow-up labels and messages." - changed
Output schema / properties / widget / properties / reveal / descriptionPrevious value: -"When the card appears: right away, after `revealDelaySeconds`, or once the visitor scrolls halfway down the page. The button always appears right away."New value: +"What the element waits for before it appears: the page loading (`IMMEDIATE`) or the visitor scrolling halfway down the page (`SCROLL`). `revealDelaySeconds` then counts from that moment. `DELAY` is accepted for older programs and behaves as `IMMEDIATE`." - changed
Output schema / properties / widget / properties / revealDelaySeconds / descriptionPrevious value: -"Seconds to wait before showing the card, when `reveal` is `DELAY`."New value: +"Seconds to wait after the `reveal` trigger before showing the element. `0` shows it the moment the trigger fires."
- Changed
growsurf_get_campaign_emails7 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +] - added
Output schema / properties / followUpReminderAdded value: +{ + "description": "Optional reminder to the referrer about directly invited contacts who have not signed up after `delayDays` (integer 2–30, default 3). Existing reminder dates stay unchanged. Disabled by default. Only new invitations created while this email is enabled qualify automatically. A later offer claim preserves invitation eligibility; popup-only claims never qualify. Each contact is included once. Referral and affiliate programs.", + "type": "object" +} - changed
Output schema / properties / settings / descriptionPrevious value: -"Sender (`sender`), physical contact address (`contact`), and shared design (`design`) settings. The design object includes `unsubscribeAffiliateInvite` for direct affiliate invitation emails."New value: +"Sender (`sender`), physical contact address (`contact`), and shared design (`design`) settings. The design object includes `unsubscribeAffiliateInvite` for direct affiliate invitation emails. Its read-only `layoutMode` is `INLINE` for new programs: bodies require `{{emailFooter}}` and may include `{{emailHeader}}`. Older programs omit `layoutMode` and keep their existing layout." - added
Output schema / properties / settings / properties / designAdded value: +{ + "properties": { + "layoutMode": { + "description": "Read-only email layout. `INLINE` requires `{{emailFooter}}` in each body; `{{emailHeader}}` is optional.", + "enum": [ + "INLINE" + ], + "readOnly": true, + "type": "string" + } + }, + "type": "object" +} - changed
Output schema / properties / settings / properties / sender / properties / fromName / descriptionPrevious value: -"Sender name, or null before one is configured. A new value must not be an email address."New value: +"Sender name, or `null` before one is configured. When updating, omit to keep the current value or supply a non-empty name that is not an email address. `null` is not accepted on update." - changed
Output schema / properties / settings / properties / sender / properties / replyToEmail / descriptionPrevious value: -"Email address that receives replies, or null before one is configured."New value: +"Email address that receives replies, or `null` before one is configured. When updating, omit to keep the current value or supply a valid email address. `null` is not accepted on update."
- Changed
growsurf_get_campaign_installation2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_get_campaign_options3 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +] - added
Output schema / properties / languagesAdded value: +{ + "description": "The languages the program runs in. Participants see the portal and program emails in their language. Turning on additional languages, and any change while they are on, requires the Business plan or higher. Translations are managed in the dashboard.", + "properties": { + "additionalLanguages": { + "description": "Other languages participants can see, besides `baseLanguage`, using the same codes. `PATCH` replaces the whole list; `[]` turns them off. The base language is dropped from the list and duplicates collapse. Removing a language keeps its translations.", + "items": { + "type": "string" + }, + "type": "array" + }, + "baseLanguage": { + "description": "The language the program is written in (default `en`). Participants see it when their language is not one of the program's languages, and for untranslated text. Supported codes: `en`, `es`, `fr`, `de`, `it`, `pt-BR`, `nl`, `pl`, `sv`, `tr`, `ja`, `ko`, `zh-CN`, `id`, `da`, `nb`, `nn`, `fi`, `is`, `cs`, `sk`, `hu`, `ro`, `hr`, `sl`, `et`, `lv`, `lt`, `el`, `bg`, `uk`, `ru`, `pt-PT`, `ca`, `vi`, `ms`, `fil`, `af`, `sw`.", + "type": "string" + }, + "showFlags": { + "description": "Shows a flag next to each language name in the language picker participants use. New programs start with `false`.", + "type": "boolean" + } + }, + "type": "object" +}
- Changed
growsurf_get_participant3 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +] - added
Output schema / properties / languageAdded value: +{ + "description": "The language code of the participant's portal and program emails, such as `es`. The program's base language unless the participant (or you) picked another of the program's languages.", + "type": "string" +}
- Changed
growsurf_get_participant_activity_logs2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_get_participant_analytics2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_get_participant_payout_destination2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_integration_guide3 fields changed- changed
Input schema / properties / webhookSecurity / defaultPrevious value: -"token_in_url"New value: +"signature" - added
Input schema / properties / webhookSecurity / descriptionAdded value: +"Always recommends signature verification. Legacy values are accepted for compatibility and cannot disable verification." - changed
Input schema / properties / webhookSecurity / enumPrevious value: -[ - "token_in_url", - "none" -]New value: +[ + "signature", + "token_in_url", + "none" +]
- Changed
growsurf_list_campaign_rewards2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_list_campaign_webhooks2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_list_integrations2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_list_participants2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_list_program_resources2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_mobile_sdk_guide3 fields changed- added
Input schema / properties / platform / descriptionAdded value: +"`both` renders the native iOS and Android SDKs. `react_native` renders the React Native SDK for bare React Native apps and Expo development builds." - changed
Input schema / properties / platform / enumPrevious value: -[ - "ios", - "android", - "both" -]New value: +[ + "ios", + "android", + "both", + "react_native" +] - changed
Output schema / descriptionPrevious value: -"Native iOS/Android SDK guidance, as a markdown document."New value: +"Native iOS/Android or React Native SDK guidance, as a markdown document."
- Changed
growsurf_participant_auth_hash2 fields changed- added
Input schema / properties / participantAuthSecret / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "email" -]New value: +[ + "email", + "participantAuthSecret" +]
- Changed
growsurf_prepare_program_resource_file2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "fileName", - "mimeType", - "fileBase64" -]New value: +[ + "fileName", + "mimeType", + "fileBase64", + "campaignId" +]
- Changed
growsurf_record_sale2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "currency", - "grossAmount" -]New value: +[ + "currency", + "grossAmount", + "campaignId" +]
- Changed
growsurf_refund_transaction2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_request_participant_payout_destination_confirmation2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "provider" -]New value: +[ + "provider", + "campaignId" +]
- Changed
growsurf_test_campaign_webhook2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "webhookId" -]New value: +[ + "webhookId", + "campaignId" +]
- Changed
growsurf_trigger_referral2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_update_campaign2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_update_campaign_design2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "fields" -]New value: +[ + "fields", + "campaignId" +]
- Changed
growsurf_update_campaign_emails4 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / properties / fields / properties / settings / properties / sender / properties / fromName / descriptionAdded value: +"Sender name, up to 100 characters. Must not be blank or an email address. Omit to keep the current value; `null` cannot clear it." - added
Input schema / properties / fields / properties / settings / properties / sender / properties / replyToEmail / descriptionAdded value: +"Valid reply-to email address, up to 100 characters. Omit to keep the current value; `null` cannot clear it." - changed
Input schema / requiredPrevious value: -[ - "fields" -]New value: +[ + "fields", + "campaignId" +]
- Changed
growsurf_update_campaign_installation2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "fields" -]New value: +[ + "fields", + "campaignId" +]
- Changed
growsurf_update_campaign_options2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "fields" -]New value: +[ + "fields", + "campaignId" +]
- Changed
growsurf_update_campaign_reward2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "campaignRewardId" -]New value: +[ + "campaignRewardId", + "campaignId" +]
- Changed
growsurf_update_campaign_webhook2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "webhookId" -]New value: +[ + "webhookId", + "campaignId" +]
- Changed
growsurf_update_participant3 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - added
Input schema / properties / languageAdded value: +{ + "description": "The language of the participant's portal and program emails. Must be one of the program's languages (`languages` in `growsurf_get_campaign_options`); any other code returns a `400`. Send `null` or the program's base language to clear it, so the participant follows the base language. Supported codes: `en`, `es`, `fr`, `de`, `it`, `pt-BR`, `nl`, `pl`, `sv`, `tr`, `ja`, `ko`, `zh-CN`, `id`, `da`, `nb`, `nn`, `fi`, `is`, `cs`, `sk`, `hu`, `ro`, `hr`, `sl`, `et`, `lv`, `lt`, `el`, `bg`, `uk`, `ru`, `pt-PT`, `ca`, `vi`, `ms`, `fil`, `af`, `sw`.", + "type": [ + "string", + "null" + ] +} - added
Input schema / requiredAdded value: +[ + "campaignId" +]
- Changed
growsurf_update_program_resource2 fields changed- added
Input schema / properties / campaignId / minLengthAdded value: +1 - changed
Input schema / requiredPrevious value: -[ - "resourceId" -]New value: +[ + "resourceId", + "campaignId" +]
48 tool updates
v0.19.9- Changed
growsurf_add_participant1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_bulk_delete_participants1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_cancel_delayed_referral1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_capture_referral_flow_screenshots1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_clone_campaign1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_create_campaign1 field changed- changed
Input schema / properties / goal / descriptionPrevious 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."
- Changed
growsurf_create_campaign_reward1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_create_campaign_webhook1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_create_mobile_participant_token1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_create_program_resource1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_delete_campaign_reward1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_delete_campaign_webhook1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_delete_program_resource1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_email_participant1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_get_campaign1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_get_campaign_activation_analytics1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_get_campaign_analytics1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_get_campaign_design1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_get_campaign_emails1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_get_campaign_installation1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_get_campaign_options1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_get_participant1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_get_participant_activity_logs1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_get_participant_analytics1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_get_participant_payout_destination1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_list_campaign_rewards1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_list_campaign_webhooks1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_list_integrations1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_list_participants1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_list_program_resources1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_prepare_program_resource_file1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_program_design_advisor1 field changed- changed
Input schema / properties / goal / descriptionPrevious 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`."
- Changed
growsurf_record_sale1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_refund_transaction1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_request_participant_payout_destination_confirmation1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_test_campaign_webhook1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_trigger_referral1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_troubleshoot_referral_tracking1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_update_campaign1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_update_campaign_design1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_update_campaign_emails1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_update_campaign_installation1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_update_campaign_options1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_update_campaign_reward1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_update_campaign_webhook1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_update_participant1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_update_program_resource1 field changed- changed
Input schema / properties / campaignId / descriptionPrevious 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."
- Changed
growsurf_webhook_normalize2 fields changed- added
Input schema / properties / payload / descriptionAdded value: +"JSON value to validate. A valid webhook envelope is an object with `event`, `createdAt`, and `data`. Other JSON values return `ok: false`." - added
Input schema / properties / payload / typeAdded value: +[ + "object", + "array", + "string", + "number", + "boolean", + "null" +]
8 tool updates
v0.19.8- Changed
growsurf_create_campaign_reward6 fields changed- changed
Input schema / properties / couponCode / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Input schema / properties / imageUrl / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Input schema / properties / nextMilestonePrefix / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Input schema / properties / nextMilestoneSuffix / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Input schema / properties / referralCouponCode / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Input schema / properties / referralDescription / typePrevious value: -"string"New value: +[ + "string", + "null" +]
- Changed
growsurf_get_campaign_analytics5 fields changed- added
Input schema / allOfAdded value: +[ + { + "if": { + "required": [ + "startDate" + ] + }, + "then": { + "required": [ + "endDate" + ] + } + }, + { + "if": { + "required": [ + "endDate" + ] + }, + "then": { + "required": [ + "startDate" + ] + } + } +] - changed
Input schema / properties / endDate / descriptionPrevious 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." - added
Input schema / properties / endDate / minimumAdded value: +1 - changed
Input schema / properties / startDate / descriptionPrevious 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." - added
Input schema / properties / startDate / minimumAdded value: +1
- Changed
growsurf_get_campaign_emails2 fields changed- changed
Output schema / descriptionPrevious 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." - added
Output schema / properties / settings / propertiesAdded 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" + } +}
- Changed
growsurf_get_campaign_installation1 field changed- changed
Output schema / properties / allowedUrls / descriptionPrevious 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."
- Changed
growsurf_get_participant_analytics5 fields changed- added
Input schema / allOfAdded value: +[ + { + "if": { + "required": [ + "startDate" + ] + }, + "then": { + "required": [ + "endDate" + ] + } + }, + { + "if": { + "required": [ + "endDate" + ] + }, + "then": { + "required": [ + "startDate" + ] + } + } +] - changed
Input schema / properties / endDate / descriptionPrevious 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." - added
Input schema / properties / endDate / minimumAdded value: +1 - changed
Input schema / properties / startDate / descriptionPrevious 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." - added
Input schema / properties / startDate / minimumAdded value: +1
- Changed
growsurf_update_campaign_emails1 field changed- added
Input schema / properties / fields / propertiesAdded 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" + } +}
- Changed
growsurf_update_campaign_installation1 field changed- changed
Input schema / properties / fields / properties / allowedUrls / descriptionPrevious 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."
- Changed
growsurf_update_campaign_reward6 fields changed- changed
Input schema / properties / couponCode / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Input schema / properties / imageUrl / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Input schema / properties / nextMilestonePrefix / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Input schema / properties / nextMilestoneSuffix / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Input schema / properties / referralCouponCode / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Input schema / properties / referralDescription / typePrevious value: -"string"New value: +[ + "string", + "null" +]
4 tool updates
v0.19.7- Changed
growsurf_get_campaign_installation1 field changed- added
Output schema / properties / instructionSelectionsAdded 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" +}
- Changed
growsurf_get_participant_payout_destination3 fields changed- changed
Output schema / properties / activeProvider / descriptionPrevious 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`." - changed
Output schema / properties / destinations / items / properties / provider / descriptionPrevious 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`." - changed
Output schema / properties / enabledProviders / descriptionPrevious 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`."
- Changed
growsurf_request_participant_payout_destination_confirmation2 fields changed- changed
Input schema / properties / provider / enumPrevious value: -[ - "PAYPAL", - "WISECOM" -]New value: +[ + "PAYPAL", + "VENMO", + "WISECOM" +] - changed
Output schema / properties / provider / descriptionPrevious 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`."
- Changed
growsurf_update_campaign_installation2 fields changed- changed
Input schema / properties / fields / descriptionPrevious 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." - added
Input schema / properties / fields / properties / instructionSelectionsAdded 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" +}
2 tool updates
v0.19.1- Changed
growsurf_get_campaign_design1 field changed- added
Output schema / properties / trafficInsightsAdded 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" +}
- Changed
growsurf_list_campaign_rewards1 field changed- changed
Output schema / properties / rewards / descriptionPrevious 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."
3 tool updates
v0.18.1- Changed
growsurf_create_campaign2 fields changed- changed
Input schema / properties / goal / descriptionPrevious 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." - changed
Input schema / properties / goal / enumPrevious 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" +]
- Changed
growsurf_get_campaign_design2 fields changed- added
Output schema / properties / theme / properties / widgetAdded 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" +} - added
Output schema / properties / widgetAdded 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" +}
- Changed
growsurf_get_participant1 field changed- added
Output schema / properties / leadCountAdded value: +{ + "description": "Pending referrals that have not converted yet.", + "type": "integer" +}
1 tool update
v0.16.0- Changed
growsurf_list_participants1 field changed- added
Input schema / properties / metadataAdded 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" +}
1 tool update
v0.15.1- Changed
growsurf_bulk_delete_participants2 fields changed- changed
Output schema / descriptionPrevious 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." - added
Output schema / properties / analyticsErasureAdded 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" +}
27 tool updates
v0.14.0- Changed
growsurf_create_campaign2 fields changed- added
Input schema / properties / goalAdded 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" +} - added
Input schema / properties / rewards / descriptionAdded 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."
- Changed
growsurf_create_campaign_reward5 fields changed- added
Input schema / properties / commissionStructure / allOfAdded value: +[ + { + "if": { + "properties": { + "event": { + "enum": [ + "CLICK", + "LEAD" + ] + } + }, + "required": [ + "event" + ] + }, + "then": { + "properties": { + "amount": { + "minimum": 1, + "type": "integer" + }, + "type": { + "enum": [ + "FIXED" + ] + } + }, + "required": [ + "amount" + ] + } + } +] - changed
Input schema / properties / commissionStructure / descriptionPrevious 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." - added
Input schema / properties / commissionStructure / properties / amount / minimumAdded value: +1 - added
Input schema / properties / commissionStructure / properties / event / descriptionAdded value: +"The affiliate event that earns the commission. `CLICK` and `LEAD` must use `FIXED`." - added
Input schema / properties / eventAdded 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" +}
- Added
growsurf_create_program_resource - Added
growsurf_delete_program_resource - Changed
growsurf_get_campaign1 field changed- added
Output schema / properties / rewardEvidenceAdded 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" +}
- Added
growsurf_get_campaign_activation_analytics - Changed
growsurf_get_campaign_analytics4 fields changed- changed
Input schema / properties / include / descriptionPrevious 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." - added
Input schema / properties / platformAdded value: +{ + "description": "Client-platform filter for engagement. Defaults to `ALL`.", + "enum": [ + "ALL", + "WEB", + "IOS", + "ANDROID" + ], + "type": "string" +} - added
Input schema / properties / timezoneAdded value: +{ + "description": "IANA timezone for engagement interval and distinct-day calculations. Used with `include=engagement`.", + "type": "string" +} - added
Output schema / properties / engagementAdded 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" +}
- Changed
growsurf_get_campaign_design5 fields changed- added
Output schema / properties / participantAvatarStyleAdded 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" +} - changed
Output schema / properties / referredExperience / descriptionPrevious 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." - added
Output schema / properties / referredExperience / propertiesAdded 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" + ] + } +} - added
Output schema / properties / resourcesAdded 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" +} - added
Output schema / properties / theme / propertiesAdded 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" + } +}
- Changed
growsurf_get_campaign_emails1 field changed- added
Output schema / properties / offerClaimedAdded 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" +}
- Changed
growsurf_get_campaign_options2 fields changed- changed
Output schema / properties / autoFulfillRewards / descriptionPrevious 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." - added
Output schema / properties / rewardEvidenceAdded 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" +}
- Changed
growsurf_get_integration_connect_link5 fields changed- changed
Input schema / properties / integration / enumPrevious 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" +] - added
Output schema / properties / autoDisabledAdded value: +{ + "description": "Whether GrowSurf switched the integration off after repeated delivery failures. Present only when `programVerified` is `true`.", + "type": "boolean" +} - added
Output schema / properties / connectedAdded value: +{ + "description": "Whether the program has stored credentials for this integration. Present only when `programVerified` is `true`.", + "type": "boolean" +} - added
Output schema / properties / enabledAdded value: +{ + "description": "Whether the integration is switched on and currently working. Present only when `programVerified` is `true`.", + "type": "boolean" +} - added
Output schema / properties / programVerifiedAdded 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" +}
- Changed
growsurf_get_participant5 fields changed- added
Output schema / properties / rewardEvidenceAdded 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" +} - changed
Output schema / properties / rewards / items / properties / fulfilledAt / descriptionPrevious 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." - changed
Output schema / properties / rewards / items / properties / isFulfilled / descriptionPrevious value: -"`true` once the reward has been fulfilled."New value: +"`true` once the reward is marked fulfilled. Confirm actual delivery through fulfillment records." - changed
Output schema / properties / rewards / items / properties / status / descriptionPrevious 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." - changed
Output schema / properties / rewards / items / properties / status / enumPrevious value: -[ - "PENDING", - "FULFILLED" -]New value: +[ + "PENDING", + "FULFILLED", + "CANCELLED" +]
- Changed
growsurf_get_participant_analytics9 fields changed- added
Input schema / properties / days / descriptionAdded value: +"Number of days for optional `series` and `email` analytics. Does not filter the all-time base response." - changed
Input schema / properties / endDate / descriptionPrevious value: -"End of the timeframe, Unix timestamp in ms."New value: +"End of the optional-data timeframe, Unix timestamp in ms. Use with `startDate`." - changed
Input schema / properties / include / descriptionPrevious 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." - changed
Input schema / properties / startDate / descriptionPrevious 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`." - added
Output schema / properties / activationAdded 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" +} - changed
Output schema / properties / analytics / descriptionPrevious value: -"Participant analytics totals."New value: +"All-time participant analytics totals. Date-window parameters do not filter these fields." - changed
Output schema / properties / analytics / properties / leads / descriptionPrevious value: -"Pending referral credits."New value: +"Current pending referral credits." - added
Output schema / properties / series / items / properties / portalViewsAdded value: +{ + "description": "Covered signed-in portal views, or `null` outside known coverage.", + "type": [ + "integer", + "null" + ] +} - added
Output schema / properties / series / items / properties / shareActionsAdded value: +{ + "description": "Covered accepted share actions, or `null` outside known coverage.", + "type": [ + "integer", + "null" + ] +}
- Changed
growsurf_list_campaign_rewards2 fields changed- added
Output schema / properties / rewardEvidenceAdded 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" +} - added
Output schema / properties / rewards / items / properties / eventAdded 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" + ] +}
- Added
growsurf_list_integrations - Changed
growsurf_list_participants1 field changed- added
Output schema / properties / rewardEvidenceAdded 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" +}
- Added
growsurf_list_program_resources - Added
growsurf_prepare_program_resource_file - Added
growsurf_program_design_advisor - Changed
growsurf_record_sale3 fields changed- changed
Input schema / allOfPrevious 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" + ] + } + } + } +] - added
Input schema / properties / paymentProviderAdded 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" +} - added
Input schema / properties / testModeAdded value: +{ + "description": "Required with `paymentProvider`: `true` for test or `false` for live. Otherwise omit.", + "type": "boolean" +}
- Changed
growsurf_refund_transaction6 fields changed- changed
Input schema / allOfPrevious 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" + ] + } + } + } +] - added
Input schema / properties / paymentProviderAdded 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" +} - added
Input schema / properties / refundAmount / descriptionAdded 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." - added
Input schema / properties / refundHistoryCompleteAdded 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" +} - added
Input schema / properties / refundId / descriptionAdded 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." - added
Input schema / properties / testModeAdded value: +{ + "description": "Original payment mode: `true` for test or `false` for live. Requires `paymentProvider`.", + "type": "boolean" +}
- Added
growsurf_troubleshoot_referral_tracking - Changed
growsurf_update_campaign1 field changed- added
Input schema / anyOfAdded value: +[ + { + "required": [ + "name" + ] + }, + { + "required": [ + "companyName" + ] + }, + { + "required": [ + "companyLogoImageUrl" + ] + }, + { + "required": [ + "status" + ] + } +]
- Changed
growsurf_update_campaign_installation1 field changed- added
Input schema / properties / replaceExistingShareUrlAdded 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" +}
- Changed
growsurf_update_campaign_reward5 fields changed- added
Input schema / properties / commissionStructure / allOfAdded value: +[ + { + "if": { + "properties": { + "event": { + "enum": [ + "CLICK", + "LEAD" + ] + } + }, + "required": [ + "event" + ] + }, + "then": { + "properties": { + "amount": { + "minimum": 1, + "type": "integer" + }, + "type": { + "enum": [ + "FIXED" + ] + } + }, + "required": [ + "amount" + ] + } + } +] - changed
Input schema / properties / commissionStructure / descriptionPrevious 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." - added
Input schema / properties / commissionStructure / properties / amount / minimumAdded value: +1 - added
Input schema / properties / commissionStructure / properties / event / descriptionAdded value: +"The affiliate event that earns the commission. `CLICK` and `LEAD` must use `FIXED`." - added
Input schema / properties / eventAdded 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" +}
- Changed
growsurf_update_campaign_webhook1 field changed- added
Input schema / anyOfAdded value: +[ + { + "required": [ + "payloadUrl" + ] + }, + { + "required": [ + "events" + ] + }, + { + "required": [ + "secret" + ] + }, + { + "required": [ + "isEnabled" + ] + } +]
- Added
growsurf_update_program_resource
54 tool updates
v0.12.2- First observed
growsurf_add_participant - First observed
growsurf_agent_program_creation_eval - First observed
growsurf_api_library_snippets - First observed
growsurf_bulk_delete_participants - First observed
growsurf_cancel_delayed_referral - First observed
growsurf_capture_referral_flow_screenshots - First observed
growsurf_client_snippets - First observed
growsurf_clone_campaign - First observed
growsurf_create_account - First observed
growsurf_create_campaign - First observed
growsurf_create_campaign_reward - First observed
growsurf_create_campaign_webhook - First observed
growsurf_create_mobile_participant_token - First observed
growsurf_delete_campaign_reward - First observed
growsurf_delete_campaign_webhook - First observed
growsurf_email_participant - First observed
growsurf_embeddable_element_snippet - First observed
growsurf_get_campaign - First observed
growsurf_get_campaign_analytics - First observed
growsurf_get_campaign_design - First observed
growsurf_get_campaign_emails - First observed
growsurf_get_campaign_installation - First observed
growsurf_get_campaign_options - First observed
growsurf_get_integration_connect_link - First observed
growsurf_get_participant - First observed
growsurf_get_participant_activity_logs - First observed
growsurf_get_participant_analytics - First observed
growsurf_get_participant_payout_destination - First observed
growsurf_get_team - First observed
growsurf_grsf_config_snippet - First observed
growsurf_integration_guide - First observed
growsurf_list_campaign_rewards - First observed
growsurf_list_campaign_webhooks - First observed
growsurf_list_campaigns - First observed
growsurf_list_participants - First observed
growsurf_mobile_sdk_guide - First observed
growsurf_participant_auth_hash - First observed
growsurf_record_sale - First observed
growsurf_refund_transaction - First observed
growsurf_request_participant_payout_destination_confirmation - First observed
growsurf_request_team_verification - First observed
growsurf_resend_team_owner_verification_email - First observed
growsurf_test_campaign_webhook - First observed
growsurf_trigger_referral - First observed
growsurf_update_campaign - First observed
growsurf_update_campaign_design - First observed
growsurf_update_campaign_emails - First observed
growsurf_update_campaign_installation - First observed
growsurf_update_campaign_options - First observed
growsurf_update_campaign_reward - First observed
growsurf_update_campaign_webhook - First observed
growsurf_update_participant - First observed
growsurf_update_team - First observed
growsurf_webhook_normalize
TDQS
Scored across 63 tools
Most tools have clearly distinct resource+action targets (campaign config tabs, rewards, resources, webhooks, participants), and descriptions proactively cross-reference each other to steer selection (e.g. snippet vs guide vs SDK tools). A few boundaries blur across the six code/guidance-generating tools and the three analytics tools, but the descriptions resolve them well.
All 63 tools share a consistent `growsurf_` prefix in snake_case, and the vast majority follow a verb_noun pattern (get_campaign, create_campaign_reward, delete_campaign_webhook). A minority deviate into noun phrases (webhook_normalize, integration_guide, participant_auth_hash, grsf_config_snippet), which is a minor inconsistency but still readable.
63 tools constitutes a very large surface, well beyond the typical 3-15 range, forcing an agent to navigate many near-sibling get/update pairs and niche helpers. The breadth stems from a genuinely large platform (campaigns, config tabs, rewards, resources, webhooks, participants, analytics, integrations, snippets, team), but the sheer count is heavy and hard to hold in context.
The surface provides near-complete lifecycle coverage: full CRUD for campaigns, campaign rewards, program resources, and webhooks, plus participant add/get/update, bulk delete, activity logs, referral triggering, sale/refund recording, payout handling, analytics, and team management. Config sub-resources (design, emails, options, installation) each have matching read/update tools, leaving no obvious dead ends.
Maintenance
Related MCP Connectors
Build, launch and manage referral, affiliate and loyalty programs with RefRef from your AI agent.
- mcp-serverOAuthcom.make
Give your AI agents the tools to build, manage, and run automation workflows.
Marketing data and actions for AI agents: GA4, Search Console, ads, social, SEO and WordPress.
Run B2B outreach from your AI agent: 250+ tools for campaigns, leads, LinkedIn and email workflows.
Related MCP Servers
- FlicenseAqualityCmaintenanceEnables 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.201-
- AlicenseAqualityDmaintenanceEnables 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.740 npmMIT
- FlicenseAqualityDmaintenanceEnables AI agents to automate sales outreach, research leads, and manage campaigns directly in OutreachPilot via natural language commands.31-
- AlicenseNot gradedqualityDmaintenanceEnables 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