Skip to main content
Glama
growsurf

GrowSurf MCP Server

Official

GrowSurf MCP Server

npm version npm downloads license node

Официальный интерфейс командной строки (CLI) GrowSurf и сервер Model Context Protocol (MCP) с открытым исходным кодом для внедрения реферальных и партнёрских программ GrowSurf с пошаговыми инструкциями и безопасными обёртками REST API.

Подключите его к ИИ-агенту, и на простом языке агент сможет создать реферальную или партнёрскую программу, настроить вознаграждения, установить отслеживание, добавлять и управлять участниками, а также читать аналитику — всё на основе REST API GrowSurf.

Для кого это

Этот MCP-сервер предназначен для:

  • Разработчиков, использующих инструменты, совместимые с MCP (Claude Code, Codex, Cursor, Copilot и другие MCP-клиенты)

  • Команд, которым нужны управляемые интеграции GrowSurf с помощью ИИ

Этот MCP-сервер НЕ предназначен для:

  • Пользователей, работающих только в браузере и желающих локальную установку stdio. ChatGPT web, Claude.ai и Claude Desktop не запускают локальный MCP-сервер, но все три подключаются к GrowSurf через размещённый удалённый коннектор по адресу https://mcp.growsurf.com. Полный список клиентов и настройку см. на https://docs.growsurf.com/build-with-ai#mcp.

Related MCP server: agentfuse-mcp

Что вы получаете

  • Управляемая интеграция:

    • Установка универсального кода

    • Рекомендации по внедрению нативных iOS/Android SDK

    • Рекомендации по нативному окну GrowSurf

    • Поток регистрации

    • Поток квалифицирующего действия

    • Отслеживание продаж / транзакций партнёров

    • Вебхуки

  • Рецепты для агентов:

    • MCP-промпты для создания реферальных программ, создания партнёрских программ, встраивания виджета, перечисления и получения программ и участников, настройки вознаграждений, подключения вебхуков и чтения аналитики

    • Устанавливаемый набор навыков агента в skills/growsurf-agent-toolkit

    • Направление на проверку стартового дизайна, писем, параметров, установки, вознаграждений и содержимого окна GrowSurf перед внесением изменений

    • Промпты для одноразового создания программы и проверки приёмки для стартового содержимого и проверки конфигурации

  • Обёртки REST API для счастливого пути:

    • Создание аккаунта и получение API-ключа без существующих учётных данных

    • Чтение и переименование привязанной команды, запрос верификации команды и повторная отправка письма с подтверждением владельцу команды

    • Перечисление и получение кампаний

    • Получение аналитики кампании (итоги, необязательные временные ряды по периодам, метрики электронной почты, итоги за предыдущий период, счётчики статусов и коэффициенты)

    • Создание, обновление и клонирование программ (кампаний)

    • Перечисление, создание, обновление и удаление вознаграждений кампании

    • Получение/обновление конфигурации дизайна, писем, параметров и установки

    • Создание временных предварительных снимков экрана GrowSurf, когда пользователь явно запрашивает визуальное подтверждение

    • Перечисление, создание, обновление, удаление и тестирование вебхуков программы

    • Перечисление, получение и добавление участников

    • Обновление участника, отправка письма участнику и получение аналитики и журналов активности участника

    • Начисление реферального кредита (для реферальных программ) с возможностью отложенного начисления (1–90 дней)

    • Отмена ожидающего отложенного реферального триггера (для реферальных программ)

    • Запись продажи/транзакции партнёра (для партнёрских программ)

    • Создание мобильных токенов участников для вошедших в систему пользователей нативных приложений

  • Официальные фрагменты библиотеки API:

    • TypeScript

    • Python

    • PHP

    • Ruby

    • Java

  • Помощники:

    • Вычисление HMAC-хэша для автоматической аутентификации участника

    • Нормализация полезных нагрузок вебхуков

    • Генерация ключей идемпотентности с максимальным усилием для дедупликации вебхуков

Требования

  • Node.js 22+

  • Аккаунт GrowSurf для размещённого OAuth

  • API-ключ GrowSurf для локальной настройки stdio или ручной удалённой настройки с API-ключом. Ключ с ограниченными правами подойдёт, если он имеет доступ к инструментам и программам, которые агент должен использовать.

  • Идентификатор кампании (программы) для инструментов, ограниченных кампанией. Установите GROWSURF_CAMPAIGN_ID по умолчанию, передайте аргумент campaignId для конкретной программы или вызовите growsurf_list_campaigns, чтобы найти доступные программы. Для новой программы передайте id, возвращённый growsurf_create_campaign, в другие инструменты.

  • Статические инструменты с руководствами и фрагментами могут работать без учётных данных

  • Исключение: growsurf_create_account не требует API-ключа. Он создаёт новый аккаунт и возвращает API-ключ. Инструментам уровня команды не нужен идентификатор кампании.

  • Каждый перечисленный инструмент публикует стандартные подсказки безопасности MCP: только чтение, деструктивные, идемпотентные и открытые. Ограниченные бизнес-действия остаются доступными; ротация API-ключей намеренно не является инструментом MCP. Вращайте ключи в настройках GrowSurf или через прямой REST/SDK-клиент.

Официальный CLI

Пакет npm устанавливает команду growsurf-mcp. Запустите её без глобальной установки:

npx -y @growsurfteam/growsurf-mcp

CLI запускает локальный stdio-сервер MCP GrowSurf. Установите GROWSURF_API_KEY для действий, использующих API, и GROWSURF_CAMPAIGN_ID для программы по умолчанию. Публичные ресурсы для разработчиков и статические руководства по интеграции работают без учётных данных.

Проверьте установленную команду, не запуская stdio-сервер:

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

Поддерживаемые MCP-хосты

Рекомендуемый путь — размещённая конечная точка OAuth GrowSurf по адресу https://mcp.growsurf.com, если ваш хост поддерживает удалённый Streamable HTTP с OAuth. Используйте локальный сервер npx, если вашему хосту нужен процесс stdio или ручная настройка API-ключа. Ещё нет аккаунта GrowSurf? Агент может подключиться к размещённой конечной точке онбординга https://mcp.growsurf.com/onboard без учётных данных и вызвать growsurf_create_account для регистрации.

Сервер MCP GrowSurf работает с любым хостом, совместимым с MCP. Примеры ниже охватывают несколько хостов на основе конфигурации и CLI. Полный актуальный список поддерживаемых клиентов (включая ChatGPT web, Claude.ai, Claude Desktop, GitHub Copilot, Gemini CLI, Devin Desktop и Cline) с пошаговой настройкой см. на https://docs.growsurf.com/build-with-ai#mcp.

  • Cursor

  • Claude Code (на основе CLI)

  • Antigravity

  • Codex (на основе CLI)

Cursor

  1. Откройте или создайте глобальную MCP-конфигурацию Cursor в ~/.cursor/mcp.json.

  2. Добавьте сервер с именем growsurf с размещённой конечной точкой OAuth:

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

Для локального stdio вместо этого используйте:

{
  "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)

Откройте терминал и подключите Claude Code к размещённой конечной точке OAuth:

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

Для локального stdio вместо этого установите сервер непосредственно в Claude Code:

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

Antigravity

  1. Откройте Antigravity.

  2. Нажмите меню … на панели справа и выберите MCP Servers.

  3. Нажмите Manage MCP Servers > View raw config.

  4. Рекомендуется: в файле mcp_config.json добавьте размещённую конечную точку OAuth:

{
  "mcpServers": {
    "growsurf": {
      "serverUrl": "https://mcp.growsurf.com"
    }
  }
}
  1. Сохраните конфигурацию, откройте Settings > Customizations и выберите Authenticate для GrowSurf.

Для локального stdio вместо этого используйте:

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

Codex

Рекомендуется: подключите Codex к размещённой конечной точке OAuth:

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

Или создайте или отредактируйте ~/.codex/config.toml:

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

Для локального stdio вместо этого добавьте следующее:

[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"

Или настройте локальный stdio из CLI:

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

Конфигурация

Установите следующие переменные окружения при запуске MCP-сервера:

  • GROWSURF_API_KEY (необязательно для запуска; требуется для инструментов, вызывающих API. Используйте ключ с областями доступа и доступом к программам, которые нужны этим инструментам)

  • GROWSURF_CAMPAIGN_ID (необязательно; программа по умолчанию для инструментов, ограниченных кампанией. Аргумент campaignId инструмента переопределяет его, поэтому один сервер может работать с любыми вашими программами)

  • GROWSURF_API_BASE_URL (необязательно; по умолчанию https://api.growsurf.com/v2. Полезно для локальных или размещённых MCP-шлюзов, которые должны вызывать другой источник API GrowSurf)

  • GROWSURF_PARTICIPANT_AUTH_SECRET (необязательно; используется помощником хэширования)

  • GROWSURF_WEBHOOK_TOKEN (необязательно; используется для вашей собственной схемы токенов URL вебхуков)

Запуск с npx

После публикации этого пакета клиенты могут запустить:

npx @growsurfteam/growsurf-mcp

Для локальной разработки в этом репозитории:

npm install
npm run build
node dist/cli.js

Инструменты MCP

Каждый инструмент объявляет схему вывода MCP и возвращает structuredContent, поэтому хосты знают форму результата каждого инструмента. Инструменты REST возвращают ответ API (плюс текстовый блок JSON для старых клиентов); инструменты с руководствами и фрагментами возвращают свой документ Markdown в поле markdown.

Управляемая интеграция

  • growsurf_integration_guide Пошаговые рекомендации по внедрению реферальной или партнёрской программы GrowSurf.

  • growsurf_mobile_sdk_guide Рекомендации по нативным iOS/Android SDK для атрибуции, shareUrl, trackShare и нативного окна GrowSurf.

  • growsurf_api_library_snippets Официальные фрагменты библиотеки REST API для TypeScript, Python, PHP, Ruby и Java.

  • growsurf_get_integration_connect_link Получите ссылку на панель управления, которая открывает панель подключения конкретной интеграции (Stripe, PayPal, Tango Card, Mailchimp и многие другие). Передайте её пользователю, когда он захочет подключить интеграцию. Подключение происходит в панели управления, а не через API.

Фрагменты для клиента и интерфейса

  • growsurf_client_snippets Примеры JavaScript SDK, окна GrowSurf и встраиваемых элементов. Включает напоминание об использовании рабочего процесса дизайна интерфейса при размещении или стилизации встраиваемого интерфейса.

  • growsurf_embeddable_element_snippet HTML-фрагмент для конкретного встраиваемого элемента GrowSurf.

  • growsurf_grsf_config_snippet Фрагмент <head> для настройки window.grsfConfig и автоматической аутентификации участника.

Онбординг аккаунта

  • growsurf_create_account Создайте аккаунт GrowSurf и получите API-ключ. Это единственный инструмент, который не требует GROWSURF_API_KEY. Возвращённый ключ показывается один раз и блокируется (403 EMAIL_NOT_VERIFIED_ERROR), пока владелец не подтвердит свою электронную почту. Ключ ротируется при первом входе владельца в панель управления. Создание аккаунта означает согласие от имени владельца аккаунта с Условиями предоставления услуг и Политикой конфиденциальности GrowSurf.

Команда

  • growsurf_get_team Получите команду, привязанную к API-ключу или OAuth-подключению, включая состояние верификации GrowSurf.

  • growsurf_update_team Обновите отображаемое имя привязанной команды.

  • growsurf_request_team_verification Запросите у GrowSurf верификацию привязанной команды, которая требуется перед отправкой писем участникам программы.

  • growsurf_resend_team_owner_verification_email Повторно отправьте письмо с подтверждением владельцу привязанной команды, не раскрывая его адрес электронной почты.

API и отслеживание

  • growsurf_get_campaign Получить конфигурацию кампании.

  • growsurf_list_campaigns Вывести список программ, доступных для учетных данных. Используйте этот инструмент, чтобы найти campaignId перед вызовом инструментов, ограниченных кампанией.

  • growsurf_get_campaign_analytics Получить аналитику программы с опциональными данными за период series, сравнением, статусом, ставкой, а также данными о доставке писем и вовлеченности через include=email.

  • growsurf_create_campaign Создать новую программу (кампанию) со стартовым контентом, соответствующим типу, и опциональными встроенными вознаграждениями (требуется только GROWSURF_API_KEY, не GROWSURF_CAMPAIGN_ID). Проверьте сгенерированный контент во вкладках Design, Emails, Options, Installation, вознаграждения и GrowSurf Window перед внесением изменений.

  • growsurf_agent_program_creation_eval Сгенерировать одноразовые eval-промпты для создания программы и проверки приемки: стартовый контент, консервативные вознаграждения, проверка конфигурации, доказательство установки на фронтенде и чистый публичный текст.

  • growsurf_update_campaign Обновить идентичность и жизненный цикл программы: название, брендинг компании и статус (изменяются только те поля, которые вы отправляете).

  • growsurf_clone_campaign Клонировать программу в новую программу со статусом DRAFT (интеграции и учетные данные не копируются).

  • growsurf_list_campaign_rewards Вывести список настроенных вознаграждений программы.

  • growsurf_create_campaign_reward Создать вознаграждение кампании.

  • growsurf_update_campaign_reward Обновить вознаграждение кампании по его ключу вознаграждения.

  • growsurf_delete_campaign_reward Удалить вознаграждение кампании по его ключу вознаграждения.

  • growsurf_get_campaign_design / growsurf_update_campaign_design Прочитать или изменить конфигурацию дизайна, включая вкладку Design в редакторе программы и текст страницы подтверждения способа выплаты.

  • growsurf_get_campaign_emails / growsurf_update_campaign_emails Прочитать или изменить конфигурацию вкладки Emails в редакторе программы.

  • growsurf_get_campaign_options / growsurf_update_campaign_options Прочитать или изменить конфигурацию вкладки Options в редакторе программы.

  • growsurf_get_campaign_installation / growsurf_update_campaign_installation Прочитать или изменить конфигурацию вкладки Installation в редакторе программы.

  • growsurf_capture_referral_flow_screenshots Сделать временные скриншоты предпросмотра GrowSurf для текущей программы после того, как пользователь явно запросит визуальное подтверждение. Этот инструмент возвращает контролируемый опыт реферера и приглашенного друга; для подтверждения установки на сайте пользователя используйте автоматизацию браузера.

  • growsurf_list_campaign_webhooks Вывести список вебхуков программы (секреты никогда не возвращаются).

  • growsurf_create_campaign_webhook Добавить вебхук в программу (с событиями и секретом подписи только для записи).

  • growsurf_update_campaign_webhook Обновить вебхук по id (primary для основного вебхука программы).

  • growsurf_delete_campaign_webhook Удалить вебхук по id.

  • growsurf_test_campaign_webhook Отправить живое тестовое событие на вебхук, используя его сохраненные URL и секрет.

  • growsurf_add_participant Добавить участника (или приглашенного участника) при регистрации.

  • growsurf_list_participants Вывести список участников текущей программы с пагинацией по nextId. Используйте этот инструмент, чтобы найти ID участника перед вызовом инструментов, ограниченных участником.

  • growsurf_get_participant Получить одного участника по GrowSurf ID участника или адресу электронной почты.

  • growsurf_update_participant Обновить участника по ID или email (включая внутренние notes).

  • growsurf_bulk_delete_participants Навсегда удалить до 200 участников (по ID и/или email, смешанные списки допускаются) одним запросом, с результатами DELETED/NOT_FOUND/DUPLICATE/ERROR по каждой строке. Необратимо — удаляет реферальные ссылки участников, вознаграждения, комиссии и записи о выплатах.

  • growsurf_email_participant Отправить письмо участнику, используя настроенный шаблон или свободную тему/текст.

  • growsurf_get_participant_analytics Получить данные одного участника: вовлеченность, рейтинг, шеринг, доход от партнерской программы, комиссию, выплаты и опциональные email-метрики. Используйте include=series, include=email или оба значения через запятую.

  • growsurf_get_participant_activity_logs Вывести список журналов активности участника (пагинация по offset/limit).

  • growsurf_trigger_referral Активировать реферальную ссылку (только для реферальных программ). Опционально передайте delayInDays (1-90), чтобы удержать начисление на N дней перед выдачей (например, для покрытия периода возврата).

  • growsurf_cancel_delayed_referral Отменить ожидающую отложенную активацию реферальной ссылки до истечения задержки (например, при возврате/отмене).

  • growsurf_get_participant_payout_destination Получить статус способа выплаты участника по каждому провайдеру, включенному для программы (PayPal и/или Wise): статус по провайдеру, подтвержденный email для выплат, юридический тип получателя и причину исправления.

  • growsurf_request_participant_payout_destination_confirmation Попросить участника подтвердить способ выплаты для провайдера — отправить ему одноразовую ссылку для подтверждения (подтвердить может только сам участник).

  • growsurf_record_sale Записать продажи или транзакции партнерской программы (только для партнерских программ).

  • growsurf_refund_transaction Записать корректировку (возврат, частичный возврат или чарджбэк) по записанной транзакции; отменяет или корректирует комиссию реферера (только для партнерских программ). Обратная операция к growsurf_record_sale.

  • growsurf_create_mobile_participant_token Создать или получить участника, затем создать токен мобильного SDK с областью участника для авторизованного мобильного пользователя.

Вспомогательные инструменты

  • growsurf_participant_auth_hash Сгенерировать HMAC-хеши автоматической аутентификации участника (для автоматической аутентификации участников).

  • growsurf_webhook_normalize Нормализовать полезные нагрузки вебхуков и сгенерировать ключи идемпотентности (для дедупликации доставок вебхуков).

Вебхуки

Вебхуки GrowSurf уведомляют ваш сервер о важных событиях реферальной или партнерской программы, например, когда создаются новые объекты, такие как участники, реферальные ссылки, вознаграждения или транзакции. Вот распространенные сценарии использования:

  • Автоматическое выполнение вознаграждений

  • Поддержание внутренних систем баллов или кредитов

  • Синхронизация данных об участниках и реферальных ссылках в вашу базу данных

Обработка дублирующихся доставок

Обработчики вебхуков должны быть идемпотентными, потому что одно и то же событие может прийти более одного раза. Сохраняйте ключ идемпотентности перед любыми изменениями в вашей системе.

Безопасность вебхуков и идемпотентность

GrowSurf подписывает доставки вебхуков, когда у вебхука настроен secret: каждая доставка включает HMAC-заголовок GrowSurf-Signature, вычисленный с этим секретом (секрет доступен только для записи и никогда не возвращается). Для безопасного использования вебхуков мы рекомендуем следующее:

  • Установите secret на вебхуке и проверяйте заголовок GrowSurf-Signature при получении

  • Проверяйте форму полезной нагрузки и ожидаемый тип события

  • Дедуплицируйте события вебхуков с помощью ключа идемпотентности, потому что одно и то же событие может прийти более одного раза

MCP-сервер GrowSurf предоставляет вспомогательный инструмент (growsurf_webhook_normalize), который нормализует полезные нагрузки вебхуков и генерирует ключ идемпотентности по мере возможности, чтобы упростить безопасную обработку вебхуков.

Разработка и тестирование

npm run dev
npm test

Дополнительные ресурсы

Ознакомьтесь с документацией для разработчиков по следующим ссылкам:

MCP-сервер GrowSurf помогает клиентам GrowSurf быстро внедрять реферальные и партнерские программы.

Available Tools

63 tools
growsurf_add_participantAdd ParticipantAInspect

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

ParametersJSON Schema
NameRequiredDescriptionDefault
emailYes
languageNoThe 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`.
lastNameNo
metadataNo
firstNameNo
ipAddressNo
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
referredByNo
fingerprintNo
isAffiliateNoAffiliate programs only. Controls affiliate enrollment for a new participant. `true` enrolls the participant with `affiliateStatus: APPROVED`; `false` creates a non-affiliate without `affiliateStatus`. Existing participants are returned unchanged.
referralStatusNo
mobileInstanceIdNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness3/5

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

An output schema exists, so return values need not be 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.

Parameters3/5

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.

Purpose4/5

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

The description opens with a specific verb+resource 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.

Usage Guidelines4/5

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 ChecksA
Read-onlyIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
programTypeNoboth
includeOneShotPromptsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint and 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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters2/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 SnippetsA
Read-onlyIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
emailNo
languageNoall
workflowNoall
campaignIdNo
referredByNo
participantIdOrEmailNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already declare 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.

Conciseness5/5

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.

Completeness4/5

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

An output schema exists, so return values need no explanation, and annotations cover 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.

Parameters3/5

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

Schema description coverage is 0%, so the description must 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.

Purpose5/5

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.

Usage Guidelines5/5

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 ParticipantsA
DestructiveIdempotent
Inspect

Bulk delete participants from your GrowSurf program in one request. DESTRUCTIVE: deletion is permanent, cannot be undone, and removes the participants' referrals, rewards, commissions, and payout records. Each entry in participants is a GrowSurf participant ID or an email address (mixed lists are allowed), up to 200 entries per request — chunk larger lists across multiple calls. Returns a summary (total, deletedCount, notFoundCount, duplicateCount, errorCount) plus per-row results in request order, each with status DELETED, NOT_FOUND, DUPLICATE (resolves to the same participant as an earlier entry), or ERROR — both 200 and 202 responses can include NOT_FOUND or ERROR rows, and the summary reports these outcomes. A 202 response includes analyticsErasure when analytics erasure is pending. DELETED means participant cleanup completed; reports can retain the participant until analytics erasure completes. Repeating successful rows does not finish analytics erasure. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
participantsYesGrowSurf participant IDs and/or email addresses to delete (1-200 entries; mixed lists allowed).

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultsNoOne entry per submitted identifier, in request order.
summaryNoCounts across all submitted entries.
analyticsErasureNoAnalytics erasure is pending. Reports can retain removed participants until erasure completes. Do not repeat successful deletions.

TDQS

A4.2/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 ReferralA
DestructiveIdempotent
Inspect

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

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

Output Schema

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

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, 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.

Conciseness4/5

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.

Completeness3/5

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.

Parameters2/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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.

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

Output Schema

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

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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

Schema description coverage is 100% for the single campaignId parameter, so the baseline is 3. The description's 'Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID' 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.

Purpose5/5

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.

Usage Guidelines4/5

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 SnippetsA
Read-onlyIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
programTypeNoboth
singlePageAppNo
referralTriggerNosignup_plus_qualifying_action
includeUnreadBadgeNo
includeGrowSurfWindowNo
participantAuthEnabledNo
includeEmbeddableElementsNo
includeEventSubscriptionsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and 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.

Conciseness5/5

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.

Completeness4/5

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

An output schema exists, so return values need no explanation, and the description covers 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.

Parameters2/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

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

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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

An output schema exists, so return values need not be described, 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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 AccountA
Destructive
Inspect

Create a brand-new GrowSurf account and return an API key. Requires the authorized owner's explicit approval of account creation and acceptance of GrowSurf's Terms of Service (https://growsurf.com/terms) and Privacy Policy (https://growsurf.com/privacy). This is the only tool that does not require GROWSURF_API_KEY. The account starts a 14-day Business trial without a credit card. The new key is returned once in apiKey, cannot be recovered through this API, and requires durable secret storage. The hosted OAuth connector is an alternative that retains credentials with the connection. The key stays locked until the owner verifies their email; program and resource endpoints return 403 with EMAIL_NOT_VERIFIED_ERROR before verification. Verification unlocks the same key. The welcome email includes verification and set-password links. Unverified accounts are deleted after 7 days. The owner's first dashboard sign-in replaces the API key; the old key then returns 403 with NOT_AUTHORIZED_ERROR. Participant emails also require team verification. Personal and disposable email addresses are not accepted.

ParametersJSON Schema
NameRequiredDescriptionDefault
emailYes
companyNo
lastNameNo
firstNameNo

Output Schema

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

TDQS

A4.4/5.0
Behavior5/5

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

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

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

Conciseness4/5

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

The description is long but dense with useful operational details and front-loads the core action and key prerequisite. A few sentences (e.g., participant email verification) are tangential to the tool's immediate invocation, but most content earns its place.

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

Completeness4/5

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

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

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

Parameters2/5

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

Schema description coverage is 0%, so the description must carry the burden for the four parameters. It only indirectly implies that the `email` parameter is the owner's email and that personal/disposable addresses are rejected; it says nothing about `company`, `firstName`, or `lastName`, leaving their purpose and format undocumented.

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

Purpose5/5

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

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

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

Usage Guidelines5/5

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

It provides explicit when-to-use guidance including prerequisites (owner approval, ToS/Privacy acceptance) and names the hosted OAuth connector as an alternative that retains credentials. It also clarifies that this is the only no-API-key tool, leaving little ambiguity about when to select it.

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

growsurf_create_campaignCreate ProgramAInspect

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

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

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior5/5

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

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

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

Conciseness4/5

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

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

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

Completeness4/5

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

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

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

Parameters4/5

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

Schema description coverage is low at 29%, so the description must compensate, and it does so for key parameters: type is the only required field, currencyISO defaults to USD and is immutable, rewards are optional and affect starter rewards, and goal sets sharing settings only at creation. It leaves name, companyName, and companyLogoImageUrl without explicit semantic guidance, but their purpose is largely self-evident from the parameter names.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Create a new GrowSurf program (campaign) with type-appropriate starter content and optional inline rewards.' It clearly differentiates from update/clone siblings by emphasizing that it creates a new program, starts it in DRAFT, and only requires type. An agent can identify the core action and scope without opening the schema.

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

Usage Guidelines4/5

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

It gives clear context for when to include rewards, when to omit them, and how goal affects creation, plus a boundary that 'Editor-tab configuration is not accepted here' and that the call 'Does not require GROWSURF_CAMPAIGN_ID.' However, it never names an alternative sibling tool (e.g., clone_campaign or update_campaign) for closely related tasks, so it falls short of explicit when-to-use-vs-alternative guidance.

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

growsurf_create_campaign_rewardCreate Campaign RewardAInspect

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

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

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness3/5

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.

Parameters2/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
eventsNo
secretNoWrite-only. Signs deliveries; never returned.
isEnabledNo
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
payloadUrlYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already 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.

Conciseness4/5

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.

Completeness4/5

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

An output schema exists so return values need not be explained, and 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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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

Usage is implied rather than stated: 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.

ParametersJSON Schema
NameRequiredDescriptionDefault
emailYes
languageNoThe 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`.
lastNameNo
metadataNo
firstNameNo
ipAddressNo
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
referredByNo
fingerprintNo
isAffiliateNoSets whether the participant is an affiliate. Use `true` only for trusted direct enrollment. Public applicants should follow the program's configured application flow.
referralStatusNo
mobileInstanceIdNo

Output Schema

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

TDQS

B3.4/5.0
Behavior4/5

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

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.

Conciseness4/5

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.

Completeness3/5

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

An output schema exists, so return values 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.

Parameters2/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoUsed only with `LINK`.
textNoUsed only with `TEXT`.
typeYes
titleYes
categoryNo
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
descriptionNo
isPublishedNo
uploadResultNoThe unmodified result returned by the secure upload flow. Used only with `FILE`.
uploadTicketNoThe one-time upload ticket. Used only with `FILE`.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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

An output schema exists so return values need no explanation, and annotations cover 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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 RewardA
DestructiveIdempotent
Inspect

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

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

Output Schema

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

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, but the description adds 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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 WebhookA
DestructiveIdempotent
Inspect

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

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

Output Schema

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

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so the safety profile is covered. The description adds 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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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

States a specific verb and resource ('Remove a webhook from your GrowSurf program') 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.

Usage Guidelines3/5

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 ResourceA
DestructiveIdempotent
Inspect

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

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

Output Schema

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

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so the safety profile is covered. The description adds genuinely 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.

Conciseness5/5

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.

Completeness4/5

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

An output schema exists, so return values need not be explained, and the 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.

Parameters3/5

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.

Purpose4/5

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

States a specific verb and resource ("Delete a participant resource from your GrowSurf program") and 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.

Usage Guidelines3/5

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 ParticipantA
Destructive
Inspect

Send an email to a participant (by GrowSurf participant ID or email). Provide EITHER emailType to trigger one of the program's configured email templates, OR subject + body for a free-form email (optionally preheader). 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.

ParametersJSON Schema
NameRequiredDescriptionDefault
bodyNoFree-form HTML body. You can personalize it with dynamic text, inserting `{{...}}` tokens like `{{firstName}}` or `{{shareUrl}}`. See [Guide to using dynamic text in GrowSurf emails](https://support.growsurf.com/article/213-guide-to-using-dynamic-text-in-growsurf-emails).
subjectNoFree-form subject. Supports dynamic text (`{{...}}` tokens), the same as the body.
emailTypeNoThe program email template to trigger. Send the camelCase key; the available types depend on the program type. The template's `isEnabled` setting controls automatic sends only, so this tool can trigger any sendable template. System and transactional types (login link, payout destination confirmation, tax) and the invite email cannot be sent. `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`.
preheaderNo
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
participantIdNo
participantEmailNo

Output Schema

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

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness4/5

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

An output schema exists, so return values need not be 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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 HTMLA
Read-onlyIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
elementYes
participantNo
withAuthAttributesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already 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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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

Schema description coverage is 0%, so the description must compensate. It 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.

Purpose5/5

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.

Usage Guidelines5/5

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 ProgramA
Read-onlyIdempotent
Inspect

Fetch your GrowSurf campaign (program) details via REST. Embedded reward settings do not establish that an individual reward was earned, approved, or delivered. Earned reward records belong to the individual participant. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.

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

Output Schema

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

TDQS

A3.5/5.0
Behavior4/5

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

Annotations already declare 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.

Conciseness4/5

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.

Completeness4/5

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

An output schema exists, so return values need not be described, 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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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 AnalyticsA
Read-onlyIdempotent
Inspect

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

ParametersJSON Schema
NameRequiredDescriptionDefault
cohortToNoExclusive eligibility-cohort end, Unix timestamp in ms. Must be greater than `cohortFrom`.
timezoneNoIANA timezone used to advance cohort boundaries. Defaults to `UTC`.
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
cohortFromNoInclusive eligibility-cohort start, Unix timestamp in ms. Use with `cohortTo`.
cohortIntervalNoBucket size for `cohorts`. Defaults to `day`.
observationWindowDaysNoDays after eligibility in which stages can count. Defaults to `30`.

Output Schema

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

TDQS

A4.3/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description adds 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.

Conciseness4/5

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.

Completeness5/5

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

An output schema exists, so return-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.

Parameters4/5

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.

Purpose4/5

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

States a specific verb and resource ('Fetch 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.

Usage Guidelines4/5

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 AnalyticsA
Read-onlyIdempotent
Inspect

Fetch analytics for your GrowSurf program: participants, referrals, impressions, per-channel shares, and affiliate revenue, commission, and payout metrics when applicable. Pass interval (day, week, or month) for a per-period series. Pass comma-separated include values for previousPeriod, statusCounts, rates, email, or engagement. engagement groups unique active, sharing, repeat, and retained participants by when portal views and share actions occurred. Its coverageStartAt, state, and reason distinguish measured zeroes from partial or unavailable history. Scope the timeframe with days (default 365, max 1825) or an explicit startDate/endDate window. Explicit dates must both be positive Unix timestamps in milliseconds, with endDate >= startDate and a maximum span of 1825 days. timezone and platform apply to engagement only. Targets campaignId if passed, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNo
endDateNoEnd of the timeframe, positive Unix timestamp in milliseconds. Supply `startDate` too; `endDate` must be >= `startDate` and at most 1825 days later.
includeNoComma-separated optional data: `previousPeriod`, `statusCounts`, `rates`, `email`, and `engagement`. Combine values when the question needs more than one view.
intervalNoday/week/month adds a per-period `series`; total (default) returns totals only.
platformNoClient-platform filter for engagement. Defaults to `ALL`.
timezoneNoIANA timezone for engagement interval and distinct-day calculations. Used with `include=engagement`.
startDateNoStart of the timeframe, positive Unix timestamp in milliseconds. Supply `endDate` too; the window must span at most 1825 days.
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.

Output Schema

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

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already 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.

Conciseness4/5

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.

Completeness5/5

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

With an output schema present the description need not explain return values, and it 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.

Parameters4/5

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.

Purpose4/5

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

States a specific verb and resource ('Fetch 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.

Usage Guidelines3/5

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 DesignB
Read-onlyIdempotent
Inspect

Fetch the configured design fields for your GrowSurf program, including GrowSurf Window content, colors, sharing sections, participant avatars under participantAvatarStyle, referred-visitor content such as the Claim Offer Popup, the website widget under widget, the participant Traffic report under trafficInsights (it starts on for new affiliate programs and hidden for referral programs, and every setting is returned with its default copy), participant sign-in copy under login, payout-destination confirmation page copy under payoutDestinationConfirmation, 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.

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

Output Schema

ParametersJSON Schema
NameRequiredDescription
loginNoThe returning-participant sign-in form plus its success, resend, validation, and error text.
shareNoShare channels, invite settings, and share-button styling.
statsNoThe participant's referral-progress stats panel. Only `title` is editable.
themeNoVisual theme styling (colors, shadows, and similar).
headerNoHeader content for participants (`postText`) and non-participants (`preText`).
signupNoSignup form fields, GDPR consent, and button and login text.
widgetNoThe website widget — the invite that sits in a corner of the customer's own site. It renders as a button or as a card, and its card folds back into the button when a visitor closes it. Both audience switches start off, so a program shows nothing until one is turned on.
windowNoLayout of the GrowSurf window (`navigationMode`: `TABS` or `LIST`).
payoutsNoAffiliate programs only. The Payouts section of the participant portal.
rewardsNoHeading, icon, and empty-state text of the rewards panel.
resourcesNoParticipant Resources presentation settings: visibility, title, link and copy labels, the message shown when nothing is published, and the section icon. Resource items use the program Resource tools.
commissionsNoAffiliate programs only. The Commissions section of the participant portal.
leaderboardNoThe leaderboard section: labels, selectors, and name masking.
landingPagesNoPortal and landing pages: company info, `content`, `styles`, third-party script ids, and SEO meta tags.
countryLabelsNoParticipant-facing country-name overrides keyed by ISO 3166-1 alpha-2 code (for example `GB`). Each label replaces the default country name wherever participants pick a country, such as payout and tax forms. Overrides merge per code on `PATCH`; `null` (or the default name) restores a code's default. Only overridden codes are returned.
referralStatusNoThe section listing who a participant invited and each invite's progress. `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.
referralSummaryNoReferral programs only. The participant's row of summary tiles (clicks, leads, referrals, rewards).
trafficInsightsNoThe Traffic report participants can open from the GrowSurf window: visits to their share link over time and where those visits came from. It starts on for new affiliate programs and hidden for referral programs. Every setting is returned, with the default copy for anything not changed. Labels cannot be blank.
affiliateSummaryNoAffiliate programs only. The affiliate's row of summary tiles (clicks, revenue, payouts).
referredExperienceNoThe banner, headline, and Claim Offer Popup shown to a visitor who arrives through a referral link. The popup is available for referral and affiliate programs.
participantSettingsNoThe participant's account settings area (logout, 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.
participantAvatarStyleNoHow participant avatars appear in the GrowSurf Window. New programs use `CHARACTERS`; missing or unknown stored values return `INITIALS`.
payoutDestinationConfirmationNoCustomizable text for the payout-destination confirmation page opened from payout integration cards. One shared set applies to every enabled payout provider. Provider-aware text may use `{{payoutProvider}}`; omitted and `null` fields use localized defaults.

TDQS

B3.2/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive/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.

Conciseness2/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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

States a specific verb and resource: 'Fetch 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.

Usage Guidelines2/5

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 EmailsA
Read-onlyIdempotent
Inspect

Fetch the Emails tab configuration for your GrowSurf program, including participant and admin email templates, settings, and read-only fields. settings.sender.fromEmail is read-only and can be changed in the dashboard after domain verification. 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.

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

Output Schema

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

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, 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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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

States a specific verb and resource ("Fetch 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.

Usage Guidelines3/5

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 InstallationA
Read-onlyIdempotent
Inspect

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

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

Output Schema

ParametersJSON Schema
NameRequiredDescription
mobileNoGrowSurf iOS and Android SDK settings.
signupNoCustom signup-form settings (used with `FORM_DETECTION`).
shareUrlNoThe landing page referred friends reach from a referral link. Set this before adding other origins to `allowedUrls`.
allowedUrlsNoEvery additional browser origin where the GrowSurf Window or SDK may run, including development origins such as `http://localhost:3000`. Preserve the full array when patching it. An origin absent from both `shareUrl` and this list can return `403`. Known shared-platform root domains, such as `github.io`, do not grant access. Add your site's hostname, such as `https://piedpiper.github.io`, or a domain you own. Path-based shared hosts, such as `unbouncepages.com`, require a domain you own.
signupEventNoThe signup tracking method: automatic form detection, or participants added via the SDKs and REST API.
referralTriggerNoReferral programs only. `ON_SIGNUP` counts a referral as soon as the friend signs up; `CUSTOM` also requires a qualifying action.
instructionSelectionsNoSaved choices shown in the Program Editor installation guide.
useGrowSurfHostedLinksNoUse GrowSurf-hosted referral links that route clicks by the visitor's device. Mainly for mobile apps.

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and non-destructive, 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.

Conciseness4/5

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.

Completeness4/5

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

With an output schema present the description 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.

Parameters3/5

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.

Purpose5/5

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

States a specific verb (Fetch) and a 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.

Usage Guidelines4/5

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 OptionsA
Read-onlyIdempotent
Inspect

Fetch the Options tab configuration for your GrowSurf program (referral triggers, anti-fraud lists and toggles, affiliate enrollment and application review, notifications, 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.

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

Output Schema

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

TDQS

A4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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

With an output schema present the description need not 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.

Parameters3/5

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

Schema coverage is 100% and the single campaignId parameter is fully documented in the schema, including the 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.

Purpose5/5

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.

Usage Guidelines3/5

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

Usage is implied rather than stated: '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_participantGet ParticipantA
Read-onlyIdempotent
Inspect

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

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

Output Schema

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

TDQS

A3.7/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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

With an output schema present the description needn't explain return values, yet it 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.

Parameters3/5

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.

Purpose4/5

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

States a specific verb and resource ('Fetch 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.

Usage Guidelines3/5

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 LogsA
Read-onlyIdempotent
Inspect

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

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

Output Schema

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

TDQS

A3.9/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so safety is covered. The description adds 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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 AnalyticsA
Read-onlyIdempotent
Inspect

Fetch analytics for one participant by GrowSurf participant ID or email. The base response includes all-time engagement, rank, share, and applicable affiliate revenue, commission, and payout metrics. Add activation to include for the program-specific eligibility anchor and covered first milestones, including firstPortalViewedAt and firstShareChannel. A null milestone with a partial or unavailable state is unknown, not proof that the action never happened. Request both activation and series for covered portalViews and shareActions buckets. Filter optional series and email data with days (up to 1825) or both startDate and endDate as positive Unix timestamps in milliseconds. endDate must be at or after startDate, and the range can span at most 1825 days. These date parameters do not filter the base response or activation milestones. Targets campaignId if passed, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoNumber of days for optional `series` and `email` analytics. Does not filter the all-time base response.
endDateNoEnd of the optional-data timeframe, positive Unix timestamp in milliseconds. Supply `startDate` too; `endDate` must be >= `startDate` and at most 1825 days later.
includeNoComma-separated optional data. Current values are `series`, `email`, and `activation`; the API returns `400` for unknown values.
intervalNoBucket size for `series` and email series. Defaults to `day`.
startDateNoStart of the optional-data timeframe, positive Unix timestamp in milliseconds. Supply `endDate` too; the window must span at most 1825 days.
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
participantIdNo
participantEmailNo

Output Schema

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

TDQS

A4.6/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 DestinationA
Read-onlyIdempotent
Inspect

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

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

Output Schema

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

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so safety is covered 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.

Conciseness4/5

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.

Completeness4/5

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

An output schema exists, so the 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.

Parameters4/5

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

Schema description coverage is only 33% — participantId and participantEmail 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.

Purpose5/5

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

The description names a specific verb and resource ('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.

Usage Guidelines3/5

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 TeamA
Read-onlyIdempotent
Inspect

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

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

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

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint/idempotentHint/destructiveHint, so safety is covered. The description adds value beyond annotations by specifying what is not returned (personal profiles, internal identifiers) and clarifying the meaning of verificationStatus, which is useful behavioral context.

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

Conciseness5/5

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

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

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

Completeness5/5

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

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

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

Parameters4/5

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

The tool has zero parameters, so there is no parameter semantics to explain. The description's note about environment variables (API key vs campaign ID) adds relevant configuration context beyond the empty schema.

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

Purpose5/5

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

The description opens with a specific verb and resource: "Fetch the team bound to the API key or OAuth connection." This clearly identifies the tool's function and distinguishes it from sibling tools like get_campaign or list_campaigns, even without naming an alternative.

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

Usage Guidelines4/5

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

The description gives useful context by explaining that verificationStatus must be VERIFIED before a program can email participants, implying when this tool is relevant. It also states the credential requirements (requires API key, not campaign ID), which helps route usage, though it does not explicitly name alternative tools or exclusions.

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

growsurf_grsf_config_snippetGenerate Participant Auto Authentication CodeB
Read-onlyIdempotent
Inspect

Generate the HTML code for GrowSurf Participant Auto Authentication using window.grsfConfig. The generated code belongs in <head>, before the GrowSurf Universal Code.

ParametersJSON Schema
NameRequiredDescriptionDefault
hashNo
emailNo
campaignIdNo
affiliateJoinNo
useCampaignIdPlaceholderNo
enableParticipantAutoAuthNo
includeAutoAuthCommentHeaderNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

B3.3/5.0
Behavior3/5

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

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

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

Conciseness5/5

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

Two tight sentences, no filler, with the core purpose front-loaded and the placement constraint appended where it is most useful.

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

Completeness3/5

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

An output schema exists, so return values need no explanation, and the annotations cover the safety profile. However, for a 7-parameter code generator the description leaves all parameters and most behavioral nuance undocumented, making it only partially complete.

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

Parameters2/5

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

Schema description coverage is 0% across 7 parameters, so the schema documents nothing. The description only alludes to window.grsfConfig and never explains hash, email, campaignId, affiliateJoin, useCampaignIdPlaceholder, enableParticipantAutoAuth, or includeAutoAuthCommentHeader, leaving the agent to guess at all inputs.

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

Purpose4/5

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

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

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

Usage Guidelines3/5

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

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

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

growsurf_integration_guidePlan Program IntegrationA
Read-onlyIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
programTypeNoboth
singlePageAppNo
referralTriggerNosignup_plus_qualifying_action
webhookSecurityNoAlways recommends signature verification. Legacy values are accepted for compatibility and cannot disable verification.signature
participantAuthEnabledNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive, 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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters2/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 RewardsA
Read-onlyIdempotent
Inspect

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

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

Output Schema

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

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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

States a specific verb (List) and resource (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.

Usage Guidelines4/5

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 ProgramsA
Read-onlyIdempotent
Inspect

List the GrowSurf programs available to the bound team, including their IDs for program selection. Deleted programs are not returned. Does not require GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
campaignsNoPrograms available to the API key's bound team.

TDQS

A4.2/5.0
Behavior4/5

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

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

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

Conciseness5/5

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

Three short sentences, front-loaded with what is returned and immediately followed by the two facts an agent needs (deleted items excluded, no campaign ID required). No filler.

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

Completeness5/5

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

An output schema exists, so return-shape explanation is unnecessary, and the annotations carry the safety profile. For a zero-parameter list tool the description supplies everything needed to select and call it correctly.

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

Parameters4/5

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

The tool takes zero parameters, which is the baseline-4 case, and the description correctly signals that no GROWSURF_CAMPAIGN_ID binding is required. There is nothing further for it to add.

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

Purpose4/5

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

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

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

Usage Guidelines4/5

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

'including their IDs for program selection' and 'Does not require GROWSURF_CAMPAIGN_ID' both describe when this tool is the right entry point (discovering a campaign ID before calling the many campaign-scoped tools). No explicit exclusions or named alternatives are given, so it stops short of a 5.

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

growsurf_list_campaign_webhooksList WebhooksA
Read-onlyIdempotent
Inspect

List your GrowSurf program's webhooks (secrets are never returned). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

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

Output Schema

ParametersJSON Schema
NameRequiredDescription
webhooksNoWebhooks configured for the program.

TDQS

A3.9/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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

With an output schema present, the description needn't explain return values, 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.

Parameters3/5

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

Schema description coverage is 100% and the single campaignId parameter 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.

Purpose5/5

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

States a specific verb (List) and resource (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.

Usage Guidelines3/5

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 IntegrationsA
Read-onlyIdempotent
Inspect

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

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

Output Schema

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

TDQS

A4.4/5.0
Behavior5/5

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

Annotations already cover the read-only/idempotent/non-destructive profile, 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.

Conciseness4/5

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.

Completeness5/5

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

With an output schema present, return-value 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.

Parameters3/5

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

Schema description coverage is 100% for the single campaignId parameter, so the 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.

Purpose5/5

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

States a specific verb and resource ('List 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.

Usage Guidelines4/5

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 ParticipantsA
Read-onlyIdempotent
Inspect

List participants in your GrowSurf program, newest page first. limit is 1-100 (default 10). Pass response nextId into the next call to continue paging. Pass metadata to return only participants whose stored metadata matches every given key and value exactly, for example { "customerId": "12345" } to look someone up by your own customer ID; filtered results are ordered by participant ID. Results include participant IDs. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
nextIdNoParticipant ID returned as `nextId` from the previous page.
metadataNoExact-match filter on participant metadata, up to 3 keys, for example `{ "customerId": "12345" }`. Values compare as strings.
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.

Output Schema

ParametersJSON Schema
NameRequiredDescription
limitNoMaximum number of participants requested for this page.
nextIdNoParticipant id to pass as `nextId` for the next page, or `null` when there are no more results.
participantsNoParticipants returned for this page.
rewardEvidenceNoWhat this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.

TDQS

A4.1/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness5/5

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

With an output schema present, return-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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines4/5

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 ResourcesA
Read-onlyIdempotent
Inspect

List the participant resources configured for your GrowSurf program, including drafts. Results stay in display order. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

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

Output Schema

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

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, so safety is covered. The description adds 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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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

Schema description coverage is 100% and the single 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.

Purpose5/5

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

States a specific verb (List) and resource (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.

Usage Guidelines3/5

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 GuideA
Read-onlyIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
platformNo`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
campaignIdNo
mobilePublicKeyNo
participantStateNoboth
attributionProviderNoall
includeInstallSnippetsNo
serverVerifiedQualifyingActionNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint and 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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 HashA
Read-onlyIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
emailYes
affiliateJoinNo
participantAuthSecretYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
hashNoThe computed hash. Pass it to the GrowSurf client as the participant's `hash` value.

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive, closed-world 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.

Conciseness4/5

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.

Completeness4/5

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

An output schema exists, so return values need not be explained. The description covers 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.

Parameters3/5

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

Schema description coverage is 0%, so the description carries the full 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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileNameYesA safe base name with an allowed extension: jpg/jpeg/png/gif/webp/pdf/csv/zip/doc/docx/xls/xlsx/ppt/pptx.
mimeTypeYesThe supported MIME type matching fileName's extension.
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
fileBase64YesCanonical padded base64 file bytes only. Do not include a data-URL prefix or whitespace.

Output Schema

ParametersJSON Schema
NameRequiredDescription
uploadResultNoThe minimal signed upload confirmation. Pass it unchanged to create/update.
uploadTicketNoThe one-time GrowSurf ticket. Pass it unchanged to create/update.

TDQS

A4.6/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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

Given an output schema exists, 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.

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds 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.

Purpose5/5

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.

Usage Guidelines4/5

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 DesignA
Read-onlyIdempotent
Inspect

Generate program designs, benchmarks, typical rewards, and metric definitions, including participant-to-referral and lead-to-referral ratios. Read-only. Returns a short draft, complete benchmarkFacts, a proposed configurationPlan, and unresolved decisions. Incentive amounts and qualifying actions remain unresolved unless supplied by the customer. detail: summary returns a configuration draft and reward structure; detail: full adds detailed benchmark tables. Hosted figures describe GrowSurf's high-performing programs; without a bundle, guidance is documentation-based. programType: AFFILIATE selects affiliate advice. industry: other covers local services, pets, hospitality, and agencies. All inputs are optional.

ParametersJSON Schema
NameRequiredDescriptionDefault
goalNoWhat a successful referral means for the business. `paid_conversions` and `leads` imply a qualifying action; `signups`, `subscribers`, and `waitlist` count the signup unless a separate `qualifyingAction` needs clarification. This advisor goal differs from the program creation goal included in `configurationPlan`.other
detailNoUse summary for a first design or configuration draft, including a reward structure recommendation. Use full only for requested detailed benchmark tables or specific figures absent from the summary, such as reward amounts, share channels, or integration proportions.summary
audienceNoWho refers whom.
industryNoClosest industry segment: `financial_services_fintech` (banking, lending, investing, insurance, payments, crypto), `saas_ai` (software sold to businesses, developer tools, AI products), `media_newsletters` (newsletters, podcasts, publishers, content brands), `healthcare_wellness` (clinics, telehealth, fitness, nutrition, mental health, supplements), `education_workforce` (courses, bootcamps, tutoring, hiring and job platforms), `consumer_subscriptions_commerce` (consumer apps, e-commerce, marketplaces, subscription boxes). Use `other` when no segment clearly fits (local services, pets, hospitality, agencies) rather than stretching one; `other` returns the platform-wide figures.other
companyNameNoUsed in the heading and proposed program name; omit it when unknown.
currencyISONoISO 4217 code. Non-USD advice omits the dollar reward bands. No exchange rate or equivalent-currency benchmark is available.
programTypeNoREFERRAL
salesMotionNoUse `sales_led` for demos, sales calls, negotiated pricing, or signed contracts; use `self_service` when customers buy directly. This selects the reward structure. Omit when unknown.
includeRulesNoAppend guidance on applying the recommendations. Off by default.
businessModelNoOne line on what the business sells and how. Also set `salesMotion` when the buying process is known.
qualifyingActionNoThe action a referred friend must complete, in the customer's words.
rewardBudgetPerReferralNoThe customer's spending limit per successful referral, in major currency units. A budget does not select an incentive amount or commission rate. Budget comparisons omit the mixed-currency reward amount bands.

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe requested summary or full advice, including the same configuration calls and their conditions.
decisionsNoUse one qualifying action throughout the draft. Unresolved choices require a customer decision before configuration.
benchmarkFactsNoComplete benchmark statements with metric units, median, Q1, Q3, sample, and source. Quote each statement intact. Empty when no suitable figures are available.
configurationPlanNoProposed calls using the listed tools' argument shapes. Preserve each tool and arguments object when presenting the plan; replace <new-program-id> with the creation response's id before execution.

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare 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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 SaleA
Idempotent
Inspect

Record a sale/transaction for an affiliate program. Use webhooks to know when commissions are added. Requires at least one transaction identifier (externalId, transactionId, orderId, paymentId, invoiceId, paymentIntentId, or chargeId) so repeated calls are de-duplicated instead of double-paying the referrer; reuse the same one when refunding. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
paidAtNo
orderIdNo
chargeIdNo
currencyYes
testModeNoRequired with `paymentProvider`: `true` for test or `false` for live. Otherwise omit.
invoiceIdNo
netAmountNo
paymentIdNo
taxAmountNo
amountPaidNo
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
customerIdNo
externalIdNo
totalTaxesNo
descriptionNo
grossAmountYes
invoiceTotalNo
amountCashNetNo
participantIdNo
transactionIdNo
subscriptionIdNo
totalTaxAmountNo
paymentIntentIdNo
paymentProviderNoConnected provider for this payment. Requires `transactionId` and `testMode`. Supply matching `grossAmount` and `currency`; other payment IDs and tax or net-amount overrides are not accepted. GrowSurf reads payment details from the provider and detects duplicate webhook/API/manual submissions.
totalTaxAmountsNo
participantEmailNo
invoiceTotalExcludingTaxNo
invoiceSubtotalExcludingTaxNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable result message.
successNo`true` when the sale was recorded; `false` when it matched an existing transaction.
duplicateNo`true` when the sale matched an existing transaction.
firstSaleNoWhether this was the referred customer's first recorded sale.
duplicateFieldsNoIdentifier fields that matched an existing transaction.
commissionsCreatedNoCommissions created by this duplicate request.
matchingCommissionIdsNoCommission ids that matched the submitted identifiers.

TDQS

A3.8/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness3/5

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

An output schema exists, so return values need not be 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.

Parameters3/5

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

Schema description coverage is only 11% across 28 parameters, so the description 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.

Purpose4/5

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

The description states a specific verb and resource ('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.

Usage Guidelines4/5

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 ChargebackA
DestructiveIdempotent
Inspect

Record a refund, partial refund, or chargeback for a previously recorded affiliate transaction in GrowSurf and reverse or adjust the referrer's commission. This records the amendment without sending a refund through the payment provider. Requires the same transaction identifier as the original sale. Omitted amountRefunded means a full refund. Already-paid commissions are not clawed back and are recorded for tax only. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
amountNo
orderIdNo
chargeIdNo
currencyNo
refundIdNoStable per-refund identifier. Required when canceling a refund or changing the refunded total after a cancellation. Reuse the original refund's identifier for its cancellation. An amendment without enough refund identity returns `409` without applying the cancellation. Newly observed higher cumulative refunds and incomplete coverage are retained for reconciliation.
testModeNoOriginal payment mode: `true` for test or `false` for live. Requires `paymentProvider`.
invoiceIdNo
paymentIdNo
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
externalIdNo
descriptionNo
refundAmountNoPositive amount for this individual refund, no greater than the sale amount, in the sale currency's minor unit. Send it with `refundId` on each original refund to support cancellations and out-of-order amendments. The amount for a given `refundId` cannot change. A cancellation can omit it when the original amount is already recorded. Incomplete refund history returns `409` without applying the cancellation. Newly observed higher cumulative refunds and incomplete coverage are retained for reconciliation.
refundStatusNo
amendmentTypeNo
participantIdNo
transactionIdNo
amountRefundedNo
paymentIntentIdNo
paymentProviderNoConnected provider for the original payment. Requires its `transactionId` and `testMode`. This amends GrowSurf records without sending a refund through the provider.
participantEmailNo
refundHistoryCompleteNoSet true only after reconciling and recording every original refundId and refundAmount, including refunds later canceled. This confirmation resolves previously incomplete history. Omit during ordinary delivery. Replaying an old confirmation cannot resolve a later gap; confirm a newly reconciled refund or complete provider list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
deletedNoPending commissions deleted by the amendment.
matchedNoCommissions found for the provided identifiers.
messageNoHuman-readable result message.
successNo`true` when the amendment was processed; `false` when no matching transaction was found.
adjustedNoCommissions partially adjusted.
notFoundNoPresent and `true` when no commission matched the provided identifiers.
reversedNoCommissions reversed (set to zero amount).
amendmentTypeNoAmendment type that was processed.
matchingCommissionIdsNoCommission ids that matched the submitted identifiers.

TDQS

A4.1/5.0
Behavior4/5

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

Annotations 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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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

States a specific verb and resource ('Record a 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.

Usage Guidelines4/5

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 ConfirmationA
Destructive
Inspect

Ask a participant to confirm their payout destination for a provider (by GrowSurf participant ID or email). Sends them a one-time confirmation link for the chosen provider; only the participant can open the link and confirm — this just triggers the message, and the provider must be enabled for the program. Returns { status, provider, providerDisplayName, expiresAt }. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
providerYesThe payout provider the participant should confirm a destination for.
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
participantIdNo
participantEmailNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusNoConfirms the message was requested (`CONFIRMATION_REQUESTED`).
providerNoThe payout provider identifier the participant was asked to confirm. Values are open-ended; current examples include `PAYPAL`, `VENMO`, and `WISECOM`.
expiresAtNoWhen the confirmation link expires, as a Unix timestamp in milliseconds.
providerDisplayNameNoThe customer-facing provider name (e.g. "PayPal", "Wise").

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness5/5

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

An output schema exists, so 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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 VerificationA
Idempotent
Inspect

Ask GrowSurf to verify the team bound to the API key or OAuth connection. Verification is required before a program can email participants. Calling this again while a request is pending does not create a duplicate. Returns the team with its updated verificationStatus. Requires GROWSURF_API_KEY; does not require GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

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

TDQS

A4.5/5.0
Behavior4/5

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

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

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

Conciseness5/5

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

Four short sentences, front-loaded with the action and condition, then idempotency, then return value and auth requirements. Every sentence adds information; nothing is redundant filler.

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

Completeness5/5

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

For a zero-parameter mutation with a declared output schema, the description covers everything an agent needs: purpose, precondition, idempotency, auth requirements, and return shape. Return-value detail is delegated appropriately to the output schema.

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

Parameters4/5

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

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

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

Purpose5/5

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

States a specific verb (verify) and resource (the team bound to the API key/OAuth connection), which clearly separates it from siblings like growsurf_get_team or growsurf_resend_team_owner_verification_email. An agent can tell what action this triggers without opening a schema.

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

Usage Guidelines4/5

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

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

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

growsurf_resend_team_owner_verification_emailResend Team Owner Verification EmailA
Destructive
Inspect

Resend the email-verification message to the bound team's owner. The response never reveals the owner's email address. A 200 with status: SENT is returned only when an email was sent. Returns 400 if the email is already verified and 429 if one was sent too recently. Requires GROWSURF_API_KEY; does not require GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusNoStatus of the verification email request.
successNoWhether the verification email request was accepted.

TDQS

A3.8/5.0
Behavior4/5

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

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

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

Conciseness5/5

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

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

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

Completeness5/5

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

Given the tool has no parameters and an output schema exists, the description covers all essential call context: response behavior, authentication needs, and a key privacy constraint. An agent can confidently invoke the tool without additional information.

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

Parameters4/5

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

The tool has zero parameters, so the baseline is 4. The description does not need to elaborate on parameters, and no additional meaning is required beyond the empty schema.

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

Purpose4/5

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

The description states a specific action (resend verification email) and target (team's owner), making the purpose clear. However, it does not mention the sibling tool request_team_verification or how this differs, so it misses the 'distinguishes from siblings' criterion for a 5.

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

Usage Guidelines2/5

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

No guidance is provided on when to use this tool versus alternatives. It does not mention the sibling request_team_verification or any conditions that would select this tool over others. The response codes (400, 429) give some context but do not help with tool selection.

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

growsurf_test_campaign_webhookSend Test WebhookA
Destructive
Inspect

Send a live test event to a webhook on your GrowSurf program using its stored URL and secret. Optionally pass event to choose which event type to simulate; when omitted, the webhook's first enabled event is used (returns 400 if the webhook has no enabled events). Returns the mock payload and the receiving endpoint's response. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

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

Output Schema

ParametersJSON Schema
NameRequiredDescription
payloadNoThe mock event payload that was sent.
successNoWhether the test webhook request completed.
responseNoResponse returned by the webhook endpoint during the test.

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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

With an output schema present, return values need not be 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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 ReferralA
Destructive
Inspect

Trigger referral credit for a referred participant (use when your trigger is Sign up + Qualifying Action). Optionally pass delayInDays (1-90) to hold the credit for N days before awarding it (e.g. to cover a refund window). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

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

Output Schema

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

TDQS

A3.8/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true, idempotentHint=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.

Conciseness4/5

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.

Completeness4/5

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

An output schema exists, so return 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.

Parameters4/5

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.

Purpose4/5

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

States a specific verb+resource ('Trigger referral credit for a referred participant') and 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.

Usage Guidelines4/5

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 TrackingA
Read-onlyIdempotent
Inspect

Diagnose referral tracking and program problems. Accepts a symptom or description without requiring a program or participant ID. Covers referrals not credited, participant emails not sending, rewards not issued, participants not added, Universal Code not detected, integrations or CRMs not syncing, Zapier errors, fraud flags, and analytics discrepancies. Returns ordered diagnostic checks, likely causes, fixes, and documentation links. It does not read program or participant records. Unknown symptom keys return the available symptoms. A description matches only when it contains a symptom label or alias verbatim; otherwise the symptom list is returned.

ParametersJSON Schema
NameRequiredDescriptionDefault
symptomNoThe symptom to diagnose. Known keys: `participant_emails_not_sending`, `reward_not_issued`, `referral_not_credited`, `participants_not_added`, `universal_code_not_detected`, `platform_specific_install`, `numbers_do_not_match`. Unknown keys return the symptom list.
campaignIdNoTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
descriptionNoThe problem in the customer's words, when `symptom` is unknown.
participantIdNoAffected participant id, echoed into participant-level checks.
participantEmailNoAffected participant email, when the id is unknown.

Output Schema

ParametersJSON Schema
NameRequiredDescription
markdownNoThe generated guidance as a markdown document.

TDQS

A4.5/5.0
Behavior4/5

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

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

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

Conciseness5/5

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

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

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

Completeness5/5

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

With an output schema present, return values need not be explained, yet the description still summarizes them (ordered checks, likely causes, fixes, docs links). Combined with annotations covering safety and full schema coverage of params, nothing an agent needs to invoke this correctly is missing.

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

Parameters4/5

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

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

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

Purpose5/5

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

Opens with a specific verb+resource: 'Diagnose referral tracking and program problems.' It also draws an explicit boundary ('does not read program or participant records'), which separates it from the many read-oriented siblings like growsurf_get_participant and growsurf_get_campaign. An agent can route to it without opening the schema.

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

Usage Guidelines4/5

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

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

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

growsurf_update_campaignUpdate ProgramA
DestructiveIdempotent
Inspect

Update your GrowSurf program's (campaign's) identity and lifecycle: name, companyName, companyLogoImageUrl, and status (set IN_PROGRESS to publish/resume the program, COMPLETE to end it). Only the fields you send are changed. type, urlId, and currencyISO are immutable (currency is chosen once at program creation), so this tool does not accept them. Editor-tab config (design, emails, options, installation) is edited with the dedicated config sub-resource tools, not here. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNo
statusNoLifecycle transition. IN_PROGRESS publishes/resumes the program; COMPLETE ends it. These are the only accepted targets — DRAFT/PENDING/CANCELLED are rejected by the API.
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
companyNameNo
companyLogoImageUrlNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already flag destructiveHint=true and idempotentHint=true, but the description 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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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

States a specific verb and resource ('Update 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.

Usage Guidelines5/5

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 DesignA
DestructiveIdempotent
Inspect

Update the design configuration for your GrowSurf program, including participant avatars under participantAvatarStyle, referred-visitor content such as the Claim Offer Popup, the website widget under widget (button or card, placement, timing, and visible pages), the participant Traffic report under trafficInsights, participant sign-in copy under login, 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.

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

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, 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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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

States a specific verb ('Update') and resource ('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.

Usage Guidelines3/5

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

Usage is implied by the field-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 EmailsA
DestructiveIdempotent
Inspect

Update writable Emails tab fields for your GrowSurf program under fields, in their existing nested shape. settings.sender.fromEmail is read-only; sender address changes require domain verification in the dashboard. settings.sender.fromName and settings.sender.replyToEmail 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.

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

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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 InstallationA
DestructiveIdempotent
Inspect

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

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsYesInstallation fields to patch. Common keys include `shareUrl`, `allowedUrls`, `signupEvent`, `referralTrigger`, `signup`, and `instructionSelections`. Arrays replace wholesale.
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
replaceExistingShareUrlNoSet this to `true` only after the customer confirms they want a different landing page. Without it, a patch that would replace a Share URL that is already set is refused.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

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

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 OptionsA
DestructiveIdempotent
Inspect

Update the Options tab configuration for your GrowSurf program under fields, in its existing nested shape. Only supplied fields change; omitted fields retain their existing values and arrays replace wholesale. 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.

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

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness4/5

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

For a nested-object mutation with an output schema present, the description 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.

Parameters4/5

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.

Purpose4/5

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

States a specific verb and resource: 'Update 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.

Usage Guidelines4/5

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 RewardB
DestructiveIdempotent
Inspect

Update an existing campaign reward (reward config) on your GrowSurf program. campaignRewardId is the reward key (e.g. crew_...). The reward type is immutable. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

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

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, and openWorldHint=true, so the safety/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.

Conciseness4/5

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.

Completeness3/5

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

An output schema exists, so return values need no explanation, and the 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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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 WebhookA
DestructiveIdempotent
Inspect

Update a webhook on your GrowSurf program by id (webhookId is primary for the program's primary webhook). Only the fields you send are changed. secret is write-only and never returned. Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
eventsNo
secretNoWrite-only.
isEnabledNo
webhookIdYes
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
payloadUrlNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, idempotentHint=true and 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.

Conciseness5/5

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.

Completeness4/5

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

An output schema exists so return values need not be described; the description covers the 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.

Parameters3/5

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.

Purpose4/5

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

States a specific verb and resource: 'Update a 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.

Usage Guidelines3/5

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 ParticipantA
DestructiveIdempotent
Inspect

Update a participant by GrowSurf participant ID or email. Only the fields you send are changed; read-only fields such as counters, isAffiliate, origin, and fraud state are rejected with a 400. In affiliate programs, affiliateStatus accepts APPROVED, SUSPENDED, or BANNED; APPROVED enrolls the participant, while SUSPENDED and BANNED require an existing affiliate. Affiliate enrollment cannot be removed through REST. notes is freeform internal notes (never shown to participants). Targets campaignId if you pass it, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
emailNoChange the participant's email address.
notesNoFreeform internal notes (internal only, never exposed to participants).
languageNoThe 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`.
lastNameNo
metadataNo
firstNameNo
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
referredByNo
vanityKeysNo
unsubscribedNo
participantIdNo
referralStatusNo
affiliateStatusNoAffiliate programs only. Sets the affiliate status. `APPROVED` also enrolls a participant who is not yet an affiliate. `SUSPENDED` and `BANNED` are rejected for non-affiliates.
participantEmailNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 ResourceA
DestructiveIdempotent
Inspect

Update at least one participant resource field, or move it to a zero-based position. Only supplied fields change. A replacement FILE requires a one-time uploadTicket and the unmodified uploadResult from GrowSurf's secure upload flow. API reference: https://docs.growsurf.com/developer-tools/rest-api/api-reference. Targets campaignId if supplied, otherwise GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoUsed with `LINK`.
textNoUsed with `TEXT`.
typeNo
titleNo
categoryNo
positionNo
campaignIdYesTarget program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server.
resourceIdYes
descriptionNo
isPublishedNo
uploadResultNoThe unmodified result returned by the secure upload flow for a replacement `FILE`.
uploadTicketNoThe one-time upload ticket for a replacement `FILE`.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, and 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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose4/5

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

States a specific verb and resource (update a 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.

Usage Guidelines3/5

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 TeamA
DestructiveIdempotent
Inspect

Update the display name of the team bound to the API key or OAuth connection. Personal profiles, billing, and team ownership are not editable here. Requires GROWSURF_API_KEY; does not require GROWSURF_CAMPAIGN_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesThe team's display name.

Output Schema

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

TDQS

A4/5.0
Behavior3/5

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

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

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

Conciseness5/5

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

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

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

Completeness4/5

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

Given the tool's simplicity (1 param, no nested objects) and presence of output schema, the description covers essential usage. It clarifies auth requirements, exclusions, and the single editable field. Slight gap: doesn't mention potential side effects or irreversible changes, but given simple scope, it's sufficient.

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

Parameters3/5

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

The input schema already provides 100% coverage for the single parameter 'name' with a description. The description adds no extra syntax or format details beyond schema, so baseline 3 is appropriate. It does not complement the schema, but doesn't need to.

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

Purpose4/5

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

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

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

Usage Guidelines5/5

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

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

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

growsurf_webhook_normalizeNormalize Webhook PayloadA
Read-onlyIdempotent
Inspect

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

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

Output Schema

ParametersJSON Schema
NameRequiredDescription
okNoWhether the payload is a valid GrowSurf webhook envelope.
errorNoWhy the payload failed validation. Present only when `ok` is `false`.
envelopeNoThe normalized webhook envelope. Present only when `ok` is `true`.
idempotencyKeyNoA deterministic key for ignoring duplicate deliveries. Present only when `ok` is `true`.

TDQS

A3.5/5.0
Behavior3/5

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

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

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

Conciseness5/5

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

One dense sentence with zero filler; the core action and the extra idempotency-key behavior are both front-loaded. Nothing could be removed without losing information.

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

Completeness3/5

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

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

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

Parameters3/5

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

Schema description coverage is 100% and the single `payload` parameter is documented thoroughly in the schema (accepted types, required envelope fields, ok:false fallback). The description adds no parameter-level detail beyond that, so the baseline of 3 applies.

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

Purpose4/5

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

States a specific verb pair (validate/normalize) on a specific resource (GrowSurf webhook payload) plus a concrete secondary output (idempotency key). It is clearly distinct from the webhook CRUD siblings (list/create/update/delete/test_campaign_webhook), though it never names or contrasts with any sibling explicitly.

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

Usage Guidelines3/5

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

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

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 47 tool updatesv0.19.15
    • Changedgrowsurf_add_participant3 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / properties / language
        Added 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"
        +  ]
        +}
      • changedInput schema / required
        Previous value: -[
        -  "email"
        -]New value: +[
        +  "email",
        +  "campaignId"
        +]
    • Changedgrowsurf_bulk_delete_participants2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "participants"
        -]New value: +[
        +  "participants",
        +  "campaignId"
        +]
    • Changedgrowsurf_cancel_delayed_referral2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_capture_referral_flow_screenshots2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_clone_campaign2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_create_campaign_reward2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "type"
        -]New value: +[
        +  "type",
        +  "campaignId"
        +]
    • Changedgrowsurf_create_campaign_webhook2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "payloadUrl"
        -]New value: +[
        +  "payloadUrl",
        +  "campaignId"
        +]
    • Changedgrowsurf_create_mobile_participant_token3 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / properties / language
        Added 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"
        +  ]
        +}
      • changedInput schema / required
        Previous value: -[
        -  "email"
        -]New value: +[
        +  "email",
        +  "campaignId"
        +]
    • Changedgrowsurf_create_program_resource2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "type",
        -  "title"
        -]New value: +[
        +  "type",
        +  "title",
        +  "campaignId"
        +]
    • Changedgrowsurf_delete_campaign_reward2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "campaignRewardId"
        -]New value: +[
        +  "campaignRewardId",
        +  "campaignId"
        +]
    • Changedgrowsurf_delete_campaign_webhook2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "webhookId"
        -]New value: +[
        +  "webhookId",
        +  "campaignId"
        +]
    • Changedgrowsurf_delete_program_resource2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "resourceId"
        -]New value: +[
        +  "resourceId",
        +  "campaignId"
        +]
    • Changedgrowsurf_email_participant3 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / properties / emailType / description
        Previous 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`."
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_get_campaign2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_get_campaign_activation_analytics2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_get_campaign_analytics2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_get_campaign_design6 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
      • changedOutput schema / properties / participantSettings / description
        Previous 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."
      • changedOutput schema / properties / referralStatus / description
        Previous 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."
      • changedOutput schema / properties / widget / properties / reveal / description
        Previous 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`."
      • changedOutput schema / properties / widget / properties / revealDelaySeconds / description
        Previous 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."
    • Changedgrowsurf_get_campaign_emails7 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
      • addedOutput schema / properties / followUpReminder
        Added 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"
        +}
      • changedOutput schema / properties / settings / description
        Previous 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."
      • addedOutput schema / properties / settings / properties / design
        Added 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"
        +}
      • changedOutput schema / properties / settings / properties / sender / properties / fromName / description
        Previous 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."
      • changedOutput schema / properties / settings / properties / sender / properties / replyToEmail / description
        Previous 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."
    • Changedgrowsurf_get_campaign_installation2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_get_campaign_options3 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
      • addedOutput schema / properties / languages
        Added 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"
        +}
    • Changedgrowsurf_get_participant3 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
      • addedOutput schema / properties / language
        Added 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"
        +}
    • Changedgrowsurf_get_participant_activity_logs2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_get_participant_analytics2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_get_participant_payout_destination2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_integration_guide3 fields changed
      • changedInput schema / properties / webhookSecurity / default
        Previous value: -"token_in_url"New value: +"signature"
      • addedInput schema / properties / webhookSecurity / description
        Added value: +"Always recommends signature verification. Legacy values are accepted for compatibility and cannot disable verification."
      • changedInput schema / properties / webhookSecurity / enum
        Previous value: -[
        -  "token_in_url",
        -  "none"
        -]New value: +[
        +  "signature",
        +  "token_in_url",
        +  "none"
        +]
    • Changedgrowsurf_list_campaign_rewards2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_list_campaign_webhooks2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_list_integrations2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_list_participants2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_list_program_resources2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_mobile_sdk_guide3 fields changed
      • addedInput schema / properties / platform / description
        Added 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."
      • changedInput schema / properties / platform / enum
        Previous value: -[
        -  "ios",
        -  "android",
        -  "both"
        -]New value: +[
        +  "ios",
        +  "android",
        +  "both",
        +  "react_native"
        +]
      • changedOutput schema / description
        Previous value: -"Native iOS/Android SDK guidance, as a markdown document."New value: +"Native iOS/Android or React Native SDK guidance, as a markdown document."
    • Changedgrowsurf_participant_auth_hash2 fields changed
      • addedInput schema / properties / participantAuthSecret / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "email"
        -]New value: +[
        +  "email",
        +  "participantAuthSecret"
        +]
    • Changedgrowsurf_prepare_program_resource_file2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "fileName",
        -  "mimeType",
        -  "fileBase64"
        -]New value: +[
        +  "fileName",
        +  "mimeType",
        +  "fileBase64",
        +  "campaignId"
        +]
    • Changedgrowsurf_record_sale2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "currency",
        -  "grossAmount"
        -]New value: +[
        +  "currency",
        +  "grossAmount",
        +  "campaignId"
        +]
    • Changedgrowsurf_refund_transaction2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_request_participant_payout_destination_confirmation2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "provider"
        -]New value: +[
        +  "provider",
        +  "campaignId"
        +]
    • Changedgrowsurf_test_campaign_webhook2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "webhookId"
        -]New value: +[
        +  "webhookId",
        +  "campaignId"
        +]
    • Changedgrowsurf_trigger_referral2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_update_campaign2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_update_campaign_design2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "fields"
        -]New value: +[
        +  "fields",
        +  "campaignId"
        +]
    • Changedgrowsurf_update_campaign_emails4 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / properties / fields / properties / settings / properties / sender / properties / fromName / description
        Added 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."
      • addedInput schema / properties / fields / properties / settings / properties / sender / properties / replyToEmail / description
        Added value: +"Valid reply-to email address, up to 100 characters. Omit to keep the current value; `null` cannot clear it."
      • changedInput schema / required
        Previous value: -[
        -  "fields"
        -]New value: +[
        +  "fields",
        +  "campaignId"
        +]
    • Changedgrowsurf_update_campaign_installation2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "fields"
        -]New value: +[
        +  "fields",
        +  "campaignId"
        +]
    • Changedgrowsurf_update_campaign_options2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "fields"
        -]New value: +[
        +  "fields",
        +  "campaignId"
        +]
    • Changedgrowsurf_update_campaign_reward2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "campaignRewardId"
        -]New value: +[
        +  "campaignRewardId",
        +  "campaignId"
        +]
    • Changedgrowsurf_update_campaign_webhook2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "webhookId"
        -]New value: +[
        +  "webhookId",
        +  "campaignId"
        +]
    • Changedgrowsurf_update_participant3 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • addedInput schema / properties / language
        Added 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"
        +  ]
        +}
      • addedInput schema / required
        Added value: +[
        +  "campaignId"
        +]
    • Changedgrowsurf_update_program_resource2 fields changed
      • addedInput schema / properties / campaignId / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "resourceId"
        -]New value: +[
        +  "resourceId",
        +  "campaignId"
        +]
  2. 48 tool updatesv0.19.9
    • Changedgrowsurf_add_participant1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_bulk_delete_participants1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_cancel_delayed_referral1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_capture_referral_flow_screenshots1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_clone_campaign1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_create_campaign1 field changed
      • changedInput schema / properties / goal / description
        Previous value: -"What the program is for, which seeds the share buttons and the starter rewards that suit that audience. Programs whose participants refer other businesses (`CUSTOMERS`, `USERS`, `B2B_SAAS_SELF_SERVICE`, `B2B_SAAS_ENTERPRISE`, `HEALTHCARE_PROVIDERS`) start with the LinkedIn share button visible. Consumer, financial, education, insurance, telehealth, newsletter, and waitlist programs (`B2C_SUBSCRIPTIONS`, `FINANCIAL_SERVICES`, `ONLINE_EDUCATION`, `INSURANCE`, `ONLINE_INSURANCE`, `TELEHEALTH`, `SUBSCRIBERS`, `WAITLIST`) start with it hidden. On a referral program, each goal also sets the rest of its share buttons to suit that audience — a telehealth program keeps the public feeds off, a consumer subscription turns Pinterest and Reddit on; an affiliate program has its own share defaults, so only the LinkedIn default applies to one. When you create a referral program without `rewards`, the goal also decides the starter rewards: most goals get one double-sided reward, `HEALTHCARE_PROVIDERS` gets a single-sided reward, `SUBSCRIBERS` gets a four-step milestone ladder, and `WAITLIST` gets a leaderboard. Every starter reward arrives switched off with a placeholder name, so the program awards nothing until the customer sets the amount and turns one on. `TELEHEALTH` is for consumer telehealth and wellness subscriptions, where patients refer friends; `HEALTHCARE_PROVIDERS` is for provider networks and clinician-facing products, where practices refer peer practices. `INSURANCE` replaces `ONLINE_INSURANCE`, which is still accepted and behaves identically. Omit `goal` and every share button keeps its standard default. Change any of it afterward with `growsurf_update_campaign_design`. Set only at creation; `growsurf_update_campaign` does not accept it."New value: +"What the program is for, which seeds the share buttons and the starter rewards that suit that audience. Programs whose participants refer other businesses (`CUSTOMERS`, `USERS`, `B2B_SAAS_SELF_SERVICE`, `B2B_SAAS_ENTERPRISE`, `HEALTHCARE_PROVIDERS`) start with the LinkedIn share button visible. Consumer, financial, education, insurance, telehealth, newsletter, and waitlist programs (`B2C_SUBSCRIPTIONS`, `FINANCIAL_SERVICES`, `ONLINE_EDUCATION`, `INSURANCE`, `ONLINE_INSURANCE`, `TELEHEALTH`, `SUBSCRIBERS`, `WAITLIST`) start with it hidden. On a referral program, each goal also sets the rest of its share buttons to suit that audience — a telehealth program keeps the public feeds off, a consumer subscription turns Pinterest and Reddit on; an affiliate program has its own share defaults, so only the LinkedIn default applies to one. When you create a referral program without `rewards`, the goal also decides the starter rewards: most goals get one double-sided reward, `HEALTHCARE_PROVIDERS` gets a single-sided reward, `SUBSCRIBERS` gets a four-step milestone ladder, and `WAITLIST` gets a leaderboard. Every starter reward arrives switched off with a placeholder name, so the program awards nothing until the customer sets the amount and turns one on. `TELEHEALTH` is for consumer telehealth and wellness subscriptions, where patients refer friends; `HEALTHCARE_PROVIDERS` is for provider networks and clinician-facing products, where practices refer peer practices. `INSURANCE` replaces `ONLINE_INSURANCE`, which is still accepted and behaves identically. Omit `goal` and every share button keeps its standard default. Sharing settings remain editable after creation. The goal itself is set only at creation."
    • Changedgrowsurf_create_campaign_reward1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_create_campaign_webhook1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_create_mobile_participant_token1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_create_program_resource1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_delete_campaign_reward1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_delete_campaign_webhook1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_delete_program_resource1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_email_participant1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_campaign1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_campaign_activation_analytics1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_campaign_analytics1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_campaign_design1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_campaign_emails1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_campaign_installation1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_campaign_options1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_participant1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_participant_activity_logs1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_participant_analytics1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_get_participant_payout_destination1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_list_campaign_rewards1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_list_campaign_webhooks1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_list_integrations1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_list_participants1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_list_program_resources1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_prepare_program_resource_file1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_program_design_advisor1 field changed
      • changedInput schema / properties / goal / description
        Previous value: -"What a successful referral means for the business. `paid_conversions` and `leads` imply a qualifying action; `signups`, `subscribers`, and `waitlist` count the signup unless a separate `qualifyingAction` needs clarification. This is the advisor's goal enum; use the separate creation goal returned in `configurationPlan` for `growsurf_create_campaign`."New value: +"What a successful referral means for the business. `paid_conversions` and `leads` imply a qualifying action; `signups`, `subscribers`, and `waitlist` count the signup unless a separate `qualifyingAction` needs clarification. This advisor goal differs from the program creation goal included in `configurationPlan`."
    • Changedgrowsurf_record_sale1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_refund_transaction1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_request_participant_payout_destination_confirmation1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_test_campaign_webhook1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_trigger_referral1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_troubleshoot_referral_tracking1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_campaign1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_campaign_design1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_campaign_emails1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_campaign_installation1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_campaign_options1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_campaign_reward1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_campaign_webhook1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_participant1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_update_program_resource1 field changed
      • changedInput schema / properties / campaignId / description
        Previous value: -"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Pass the `id` returned by growsurf_create_campaign to configure or operate a program you just created, without restarting the server."New value: +"Target program (campaign) id for this call. Defaults to GROWSURF_CAMPAIGN_ID when omitted. Program IDs also identify newly created programs without restarting the server."
    • Changedgrowsurf_webhook_normalize2 fields changed
      • addedInput schema / properties / payload / description
        Added value: +"JSON value to validate. A valid webhook envelope is an object with `event`, `createdAt`, and `data`. Other JSON values return `ok: false`."
      • addedInput schema / properties / payload / type
        Added value: +[
        +  "object",
        +  "array",
        +  "string",
        +  "number",
        +  "boolean",
        +  "null"
        +]
  3. 8 tool updatesv0.19.8
    • Changedgrowsurf_create_campaign_reward6 fields changed
      • changedInput schema / properties / couponCode / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / imageUrl / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / nextMilestonePrefix / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / nextMilestoneSuffix / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / referralCouponCode / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / referralDescription / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
    • Changedgrowsurf_get_campaign_analytics5 fields changed
      • addedInput schema / allOf
        Added value: +[
        +  {
        +    "if": {
        +      "required": [
        +        "startDate"
        +      ]
        +    },
        +    "then": {
        +      "required": [
        +        "endDate"
        +      ]
        +    }
        +  },
        +  {
        +    "if": {
        +      "required": [
        +        "endDate"
        +      ]
        +    },
        +    "then": {
        +      "required": [
        +        "startDate"
        +      ]
        +    }
        +  }
        +]
      • changedInput schema / properties / endDate / description
        Previous value: -"End of the timeframe, Unix timestamp in ms."New value: +"End of the timeframe, positive Unix timestamp in milliseconds. Supply `startDate` too; `endDate` must be >= `startDate` and at most 1825 days later."
      • addedInput schema / properties / endDate / minimum
        Added value: +1
      • changedInput schema / properties / startDate / description
        Previous value: -"Start of the timeframe, Unix timestamp in ms. Use with endDate instead of days."New value: +"Start of the timeframe, positive Unix timestamp in milliseconds. Supply `endDate` too; the window must span at most 1825 days."
      • addedInput schema / properties / startDate / minimum
        Added value: +1
    • Changedgrowsurf_get_campaign_emails2 fields changed
      • changedOutput schema / description
        Previous value: -"A program's email configuration. Each template property is an object with `subject`, `preheader`, `body` (HTML), and `isEnabled` (plus `useCompanyReplyTo` on the invite email). The templates available depend on the program type. `GET` returns the full object; `PATCH` back only the fields you want to change."New value: +"A program's email configuration. Each template property is an object with `subject`, `preheader`, `body` (HTML), and `isEnabled` (plus `useCompanyReplyTo` on the invite email). The templates available depend on the program type. `GET` includes read-only fields; `PATCH` only the writable fields you want to change. The `invite` and transactional email `isEnabled` toggles cannot be changed here."
      • addedOutput schema / properties / settings / properties
        Added value: +{
        +  "sender": {
        +    "properties": {
        +      "fromEmail": {
        +        "description": "Read-only sender email address. Change it in the dashboard after domain verification; omit it from an email configuration update.",
        +        "readOnly": true,
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "fromName": {
        +        "description": "Sender name, or null before one is configured. A new value must not be an email address.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "replyToEmail": {
        +        "description": "Email address that receives replies, or null before one is configured.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "type": "object"
        +  }
        +}
    • Changedgrowsurf_get_campaign_installation1 field changed
      • changedOutput schema / properties / allowedUrls / description
        Previous value: -"Every additional browser origin where the GrowSurf Window or SDK may run, including development origins such as `http://localhost:3000`. Preserve the full array when patching it. An origin absent from both `shareUrl` and this list can return `403`."New value: +"Every additional browser origin where the GrowSurf Window or SDK may run, including development origins such as `http://localhost:3000`. Preserve the full array when patching it. An origin absent from both `shareUrl` and this list can return `403`. Known shared-platform root domains, such as `github.io`, do not grant access. Add your site's hostname, such as `https://piedpiper.github.io`, or a domain you own. Path-based shared hosts, such as `unbouncepages.com`, require a domain you own."
    • Changedgrowsurf_get_participant_analytics5 fields changed
      • addedInput schema / allOf
        Added value: +[
        +  {
        +    "if": {
        +      "required": [
        +        "startDate"
        +      ]
        +    },
        +    "then": {
        +      "required": [
        +        "endDate"
        +      ]
        +    }
        +  },
        +  {
        +    "if": {
        +      "required": [
        +        "endDate"
        +      ]
        +    },
        +    "then": {
        +      "required": [
        +        "startDate"
        +      ]
        +    }
        +  }
        +]
      • changedInput schema / properties / endDate / description
        Previous value: -"End of the optional-data timeframe, Unix timestamp in ms. Use with `startDate`."New value: +"End of the optional-data timeframe, positive Unix timestamp in milliseconds. Supply `startDate` too; `endDate` must be >= `startDate` and at most 1825 days later."
      • addedInput schema / properties / endDate / minimum
        Added value: +1
      • changedInput schema / properties / startDate / description
        Previous value: -"Start of the optional-data timeframe, Unix timestamp in ms. Use with `endDate` instead of `days`."New value: +"Start of the optional-data timeframe, positive Unix timestamp in milliseconds. Supply `endDate` too; the window must span at most 1825 days."
      • addedInput schema / properties / startDate / minimum
        Added value: +1
    • Changedgrowsurf_update_campaign_emails1 field changed
      • addedInput schema / properties / fields / properties
        Added value: +{
        +  "settings": {
        +    "additionalProperties": true,
        +    "properties": {
        +      "sender": {
        +        "additionalProperties": true,
        +        "description": "Patch `fromName` or `replyToEmail`. Change the read-only `fromEmail` in the dashboard after domain verification.",
        +        "not": {
        +          "required": [
        +            "fromEmail"
        +          ]
        +        },
        +        "properties": {
        +          "fromName": {
        +            "type": "string"
        +          },
        +          "replyToEmail": {
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      }
        +    },
        +    "type": "object"
        +  }
        +}
    • Changedgrowsurf_update_campaign_installation1 field changed
      • changedInput schema / properties / fields / properties / allowedUrls / description
        Previous value: -"Every browser origin allowed to use the program, including local and staging origins. Send the full array because arrays replace wholesale."New value: +"Every browser origin allowed to use the program, including local and staging origins. Send the full array because arrays replace wholesale. Known shared-platform root domains, such as `github.io`, do not grant access. Add your site's hostname, such as `https://piedpiper.github.io`, or a domain you own. Path-based shared hosts, such as `unbouncepages.com`, require a domain you own."
    • Changedgrowsurf_update_campaign_reward6 fields changed
      • changedInput schema / properties / couponCode / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / imageUrl / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / nextMilestonePrefix / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / nextMilestoneSuffix / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / referralCouponCode / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / referralDescription / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
  4. 4 tool updatesv0.19.7
    • Changedgrowsurf_get_campaign_installation1 field changed
      • addedOutput schema / properties / instructionSelections
        Added value: +{
        +  "description": "Saved choices shown in the Program Editor installation guide.",
        +  "properties": {
        +    "mobileAttributionProvider": {
        +      "description": "Mobile attribution provider selected for the guide.",
        +      "enum": [
        +        "branch",
        +        "appsflyer",
        +        "adjust",
        +        "singular",
        +        "other"
        +      ],
        +      "type": "string"
        +    },
        +    "platform": {
        +      "description": "Platform shown in step 1.",
        +      "enum": [
        +        "web",
        +        "ios",
        +        "android"
        +      ],
        +      "type": "string"
        +    },
        +    "stepProviders": {
        +      "description": "Selected method for each installation step; affiliate and referral choices depend on program type.",
        +      "properties": {
        +        "step2Affiliate": {
        +          "description": "Affiliate step 2 method.",
        +          "enum": [
        +            "stripe",
        +            "chargebee",
        +            "recurly",
        +            "restApi"
        +          ],
        +          "type": "string"
        +        },
        +        "step2Referral": {
        +          "description": "Referral step 2 method.",
        +          "enum": [
        +            "restApi",
        +            "zapier",
        +            "stripe",
        +            "chargebee",
        +            "recurly",
        +            "paypal",
        +            "hubspot",
        +            "salesforce"
        +          ],
        +          "type": "string"
        +        },
        +        "step2Signup": {
        +          "description": "Signup method shown in step 2.",
        +          "enum": [
        +            "restApi",
        +            "javascript"
        +          ],
        +          "type": "string"
        +        },
        +        "step3Affiliate": {
        +          "description": "Affiliate payout method shown in step 3.",
        +          "enum": [
        +            "paypal",
        +            "wise"
        +          ],
        +          "type": "string"
        +        },
        +        "step3Referral": {
        +          "description": "Referral reward method shown in step 3.",
        +          "enum": [
        +            "webhooks",
        +            "zapier",
        +            "paypal",
        +            "tangocard",
        +            "stripe",
        +            "chargebee",
        +            "recurly"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedgrowsurf_get_participant_payout_destination3 fields changed
      • changedOutput schema / properties / activeProvider / description
        Previous value: -"The payout provider currently selected, or `null` until the participant confirms one. Provider identifiers are open-ended; current examples include `PAYPAL` and `WISECOM`."New value: +"The payout provider currently selected, or `null` until the participant confirms one. Provider identifiers are open-ended; current examples include `PAYPAL`, `VENMO`, and `WISECOM`."
      • changedOutput schema / properties / destinations / items / properties / provider / description
        Previous value: -"The payout provider identifier for this entry. Values are open-ended; current examples include `PAYPAL` and `WISECOM`."New value: +"The payout provider identifier for this entry. Values are open-ended; current examples include `PAYPAL`, `VENMO`, and `WISECOM`."
      • changedOutput schema / properties / enabledProviders / description
        Previous value: -"Payout provider identifiers enabled for this program. Values are open-ended; current examples include `PAYPAL` and `WISECOM`."New value: +"Payout provider identifiers enabled for this program. Values are open-ended; current examples include `PAYPAL`, `VENMO`, and `WISECOM`."
    • Changedgrowsurf_request_participant_payout_destination_confirmation2 fields changed
      • changedInput schema / properties / provider / enum
        Previous value: -[
        -  "PAYPAL",
        -  "WISECOM"
        -]New value: +[
        +  "PAYPAL",
        +  "VENMO",
        +  "WISECOM"
        +]
      • changedOutput schema / properties / provider / description
        Previous value: -"The payout provider identifier the participant was asked to confirm. Values are open-ended; current examples include `PAYPAL` and `WISECOM`."New value: +"The payout provider identifier the participant was asked to confirm. Values are open-ended; current examples include `PAYPAL`, `VENMO`, and `WISECOM`."
    • Changedgrowsurf_update_campaign_installation2 fields changed
      • changedInput schema / properties / fields / description
        Previous value: -"Installation fields to patch. Common keys include `shareUrl`, `allowedUrls`, `signupEvent`, `referralTrigger`, and `signup`. Arrays replace wholesale."New value: +"Installation fields to patch. Common keys include `shareUrl`, `allowedUrls`, `signupEvent`, `referralTrigger`, `signup`, and `instructionSelections`. Arrays replace wholesale."
      • addedInput schema / properties / fields / properties / instructionSelections
        Added value: +{
        +  "additionalProperties": true,
        +  "description": "Guide choices. Send only the choices to change.",
        +  "properties": {
        +    "mobileAttributionProvider": {
        +      "enum": [
        +        "branch",
        +        "appsflyer",
        +        "adjust",
        +        "singular",
        +        "other"
        +      ],
        +      "type": "string"
        +    },
        +    "platform": {
        +      "enum": [
        +        "web",
        +        "ios",
        +        "android"
        +      ],
        +      "type": "string"
        +    },
        +    "stepProviders": {
        +      "additionalProperties": true,
        +      "description": "Selected method for each guide step. Available keys depend on program type.",
        +      "properties": {
        +        "step2Affiliate": {
        +          "enum": [
        +            "stripe",
        +            "chargebee",
        +            "recurly",
        +            "restApi"
        +          ],
        +          "type": "string"
        +        },
        +        "step2Referral": {
        +          "enum": [
        +            "restApi",
        +            "zapier",
        +            "stripe",
        +            "chargebee",
        +            "recurly",
        +            "paypal",
        +            "hubspot",
        +            "salesforce"
        +          ],
        +          "type": "string"
        +        },
        +        "step2Signup": {
        +          "enum": [
        +            "restApi",
        +            "javascript"
        +          ],
        +          "type": "string"
        +        },
        +        "step3Affiliate": {
        +          "enum": [
        +            "paypal",
        +            "wise"
        +          ],
        +          "type": "string"
        +        },
        +        "step3Referral": {
        +          "enum": [
        +            "webhooks",
        +            "zapier",
        +            "paypal",
        +            "tangocard",
        +            "stripe",
        +            "chargebee",
        +            "recurly"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    }
        +  },
        +  "type": "object"
        +}
  5. 2 tool updatesv0.19.1
    • Changedgrowsurf_get_campaign_design1 field changed
      • addedOutput schema / properties / trafficInsights
        Added value: +{
        +  "description": "The Traffic report participants can open from the GrowSurf window: visits to their share link over time and where those visits came from. It starts on for new affiliate programs and hidden for referral programs. Every setting is returned, with the default copy for anything not changed. Labels cannot be blank.",
        +  "properties": {
        +    "allLinksLabel": {
        +      "description": "The share link picker option that combines all of the participant's links.",
        +      "type": "string"
        +    },
        +    "backLinkText": {
        +      "description": "The text of the link back from the report.",
        +      "type": "string"
        +    },
        +    "breakdowns": {
        +      "description": "The tables that show where visits came from: `utm`, `referrer`, `destination`, `geo`, `technology`, and `trigger`. Each has `isVisible` and `label`; some also name their levels under `levels` or their fixed rows under `values`.",
        +      "type": "object"
        +    },
        +    "breakdownsTitle": {
        +      "description": "The heading above the breakdown table.",
        +      "type": "string"
        +    },
        +    "dateRangeLabels": {
        +      "description": "The date range picker labels, keyed by `LAST_7_DAYS`, `LAST_30_DAYS`, `LAST_90_DAYS`, and `ALL_TIME`.",
        +      "type": "object"
        +    },
        +    "defaultDateRange": {
        +      "description": "The date range the report opens with.",
        +      "enum": [
        +        "LAST_7_DAYS",
        +        "LAST_30_DAYS",
        +        "LAST_90_DAYS",
        +        "ALL_TIME"
        +      ],
        +      "type": "string"
        +    },
        +    "emptyState": {
        +      "description": "The message shown before the participant's link has any visits. Can be empty.",
        +      "type": "string"
        +    },
        +    "isPublicDisplayed": {
        +      "description": "Whether participants can open the Traffic report.",
        +      "type": "boolean"
        +    },
        +    "messages": {
        +      "description": "Messages shown when the report cannot show everything: `error`, `unavailable`, `partial`, `partialFrom` (`{{date}}` is replaced with the first available date), `breakdownPartial`, and `breakdownEmpty`.",
        +      "type": "object"
        +    },
        +    "metrics": {
        +      "description": "The two visit counts at the top of the report, `visits` and `uniqueVisitors`, each with `isVisible`, `label`, and `helperText`.",
        +      "type": "object"
        +    },
        +    "notSetLabel": {
        +      "description": "The row name for visits that have no value for the chosen breakdown.",
        +      "type": "string"
        +    },
        +    "title": {
        +      "description": "The report heading.",
        +      "type": "string"
        +    },
        +    "trafficForLabel": {
        +      "description": "The label in front of the share link picker.",
        +      "type": "string"
        +    },
        +    "viewTrafficInsightsLinkText": {
        +      "description": "The text of the row or tab that opens the report.",
        +      "type": "string"
        +    },
        +    "visitsOverTimeTitle": {
        +      "description": "The heading above the visits chart.",
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedgrowsurf_list_campaign_rewards1 field changed
      • changedOutput schema / properties / rewards / description
        Previous value: -"The program's active, visible, and enabled reward configs."New value: +"The program's configured Campaign Rewards, including switched-off rewards. Deleted rewards are excluded."
  6. 3 tool updatesv0.18.1
    • Changedgrowsurf_create_campaign2 fields changed
      • changedInput schema / properties / goal / description
        Previous value: -"What the program is for, which seeds share settings that suit that audience. Programs selling to businesses (`CUSTOMERS`, `USERS`, `B2B_SAAS_SELF_SERVICE`, `B2B_SAAS_ENTERPRISE`) start with the LinkedIn share button visible. Consumer, financial, education, insurance, newsletter, and waitlist programs (`B2C_SUBSCRIPTIONS`, `FINANCIAL_SERVICES`, `ONLINE_EDUCATION`, `ONLINE_INSURANCE`, `SUBSCRIBERS`, `WAITLIST`) start with it hidden. Omit `goal` and every share button keeps its standard default. Change any of it afterward with `growsurf_update_campaign_design`. Set only at creation; `growsurf_update_campaign` does not accept it."New value: +"What the program is for, which seeds the share buttons and the starter rewards that suit that audience. Programs whose participants refer other businesses (`CUSTOMERS`, `USERS`, `B2B_SAAS_SELF_SERVICE`, `B2B_SAAS_ENTERPRISE`, `HEALTHCARE_PROVIDERS`) start with the LinkedIn share button visible. Consumer, financial, education, insurance, telehealth, newsletter, and waitlist programs (`B2C_SUBSCRIPTIONS`, `FINANCIAL_SERVICES`, `ONLINE_EDUCATION`, `INSURANCE`, `ONLINE_INSURANCE`, `TELEHEALTH`, `SUBSCRIBERS`, `WAITLIST`) start with it hidden. On a referral program, each goal also sets the rest of its share buttons to suit that audience — a telehealth program keeps the public feeds off, a consumer subscription turns Pinterest and Reddit on; an affiliate program has its own share defaults, so only the LinkedIn default applies to one. When you create a referral program without `rewards`, the goal also decides the starter rewards: most goals get one double-sided reward, `HEALTHCARE_PROVIDERS` gets a single-sided reward, `SUBSCRIBERS` gets a four-step milestone ladder, and `WAITLIST` gets a leaderboard. Every starter reward arrives switched off with a placeholder name, so the program awards nothing until the customer sets the amount and turns one on. `TELEHEALTH` is for consumer telehealth and wellness subscriptions, where patients refer friends; `HEALTHCARE_PROVIDERS` is for provider networks and clinician-facing products, where practices refer peer practices. `INSURANCE` replaces `ONLINE_INSURANCE`, which is still accepted and behaves identically. Omit `goal` and every share button keeps its standard default. Change any of it afterward with `growsurf_update_campaign_design`. Set only at creation; `growsurf_update_campaign` does not accept it."
      • changedInput schema / properties / goal / enum
        Previous value: -[
        -  "CUSTOMERS",
        -  "USERS",
        -  "SUBSCRIBERS",
        -  "WAITLIST",
        -  "B2B_SAAS_SELF_SERVICE",
        -  "B2B_SAAS_ENTERPRISE",
        -  "B2C_SUBSCRIPTIONS",
        -  "FINANCIAL_SERVICES",
        -  "ONLINE_EDUCATION",
        -  "ONLINE_INSURANCE"
        -]New value: +[
        +  "CUSTOMERS",
        +  "USERS",
        +  "SUBSCRIBERS",
        +  "WAITLIST",
        +  "B2B_SAAS_SELF_SERVICE",
        +  "B2B_SAAS_ENTERPRISE",
        +  "B2C_SUBSCRIPTIONS",
        +  "FINANCIAL_SERVICES",
        +  "ONLINE_EDUCATION",
        +  "INSURANCE",
        +  "ONLINE_INSURANCE",
        +  "TELEHEALTH",
        +  "HEALTHCARE_PROVIDERS"
        +]
    • Changedgrowsurf_get_campaign_design2 fields changed
      • addedOutput schema / properties / theme / properties / widget
        Added value: +{
        +  "description": "Paid-plan color settings for the website widget.",
        +  "properties": {
        +    "backgroundColor": {
        +      "description": "Fill color of the button, and of the card's own button.",
        +      "maxLength": 255,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "borderRadius": {
        +      "description": "Corner rounding, as a CSS length such as `12px`.",
        +      "maxLength": 255,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "color": {
        +      "description": "Text and drawing color on the button, and on the card's own button.",
        +      "maxLength": 255,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / widget
        Added value: +{
        +  "description": "The website widget — the invite that sits in a corner of the customer's own site. It renders as a button or as a card, and its card folds back into the button when a visitor closes it. Both audience switches start off, so a program shows nothing until one is turned on.",
        +  "properties": {
        +    "appearance": {
        +      "description": "`BUTTON` is a single button in the corner. `CARD` is a small card with a heading, a line of text, and a button, which a visitor can close.",
        +      "enum": [
        +        "BUTTON",
        +        "CARD"
        +      ],
        +      "type": "string"
        +    },
        +    "artImageUrl": {
        +      "description": "The picture shown at the top of the card.",
        +      "maxLength": 500,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "buttonText": {
        +      "description": "The label on the card's button, which opens the program.",
        +      "maxLength": 100,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "icon": {
        +      "description": "An uploaded image instead of a `markKey` drawing. `CUSTOM` uses `iconImageUrl`; `NONE` shows no image. `DEFAULT` is the old GrowSurf image: a program already set to it keeps it and can read it back, but it cannot be set. Requires a paid plan.",
        +      "enum": [
        +        "CUSTOM",
        +        "NONE",
        +        "DEFAULT"
        +      ],
        +      "type": "string"
        +    },
        +    "iconImageUrl": {
        +      "description": "The uploaded image, used when `icon` is `CUSTOM`. Requires a paid plan.",
        +      "maxLength": 500,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "isArtShown": {
        +      "description": "Whether the card shows a picture above its text. Ignored by the button.",
        +      "type": "boolean"
        +    },
        +    "isHiddenOnMobile": {
        +      "description": "Whether to leave phones alone. On small screens the card fills the bottom of the page.",
        +      "type": "boolean"
        +    },
        +    "isShownToNewVisitors": {
        +      "description": "Whether people who have not joined the program see the widget.",
        +      "type": "boolean"
        +    },
        +    "isShownToParticipants": {
        +      "description": "Whether people who have already joined see the widget.",
        +      "type": "boolean"
        +    },
        +    "markKey": {
        +      "description": "The small drawing on the widget. It takes the colour chosen for the widget, so it matches on any background. `null` for no drawing.",
        +      "enum": [
        +        "GIFT",
        +        "TICKET",
        +        "DISCOUNT",
        +        "CASH",
        +        "PERK",
        +        "SHARE",
        +        "LINK",
        +        "INVITE",
        +        "FRIENDS",
        +        "THANKS",
        +        null
        +      ],
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "newVisitorDescription": {
        +      "description": "The line under the heading for people who have not joined. Card only.",
        +      "maxLength": 255,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "newVisitorText": {
        +      "description": "What people who have not joined read. It is the button's label, and the card's heading.",
        +      "maxLength": 100,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "offsetEdge": {
        +      "description": "How far in from the top or bottom edge, in pixels, following `placement`. Raise it to clear a chat button that already sits in that corner.",
        +      "maximum": 400,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "offsetSide": {
        +      "description": "How far in from the left or right edge, in pixels, following `placement`. For a centered placement it becomes an even gap on both sides.",
        +      "maximum": 400,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "pageRules": {
        +      "description": "Which pages the widget appears on. This controls the widget only — referral tracking, embedded elements, and opening the window from the site's own code keep working on every page where GrowSurf is installed.",
        +      "properties": {
        +        "mode": {
        +          "description": "`ALL` shows it everywhere. `ONLY` shows it just on the listed pages. `EXCEPT` shows it everywhere but the listed pages. With no pages listed, `ONLY` and `EXCEPT` behave as `ALL`.",
        +          "enum": [
        +            "ALL",
        +            "ONLY",
        +            "EXCEPT"
        +          ],
        +          "type": "string"
        +        },
        +        "patterns": {
        +          "description": "The pages to match. Use `*` to stand in for anything, as in `/portal/*`. A path on its own, such as `/pricing`, matches that path on every installed domain.",
        +          "items": {
        +            "maxLength": 500,
        +            "type": "string"
        +          },
        +          "maxItems": 20,
        +          "type": "array"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "participantDescription": {
        +      "description": "The line under the heading for people who have already joined. Card only.",
        +      "maxLength": 255,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "participantText": {
        +      "description": "What people who have already joined read. It is the button's label, and the card's heading.",
        +      "maxLength": 100,
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "placement": {
        +      "description": "Which corner or edge of the page the widget sits against.",
        +      "enum": [
        +        "TOP_LEFT",
        +        "TOP_CENTER",
        +        "TOP_RIGHT",
        +        "BOTTOM_LEFT",
        +        "BOTTOM_CENTER",
        +        "BOTTOM_RIGHT"
        +      ],
        +      "type": "string"
        +    },
        +    "returnAfterDays": {
        +      "description": "Days before the card is offered again to someone who closed it. Until then they keep the button, so they can still open the program. `0` never offers it again.",
        +      "maximum": 365,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "reveal": {
        +      "description": "When the card appears: right away, after `revealDelaySeconds`, or once the visitor scrolls halfway down the page. The button always appears right away.",
        +      "enum": [
        +        "IMMEDIATE",
        +        "DELAY",
        +        "SCROLL"
        +      ],
        +      "type": "string"
        +    },
        +    "revealDelaySeconds": {
        +      "description": "Seconds to wait before showing the card, when `reveal` is `DELAY`.",
        +      "maximum": 120,
        +      "minimum": 0,
        +      "type": "integer"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedgrowsurf_get_participant1 field changed
      • addedOutput schema / properties / leadCount
        Added value: +{
        +  "description": "Pending referrals that have not converted yet.",
        +  "type": "integer"
        +}
  7. 1 tool updatev0.16.0
    • Changedgrowsurf_list_participants1 field changed
      • addedInput schema / properties / metadata
        Added value: +{
        +  "additionalProperties": {
        +    "type": "string"
        +  },
        +  "description": "Exact-match filter on participant metadata, up to 3 keys, for example `{ \"customerId\": \"12345\" }`. Values compare as strings.",
        +  "maxProperties": 3,
        +  "minProperties": 1,
        +  "type": "object"
        +}
  8. 1 tool updatev0.15.1
    • Changedgrowsurf_bulk_delete_participants2 fields changed
      • changedOutput schema / description
        Previous value: -"Bulk delete outcome. A `200` response can still include `NOT_FOUND` or `ERROR` rows, so check the summary."New value: +"Bulk delete outcome. A `202` response includes `analyticsErasure` when analytics erasure is pending. Both `200` and `202` responses can include `NOT_FOUND` or `ERROR` rows, so check the summary."
      • addedOutput schema / properties / analyticsErasure
        Added value: +{
        +  "description": "Analytics erasure is pending. Reports can retain removed participants until erasure completes. Do not repeat successful deletions.",
        +  "properties": {
        +    "operationId": {
        +      "description": "Opaque reference for support inquiries about this analytics erasure.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "Erasure has been accepted but is not confirmed complete.",
        +      "enum": [
        +        "pending"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
  9. 27 tool updatesv0.14.0
    • Changedgrowsurf_create_campaign2 fields changed
      • addedInput schema / properties / goal
        Added value: +{
        +  "description": "What the program is for, which seeds share settings that suit that audience. Programs selling to businesses (`CUSTOMERS`, `USERS`, `B2B_SAAS_SELF_SERVICE`, `B2B_SAAS_ENTERPRISE`) start with the LinkedIn share button visible. Consumer, financial, education, insurance, newsletter, and waitlist programs (`B2C_SUBSCRIPTIONS`, `FINANCIAL_SERVICES`, `ONLINE_EDUCATION`, `ONLINE_INSURANCE`, `SUBSCRIBERS`, `WAITLIST`) start with it hidden. Omit `goal` and every share button keeps its standard default. Change any of it afterward with `growsurf_update_campaign_design`. Set only at creation; `growsurf_update_campaign` does not accept it.",
        +  "enum": [
        +    "CUSTOMERS",
        +    "USERS",
        +    "SUBSCRIBERS",
        +    "WAITLIST",
        +    "B2B_SAAS_SELF_SERVICE",
        +    "B2B_SAAS_ENTERPRISE",
        +    "B2C_SUBSCRIPTIONS",
        +    "FINANCIAL_SERVICES",
        +    "ONLINE_EDUCATION",
        +    "ONLINE_INSURANCE"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / rewards / description
        Added value: +"Rewards to create with the program. Include this only when the person told you the amount and who funds it. Omit it and the program is seeded with starter rewards that are switched off, awarding nothing until the customer enables one. Send `[]` to start with no rewards at all."
    • Changedgrowsurf_create_campaign_reward5 fields changed
      • addedInput schema / properties / commissionStructure / allOf
        Added value: +[
        +  {
        +    "if": {
        +      "properties": {
        +        "event": {
        +          "enum": [
        +            "CLICK",
        +            "LEAD"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "event"
        +      ]
        +    },
        +    "then": {
        +      "properties": {
        +        "amount": {
        +          "minimum": 1,
        +          "type": "integer"
        +        },
        +        "type": {
        +          "enum": [
        +            "FIXED"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "amount"
        +      ]
        +    }
        +  }
        +]
      • changedInput schema / properties / commissionStructure / description
        Previous value: -"Affiliate commission structure (AFFILIATE rewards only). Provide `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission."New value: +"Affiliate commission structure (AFFILIATE rewards only). Provide a positive `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission. CLICK and LEAD commissions must use FIXED."
      • addedInput schema / properties / commissionStructure / properties / amount / minimum
        Added value: +1
      • addedInput schema / properties / commissionStructure / properties / event / description
        Added value: +"The affiliate event that earns the commission. `CLICK` and `LEAD` must use `FIXED`."
      • addedInput schema / properties / event
        Added value: +{
        +  "description": "The referral event that earns this Campaign Reward. Use `LEAD` for a referred signup or `CONVERSION` for a qualifying action. A `LEAD` reward requires a later custom conversion trigger. Referral reward types only.",
        +  "enum": [
        +    "LEAD",
        +    "CONVERSION"
        +  ],
        +  "type": "string"
        +}
    • Addedgrowsurf_create_program_resource
    • Addedgrowsurf_delete_program_resource
    • Changedgrowsurf_get_campaign1 field changed
      • addedOutput schema / properties / rewardEvidence
        Added value: +{
        +  "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.",
        +  "properties": {
        +    "approvalPolicy": {
        +      "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.",
        +      "enum": [
        +        "manual",
        +        "automatic",
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "automaticFulfillmentMarking": {
        +      "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.",
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "basis": {
        +      "enum": [
        +        "this_response_only"
        +      ],
        +      "type": "string"
        +    },
        +    "conclusion": {
        +      "type": "string"
        +    },
        +    "deliveryStatus": {
        +      "enum": [
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "integrationConnection": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    },
        +    "nextStep": {
        +      "type": "string"
        +    },
        +    "programReferralTrigger": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Addedgrowsurf_get_campaign_activation_analytics
    • Changedgrowsurf_get_campaign_analytics4 fields changed
      • changedInput schema / properties / include / description
        Previous value: -"Comma-separated optional data: `previousPeriod`, `statusCounts`, `rates`, and `email`. Combine `email` with `previousPeriod` or a non-total `interval` to receive matching email metrics for those windows."New value: +"Comma-separated optional data: `previousPeriod`, `statusCounts`, `rates`, `email`, and `engagement`. Combine values when the question needs more than one view."
      • addedInput schema / properties / platform
        Added value: +{
        +  "description": "Client-platform filter for engagement. Defaults to `ALL`.",
        +  "enum": [
        +    "ALL",
        +    "WEB",
        +    "IOS",
        +    "ANDROID"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / timezone
        Added value: +{
        +  "description": "IANA timezone for engagement interval and distinct-day calculations. Used with `include=engagement`.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / engagement
        Added value: +{
        +  "description": "Opt-in participant engagement grouped by when activity occurred.",
        +  "properties": {
        +    "breakdowns": {
        +      "description": "Engagement grouped by platform, portal source, and share channel.",
        +      "properties": {
        +        "firstShareChannels": {
        +          "items": {
        +            "properties": {
        +              "key": {
        +                "description": "Stable first-share channel key.",
        +                "type": "string"
        +              },
        +              "sharingParticipants": {
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "platforms": {
        +          "items": {
        +            "properties": {
        +              "activeParticipants": {
        +                "type": "integer"
        +              },
        +              "key": {
        +                "enum": [
        +                  "WEB",
        +                  "IOS",
        +                  "ANDROID"
        +                ],
        +                "type": "string"
        +              },
        +              "portalViews": {
        +                "type": "integer"
        +              },
        +              "shareActions": {
        +                "type": "integer"
        +              },
        +              "sharingParticipants": {
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "portalViewSources": {
        +          "items": {
        +            "properties": {
        +              "activeParticipants": {
        +                "type": "integer"
        +              },
        +              "key": {
        +                "enum": [
        +                  "DEFAULT_LAUNCHER",
        +                  "SDK_OPEN",
        +                  "CSS_CLASS",
        +                  "EMBEDDABLE_ELEMENT",
        +                  "HOSTED_PORTAL",
        +                  "NATIVE_WINDOW",
        +                  "UNKNOWN"
        +                ],
        +                "type": "string"
        +              },
        +              "portalViews": {
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "shareChannels": {
        +          "items": {
        +            "properties": {
        +              "key": {
        +                "description": "Stable share-channel key.",
        +                "type": "string"
        +              },
        +              "shareActions": {
        +                "type": "integer"
        +              },
        +              "sharingParticipants": {
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "comparison": {
        +      "description": "Current-versus-previous engagement changes.",
        +      "properties": {
        +        "metrics": {
        +          "properties": {
        +            "activeParticipants": {
        +              "description": "Change in unique active participants.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "portalViews": {
        +              "description": "Change in total signed-in portal views.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "repeatActiveParticipants": {
        +              "description": "Change in repeat active participants.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "repeatSharingParticipants": {
        +              "description": "Change in repeat sharing participants.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "shareActions": {
        +              "description": "Change in total accepted share actions.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "sharingParticipants": {
        +              "description": "Change in unique sharing participants.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            }
        +          },
        +          "type": [
        +            "object",
        +            "null"
        +          ]
        +        },
        +        "reason": {
        +          "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +          "enum": [
        +            "COVERAGE_UNAVAILABLE",
        +            "PRE_COVERAGE",
        +            "PARTIAL_COVERAGE",
        +            "INSUFFICIENT_COVERAGE",
        +            "EMPTY_DENOMINATOR",
        +            "QUERY_LIMIT_EXCEEDED",
        +            "PARTICIPANT_NOT_ELIGIBLE",
        +            null
        +          ],
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "state": {
        +          "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +          "enum": [
        +            "AVAILABLE",
        +            "PARTIAL",
        +            "UNAVAILABLE"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "coverageStartAt": {
        +      "description": "Earliest expected complete capture time (Unix ms), or `null` until coverage begins.",
        +      "type": [
        +        "integer",
        +        "null"
        +      ]
        +    },
        +    "interval": {
        +      "description": "Bucket size used for `series`.",
        +      "enum": [
        +        "day",
        +        "week",
        +        "month"
        +      ],
        +      "type": "string"
        +    },
        +    "metricContractVersion": {
        +      "description": "Shared activation and engagement metric version.",
        +      "type": "integer"
        +    },
        +    "period": {
        +      "description": "Exact half-open current and previous activity bounds.",
        +      "properties": {
        +        "effectiveFrom": {
        +          "description": "Measured start after coverage, or `null`.",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "from": {
        +          "description": "Inclusive requested activity start (Unix ms).",
        +          "type": "integer"
        +        },
        +        "previousFrom": {
        +          "description": "Inclusive previous-period start (Unix ms).",
        +          "type": "integer"
        +        },
        +        "previousTo": {
        +          "description": "Exclusive previous-period end (Unix ms).",
        +          "type": "integer"
        +        },
        +        "to": {
        +          "description": "Exclusive requested activity end (Unix ms).",
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "platform": {
        +      "description": "Requested and applied client-platform filter.",
        +      "properties": {
        +        "applied": {
        +          "enum": [
        +            "ALL",
        +            "WEB",
        +            "IOS",
        +            "ANDROID"
        +          ],
        +          "type": "string"
        +        },
        +        "requested": {
        +          "enum": [
        +            "ALL",
        +            "WEB",
        +            "IOS",
        +            "ANDROID"
        +          ],
        +          "type": "string"
        +        },
        +        "state": {
        +          "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +          "enum": [
        +            "AVAILABLE",
        +            "PARTIAL",
        +            "UNAVAILABLE"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "previousPeriod": {
        +      "description": "Engagement totals for the immediately previous equal activity period.",
        +      "properties": {
        +        "reason": {
        +          "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +          "enum": [
        +            "COVERAGE_UNAVAILABLE",
        +            "PRE_COVERAGE",
        +            "PARTIAL_COVERAGE",
        +            "INSUFFICIENT_COVERAGE",
        +            "EMPTY_DENOMINATOR",
        +            "QUERY_LIMIT_EXCEEDED",
        +            "PARTICIPANT_NOT_ELIGIBLE",
        +            null
        +          ],
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "state": {
        +          "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +          "enum": [
        +            "AVAILABLE",
        +            "PARTIAL",
        +            "UNAVAILABLE"
        +          ],
        +          "type": "string"
        +        },
        +        "totals": {
        +          "description": "Unique participant metrics and action totals for one activity period.",
        +          "properties": {
        +            "activeParticipants": {
        +              "description": "Eligible participants with a signed-in portal view.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "portalViews": {
        +              "description": "Total accepted signed-in portal-view actions.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "repeatActiveParticipants": {
        +              "description": "Eligible participants active on at least two distinct program-local days.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "repeatSharingParticipants": {
        +              "description": "Eligible participants who shared on at least two distinct program-local days.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "retainedActiveParticipants": {
        +              "description": "Eligible participants active in both the current and previous equal periods.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "shareActions": {
        +              "description": "Total accepted referral-link share actions.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "sharingParticipants": {
        +              "description": "Eligible participants with an accepted share action.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "sharingRate": {
        +              "description": "Sharing participants divided by active participants.",
        +              "properties": {
        +                "delta": {
        +                  "description": "Optional current-minus-previous difference on comparison metrics.",
        +                  "type": "number"
        +                },
        +                "reason": {
        +                  "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +                  "enum": [
        +                    "COVERAGE_UNAVAILABLE",
        +                    "PRE_COVERAGE",
        +                    "PARTIAL_COVERAGE",
        +                    "INSUFFICIENT_COVERAGE",
        +                    "EMPTY_DENOMINATOR",
        +                    "QUERY_LIMIT_EXCEEDED",
        +                    "PARTICIPANT_NOT_ELIGIBLE",
        +                    null
        +                  ],
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                },
        +                "state": {
        +                  "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +                  "enum": [
        +                    "AVAILABLE",
        +                    "PARTIAL",
        +                    "UNAVAILABLE"
        +                  ],
        +                  "type": "string"
        +                },
        +                "value": {
        +                  "description": "Measured value, or `null` when unavailable.",
        +                  "type": [
        +                    "number",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            }
        +          },
        +          "type": [
        +            "object",
        +            "null"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "programType": {
        +      "description": "Program eligibility model.",
        +      "enum": [
        +        "REFERRAL",
        +        "AFFILIATE"
        +      ],
        +      "type": "string"
        +    },
        +    "reason": {
        +      "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +      "enum": [
        +        "COVERAGE_UNAVAILABLE",
        +        "PRE_COVERAGE",
        +        "PARTIAL_COVERAGE",
        +        "INSUFFICIENT_COVERAGE",
        +        "EMPTY_DENOMINATOR",
        +        "QUERY_LIMIT_EXCEEDED",
        +        "PARTICIPANT_NOT_ELIGIBLE",
        +        null
        +      ],
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "series": {
        +      "description": "Continuous half-open activity intervals in ascending order.",
        +      "items": {
        +        "properties": {
        +          "activeParticipants": {
        +            "description": "Unique active participants.",
        +            "type": "integer"
        +          },
        +          "from": {
        +            "description": "Inclusive interval start (Unix ms).",
        +            "type": "integer"
        +          },
        +          "portalViews": {
        +            "description": "Total signed-in portal views.",
        +            "type": "integer"
        +          },
        +          "shareActions": {
        +            "description": "Total accepted share actions.",
        +            "type": "integer"
        +          },
        +          "sharingParticipants": {
        +            "description": "Unique sharing participants.",
        +            "type": "integer"
        +          },
        +          "to": {
        +            "description": "Exclusive interval end (Unix ms).",
        +            "type": "integer"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "state": {
        +      "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +      "enum": [
        +        "AVAILABLE",
        +        "PARTIAL",
        +        "UNAVAILABLE"
        +      ],
        +      "type": "string"
        +    },
        +    "timezone": {
        +      "description": "IANA timezone used for interval and distinct-day calculations.",
        +      "type": "string"
        +    },
        +    "totals": {
        +      "description": "Unique participant metrics and action totals for one activity period.",
        +      "properties": {
        +        "activeParticipants": {
        +          "description": "Eligible participants with a signed-in portal view.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "portalViews": {
        +          "description": "Total accepted signed-in portal-view actions.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "repeatActiveParticipants": {
        +          "description": "Eligible participants active on at least two distinct program-local days.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "repeatSharingParticipants": {
        +          "description": "Eligible participants who shared on at least two distinct program-local days.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "retainedActiveParticipants": {
        +          "description": "Eligible participants active in both the current and previous equal periods.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "shareActions": {
        +          "description": "Total accepted referral-link share actions.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "sharingParticipants": {
        +          "description": "Eligible participants with an accepted share action.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "sharingRate": {
        +          "description": "Sharing participants divided by active participants.",
        +          "properties": {
        +            "delta": {
        +              "description": "Optional current-minus-previous difference on comparison metrics.",
        +              "type": "number"
        +            },
        +            "reason": {
        +              "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +              "enum": [
        +                "COVERAGE_UNAVAILABLE",
        +                "PRE_COVERAGE",
        +                "PARTIAL_COVERAGE",
        +                "INSUFFICIENT_COVERAGE",
        +                "EMPTY_DENOMINATOR",
        +                "QUERY_LIMIT_EXCEEDED",
        +                "PARTICIPANT_NOT_ELIGIBLE",
        +                null
        +              ],
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "state": {
        +              "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +              "enum": [
        +                "AVAILABLE",
        +                "PARTIAL",
        +                "UNAVAILABLE"
        +              ],
        +              "type": "string"
        +            },
        +            "value": {
        +              "description": "Measured value, or `null` when unavailable.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        }
        +      },
        +      "type": "object"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedgrowsurf_get_campaign_design5 fields changed
      • addedOutput schema / properties / participantAvatarStyle
        Added value: +{
        +  "description": "How participant avatars appear in the GrowSurf Window. New programs use `CHARACTERS`; missing or unknown stored values return `INITIALS`.",
        +  "enum": [
        +    "CHARACTERS",
        +    "INITIALS",
        +    "ANIMALS",
        +    "GRADIENT"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / properties / referredExperience / description
        Previous value: -"The banner and headline shown to a visitor who arrives through a referral link."New value: +"The banner, headline, and Claim Offer Popup shown to a visitor who arrives through a referral link. The popup is available for referral and affiliate programs."
      • addedOutput schema / properties / referredExperience / properties
        Added value: +{
        +  "isOfferPopupConfettiEnabled": {
        +    "description": "Whether to show confetti after a claim.",
        +    "type": "boolean"
        +  },
        +  "isOfferPopupEnabled": {
        +    "description": "Whether referred visitors see the Claim Offer Popup.",
        +    "type": "boolean"
        +  },
        +  "isOfferPopupOverlayDimmed": {
        +    "description": "Whether a centered popup dims the page behind it.",
        +    "type": "boolean"
        +  },
        +  "isOfferPopupReferrerImageShown": {
        +    "description": "Whether to show the referrer's profile image.",
        +    "type": "boolean"
        +  },
        +  "isOfferPopupShownOnAllPages": {
        +    "description": "Whether the popup can appear on every installed page.",
        +    "type": "boolean"
        +  },
        +  "offerPopupButtonText": {
        +    "description": "Offer-save button text.",
        +    "maxLength": 100,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "offerPopupDelaySeconds": {
        +    "description": "Delay before the popup appears.",
        +    "enum": [
        +      0,
        +      3,
        +      5,
        +      10
        +    ],
        +    "type": "integer"
        +  },
        +  "offerPopupDescription": {
        +    "description": "Text below the popup heading.",
        +    "maxLength": 255,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "offerPopupImageUrl": {
        +    "description": "Optional popup image.",
        +    "maxLength": 500,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "offerPopupPlacement": {
        +    "description": "Where the popup appears.",
        +    "enum": [
        +      "CENTER",
        +      "BOTTOM",
        +      "BOTTOM_RIGHT",
        +      "BOTTOM_LEFT",
        +      "TOP"
        +    ],
        +    "type": "string"
        +  },
        +  "offerPopupSecondaryLinkText": {
        +    "description": "Optional post-claim link text.",
        +    "maxLength": 100,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "offerPopupSecondaryLinkUrl": {
        +    "description": "Optional post-claim link destination. When saving, use `http://` or `https://`. Send `null` or an empty string to clear it.",
        +    "maxLength": 255,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "offerPopupThankYouButtonText": {
        +    "description": "Post-claim signup button text.",
        +    "maxLength": 100,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "offerPopupThankYouText": {
        +    "description": "Message shown after the offer is saved.",
        +    "maxLength": 255,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  },
        +  "offerPopupTitle": {
        +    "description": "Popup heading.",
        +    "maxLength": 255,
        +    "type": [
        +      "string",
        +      "null"
        +    ]
        +  }
        +}
      • addedOutput schema / properties / resources
        Added value: +{
        +  "description": "Participant Resources presentation settings: visibility, title, link and copy labels, the message shown when nothing is published, and the section icon. Resource items use the program Resource tools.",
        +  "type": "object"
        +}
      • addedOutput schema / properties / theme / properties
        Added value: +{
        +  "referredExperienceOfferPopup": {
        +    "description": "Paid-plan color settings for the Claim Offer Popup.",
        +    "properties": {
        +      "backgroundColor": {
        +        "description": "Popup background color.",
        +        "maxLength": 255,
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "color": {
        +        "description": "Popup text color.",
        +        "maxLength": 255,
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "type": "object"
        +  }
        +}
    • Changedgrowsurf_get_campaign_emails1 field changed
      • addedOutput schema / properties / offerClaimed
        Added value: +{
        +  "description": "Sent when a referred visitor saves an offer through the Claim Offer Popup. Referral and affiliate programs. Promotional; its toggle can be changed.",
        +  "type": "object"
        +}
    • Changedgrowsurf_get_campaign_options2 fields changed
      • changedOutput schema / properties / autoFulfillRewards / description
        Previous value: -"Referral programs only. Automatically mark earned rewards as fulfilled."New value: +"Referral programs only. Automatically mark earned rewards as fulfilled. `false` permits manual fulfillment and does not establish a delivery failure."
      • addedOutput schema / properties / rewardEvidence
        Added value: +{
        +  "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.",
        +  "properties": {
        +    "approvalPolicy": {
        +      "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.",
        +      "enum": [
        +        "manual",
        +        "automatic",
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "automaticFulfillmentMarking": {
        +      "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.",
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "basis": {
        +      "enum": [
        +        "this_response_only"
        +      ],
        +      "type": "string"
        +    },
        +    "conclusion": {
        +      "type": "string"
        +    },
        +    "deliveryStatus": {
        +      "enum": [
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "integrationConnection": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    },
        +    "nextStep": {
        +      "type": "string"
        +    },
        +    "programReferralTrigger": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedgrowsurf_get_integration_connect_link5 fields changed
      • changedInput schema / properties / integration / enum
        Previous value: -[
        -  "stripe",
        -  "chargebee",
        -  "recurly",
        -  "paypal",
        -  "wisecom",
        -  "tangocard",
        -  "hubspot",
        -  "salesforce",
        -  "marketo",
        -  "mailchimp",
        -  "activecampaign",
        -  "bentonow",
        -  "mailerlite",
        -  "resenddotcom",
        -  "loopsdotso",
        -  "convertkit",
        -  "constantContact",
        -  "campaignMonitor",
        -  "aweber",
        -  "klaviyo",
        -  "mailjet",
        -  "sendgrid",
        -  "sendinblue",
        -  "emailoctopus",
        -  "customerio",
        -  "getresponse",
        -  "drip",
        -  "googleanalytics",
        -  "segmentanalytics",
        -  "posthoganalytics",
        -  "mixpanelanalytics",
        -  "pendo",
        -  "fullstory",
        -  "heapanalytics",
        -  "amplitude",
        -  "googleads",
        -  "metaads",
        -  "linkedinads",
        -  "twitterads",
        -  "slack",
        -  "intercom",
        -  "helpScout",
        -  "zapier",
        -  "integromat",
        -  "pabblyConnect",
        -  "webhook",
        -  "baskHealth"
        -]New value: +[
        +  "stripe",
        +  "chargebee",
        +  "recurly",
        +  "paypal",
        +  "wisecom",
        +  "tangoCard",
        +  "tremendous",
        +  "hubspot",
        +  "salesforce",
        +  "marketo",
        +  "mailchimp",
        +  "activecampaign",
        +  "braze",
        +  "bentonow",
        +  "mailerlite",
        +  "resenddotcom",
        +  "loopsdotso",
        +  "convertkit",
        +  "constantContact",
        +  "campaignMonitor",
        +  "aweber",
        +  "klaviyo",
        +  "mailjet",
        +  "sendgrid",
        +  "sendinblue",
        +  "emailoctopus",
        +  "customerio",
        +  "getresponse",
        +  "drip",
        +  "googleanalytics",
        +  "segmentanalytics",
        +  "posthoganalytics",
        +  "mixpanelanalytics",
        +  "pendo",
        +  "fullstory",
        +  "heapanalytics",
        +  "amplitude",
        +  "googleads",
        +  "metaads",
        +  "linkedinads",
        +  "twitterads",
        +  "slack",
        +  "intercom",
        +  "helpScout",
        +  "zapier",
        +  "integromat",
        +  "pabblyConnect",
        +  "webhook",
        +  "baskHealth",
        +  "tangocard"
        +]
      • addedOutput schema / properties / autoDisabled
        Added value: +{
        +  "description": "Whether GrowSurf switched the integration off after repeated delivery failures. Present only when `programVerified` is `true`.",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / connected
        Added value: +{
        +  "description": "Whether the program has stored credentials for this integration. Present only when `programVerified` is `true`.",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / enabled
        Added value: +{
        +  "description": "Whether the integration is switched on and currently working. Present only when `programVerified` is `true`.",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / programVerified
        Added value: +{
        +  "description": "`true` when the program's live integration list was read, so the program id is confirmed and the three state fields below are present and current. `false` when that read was unavailable, for example without an API key or `program:read`: the link still works but points at the production dashboard, and the state fields are omitted because the state is unknown. Never treat an absent state field as `false`.",
        +  "type": "boolean"
        +}
    • Changedgrowsurf_get_participant5 fields changed
      • addedOutput schema / properties / rewardEvidence
        Added value: +{
        +  "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.",
        +  "properties": {
        +    "approvalPolicy": {
        +      "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.",
        +      "enum": [
        +        "manual",
        +        "automatic",
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "automaticFulfillmentMarking": {
        +      "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.",
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "basis": {
        +      "enum": [
        +        "this_response_only"
        +      ],
        +      "type": "string"
        +    },
        +    "conclusion": {
        +      "type": "string"
        +    },
        +    "deliveryStatus": {
        +      "enum": [
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "integrationConnection": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    },
        +    "nextStep": {
        +      "type": "string"
        +    },
        +    "programReferralTrigger": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / rewards / items / properties / fulfilledAt / description
        Previous value: -"When the reward was fulfilled, as a Unix timestamp in milliseconds. `null` until fulfilled."New value: +"When the reward was marked fulfilled, as a Unix timestamp in milliseconds. `null` until marked fulfilled; this is not a delivery receipt."
      • changedOutput schema / properties / rewards / items / properties / isFulfilled / description
        Previous value: -"`true` once the reward has been fulfilled."New value: +"`true` once the reward is marked fulfilled. Confirm actual delivery through fulfillment records."
      • changedOutput schema / properties / rewards / items / properties / status / description
        Previous value: -"Fulfillment status of the earned reward."New value: +"Fulfillment marking of the earned reward. `FULFILLED` records that it was marked fulfilled, not proof of delivery. `CANCELLED` means an unpaid Lead reward was reversed before fulfillment."
      • changedOutput schema / properties / rewards / items / properties / status / enum
        Previous value: -[
        -  "PENDING",
        -  "FULFILLED"
        -]New value: +[
        +  "PENDING",
        +  "FULFILLED",
        +  "CANCELLED"
        +]
    • Changedgrowsurf_get_participant_analytics9 fields changed
      • addedInput schema / properties / days / description
        Added value: +"Number of days for optional `series` and `email` analytics. Does not filter the all-time base response."
      • changedInput schema / properties / endDate / description
        Previous value: -"End of the timeframe, Unix timestamp in ms."New value: +"End of the optional-data timeframe, Unix timestamp in ms. Use with `startDate`."
      • changedInput schema / properties / include / description
        Previous value: -"Comma-separated optional data. Current values are `series` and `email`; the API returns `400` for unknown values."New value: +"Comma-separated optional data. Current values are `series`, `email`, and `activation`; the API returns `400` for unknown values."
      • changedInput schema / properties / startDate / description
        Previous value: -"Start of the timeframe, Unix timestamp in ms. Use with endDate instead of days."New value: +"Start of the optional-data timeframe, Unix timestamp in ms. Use with `endDate` instead of `days`."
      • addedOutput schema / properties / activation
        Added value: +{
        +  "description": "Opt-in covered eligibility and first-milestone analytics for one participant.",
        +  "properties": {
        +    "cohort": {
        +      "description": "Program-specific eligibility anchor and covered value.",
        +      "properties": {
        +        "anchorAt": {
        +          "description": "Covered anchor time (Unix ms). `null` is unknown and does not mean enrollment never occurred.",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "anchorField": {
        +          "enum": [
        +            "enrolledAsAdvocateAt",
        +            "approvedAsAffiliateAt"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "coverageStartAt": {
        +      "description": "Earliest expected complete participant activation capture time (Unix ms).",
        +      "type": [
        +        "integer",
        +        "null"
        +      ]
        +    },
        +    "enrolledAsAdvocateAt": {
        +      "description": "Referral only. Covered advocate enrollment (Unix ms); `null` does not mean enrollment never occurred.",
        +      "type": [
        +        "integer",
        +        "null"
        +      ]
        +    },
        +    "metricContractVersion": {
        +      "description": "Shared activation and engagement metric version.",
        +      "type": "integer"
        +    },
        +    "milestones": {
        +      "description": "Covered first milestones. A `null` value is unknown and does not mean the action never happened.",
        +      "properties": {
        +        "firstCommissionAt": {
        +          "description": "Affiliate only. First covered commission (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "firstLeadAt": {
        +          "description": "First covered referred lead (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "firstPortalViewedAt": {
        +          "description": "First covered signed-in portal view (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "firstReferralAt": {
        +          "description": "First covered credited referral (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "firstReferralLinkCopiedAt": {
        +          "description": "First covered referral-link copy (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "firstRewardAt": {
        +          "description": "Referral only. First covered participant reward (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "firstShareAt": {
        +          "description": "First covered accepted share action (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "firstShareChannel": {
        +          "description": "Channel for `firstShareAt`, or `null` when the first covered share is unavailable.",
        +          "enum": [
        +            "email",
        +            "facebook",
        +            "twitter",
        +            "linkedin",
        +            "pinterest",
        +            "threads",
        +            "bluesky",
        +            "sms",
        +            "messenger",
        +            "whatsapp",
        +            "wechat",
        +            "telegram",
        +            "reddit",
        +            "tumblr",
        +            "qrcode",
        +            "copyRefLink",
        +            "iosNativeShare",
        +            "androidNativeShare",
        +            null
        +          ],
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "firstUniqueClickAt": {
        +          "description": "First covered unique referral visit (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "payoutSetupCompletedAt": {
        +          "description": "First covered payout-setup completion (Unix ms).",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "programType": {
        +      "description": "Program eligibility model.",
        +      "enum": [
        +        "REFERRAL",
        +        "AFFILIATE"
        +      ],
        +      "type": "string"
        +    },
        +    "reason": {
        +      "description": "Why a value is partial or unavailable, or `null` when it is available.",
        +      "enum": [
        +        "COVERAGE_UNAVAILABLE",
        +        "PRE_COVERAGE",
        +        "PARTIAL_COVERAGE",
        +        "INSUFFICIENT_COVERAGE",
        +        "EMPTY_DENOMINATOR",
        +        "QUERY_LIMIT_EXCEEDED",
        +        "PARTICIPANT_NOT_ELIGIBLE",
        +        null
        +      ],
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "state": {
        +      "description": "Whether the value is complete, partial, or unavailable for the requested bounds.",
        +      "enum": [
        +        "AVAILABLE",
        +        "PARTIAL",
        +        "UNAVAILABLE"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / analytics / description
        Previous value: -"Participant analytics totals."New value: +"All-time participant analytics totals. Date-window parameters do not filter these fields."
      • changedOutput schema / properties / analytics / properties / leads / description
        Previous value: -"Pending referral credits."New value: +"Current pending referral credits."
      • addedOutput schema / properties / series / items / properties / portalViews
        Added value: +{
        +  "description": "Covered signed-in portal views, or `null` outside known coverage.",
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / series / items / properties / shareActions
        Added value: +{
        +  "description": "Covered accepted share actions, or `null` outside known coverage.",
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
    • Changedgrowsurf_list_campaign_rewards2 fields changed
      • addedOutput schema / properties / rewardEvidence
        Added value: +{
        +  "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.",
        +  "properties": {
        +    "approvalPolicy": {
        +      "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.",
        +      "enum": [
        +        "manual",
        +        "automatic",
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "automaticFulfillmentMarking": {
        +      "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.",
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "basis": {
        +      "enum": [
        +        "this_response_only"
        +      ],
        +      "type": "string"
        +    },
        +    "conclusion": {
        +      "type": "string"
        +    },
        +    "deliveryStatus": {
        +      "enum": [
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "integrationConnection": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    },
        +    "nextStep": {
        +      "type": "string"
        +    },
        +    "programReferralTrigger": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / rewards / items / properties / event
        Added value: +{
        +  "description": "The referral event that earns this Campaign Reward. `LEAD` means a referred signup; `CONVERSION` means a qualifying action.",
        +  "enum": [
        +    "LEAD",
        +    "CONVERSION",
        +    null
        +  ],
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Addedgrowsurf_list_integrations
    • Changedgrowsurf_list_participants1 field changed
      • addedOutput schema / properties / rewardEvidence
        Added value: +{
        +  "description": "What this response establishes about rewards. Combine with other reads; unknown here does not override evidence elsewhere.",
        +  "properties": {
        +    "approvalPolicy": {
        +      "description": "Referral reward approval policy from requireManualRewardApproval, not affiliate commission approval or an individual reward state.",
        +      "enum": [
        +        "manual",
        +        "automatic",
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "automaticFulfillmentMarking": {
        +      "description": "The autoFulfillRewards setting, when returned by an options read. Null means unknown; this controls marking, not delivery.",
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "basis": {
        +      "enum": [
        +        "this_response_only"
        +      ],
        +      "type": "string"
        +    },
        +    "conclusion": {
        +      "type": "string"
        +    },
        +    "deliveryStatus": {
        +      "enum": [
        +        "unknown"
        +      ],
        +      "type": "string"
        +    },
        +    "integrationConnection": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    },
        +    "nextStep": {
        +      "type": "string"
        +    },
        +    "programReferralTrigger": {
        +      "enum": [
        +        "not_established"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Addedgrowsurf_list_program_resources
    • Addedgrowsurf_prepare_program_resource_file
    • Addedgrowsurf_program_design_advisor
    • Changedgrowsurf_record_sale3 fields changed
      • changedInput schema / allOf
        Previous value: -[
        -  {
        -    "anyOf": [
        -      {
        -        "required": [
        -          "participantId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "participantEmail"
        -        ]
        -      }
        -    ]
        -  },
        -  {
        -    "anyOf": [
        -      {
        -        "required": [
        -          "externalId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "transactionId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "orderId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "paymentId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "invoiceId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "paymentIntentId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "chargeId"
        -        ]
        -      }
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "anyOf": [
        +      {
        +        "required": [
        +          "participantId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "participantEmail"
        +        ]
        +      }
        +    ]
        +  },
        +  {
        +    "anyOf": [
        +      {
        +        "required": [
        +          "externalId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "transactionId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "orderId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "paymentId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "invoiceId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "paymentIntentId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "chargeId"
        +        ]
        +      }
        +    ]
        +  },
        +  {
        +    "if": {
        +      "required": [
        +        "paymentProvider"
        +      ]
        +    },
        +    "then": {
        +      "required": [
        +        "testMode",
        +        "transactionId"
        +      ]
        +    }
        +  },
        +  {
        +    "if": {
        +      "not": {
        +        "required": [
        +          "paymentProvider"
        +        ]
        +      }
        +    },
        +    "then": {
        +      "not": {
        +        "required": [
        +          "testMode"
        +        ]
        +      }
        +    }
        +  }
        +]
      • addedInput schema / properties / paymentProvider
        Added value: +{
        +  "description": "Connected provider for this payment. Requires `transactionId` and `testMode`. Supply matching `grossAmount` and `currency`; other payment IDs and tax or net-amount overrides are not accepted. GrowSurf reads payment details from the provider and detects duplicate webhook/API/manual submissions.",
        +  "enum": [
        +    "stripe",
        +    "chargebee",
        +    "recurly"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / testMode
        Added value: +{
        +  "description": "Required with `paymentProvider`: `true` for test or `false` for live. Otherwise omit.",
        +  "type": "boolean"
        +}
    • Changedgrowsurf_refund_transaction6 fields changed
      • changedInput schema / allOf
        Previous value: -[
        -  {
        -    "anyOf": [
        -      {
        -        "required": [
        -          "participantId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "participantEmail"
        -        ]
        -      }
        -    ]
        -  },
        -  {
        -    "anyOf": [
        -      {
        -        "required": [
        -          "externalId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "transactionId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "orderId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "paymentId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "invoiceId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "paymentIntentId"
        -        ]
        -      },
        -      {
        -        "required": [
        -          "chargeId"
        -        ]
        -      }
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "anyOf": [
        +      {
        +        "required": [
        +          "participantId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "participantEmail"
        +        ]
        +      }
        +    ]
        +  },
        +  {
        +    "anyOf": [
        +      {
        +        "required": [
        +          "externalId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "transactionId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "orderId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "paymentId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "invoiceId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "paymentIntentId"
        +        ]
        +      },
        +      {
        +        "required": [
        +          "chargeId"
        +        ]
        +      }
        +    ]
        +  },
        +  {
        +    "if": {
        +      "required": [
        +        "paymentProvider"
        +      ]
        +    },
        +    "then": {
        +      "required": [
        +        "testMode",
        +        "transactionId"
        +      ]
        +    }
        +  },
        +  {
        +    "if": {
        +      "not": {
        +        "required": [
        +          "paymentProvider"
        +        ]
        +      }
        +    },
        +    "then": {
        +      "not": {
        +        "required": [
        +          "testMode"
        +        ]
        +      }
        +    }
        +  }
        +]
      • addedInput schema / properties / paymentProvider
        Added value: +{
        +  "description": "Connected provider for the original payment. Requires its `transactionId` and `testMode`. This amends GrowSurf records without sending a refund through the provider.",
        +  "enum": [
        +    "stripe",
        +    "chargebee",
        +    "recurly"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / refundAmount / description
        Added value: +"Positive amount for this individual refund, no greater than the sale amount, in the sale currency's minor unit. Send it with `refundId` on each original refund to support cancellations and out-of-order amendments. The amount for a given `refundId` cannot change. A cancellation can omit it when the original amount is already recorded. Incomplete refund history returns `409` without applying the cancellation. Newly observed higher cumulative refunds and incomplete coverage are retained for reconciliation."
      • addedInput schema / properties / refundHistoryComplete
        Added value: +{
        +  "description": "Set true only after reconciling and recording every original refundId and refundAmount, including refunds later canceled. This confirmation resolves previously incomplete history. Omit during ordinary delivery. Replaying an old confirmation cannot resolve a later gap; confirm a newly reconciled refund or complete provider list.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / refundId / description
        Added value: +"Stable per-refund identifier. Required when canceling a refund or changing the refunded total after a cancellation. Reuse the original refund's identifier for its cancellation. An amendment without enough refund identity returns `409` without applying the cancellation. Newly observed higher cumulative refunds and incomplete coverage are retained for reconciliation."
      • addedInput schema / properties / testMode
        Added value: +{
        +  "description": "Original payment mode: `true` for test or `false` for live. Requires `paymentProvider`.",
        +  "type": "boolean"
        +}
    • Addedgrowsurf_troubleshoot_referral_tracking
    • Changedgrowsurf_update_campaign1 field changed
      • addedInput schema / anyOf
        Added value: +[
        +  {
        +    "required": [
        +      "name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "companyName"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "companyLogoImageUrl"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "status"
        +    ]
        +  }
        +]
    • Changedgrowsurf_update_campaign_installation1 field changed
      • addedInput schema / properties / replaceExistingShareUrl
        Added value: +{
        +  "description": "Set this to `true` only after the customer confirms they want a different landing page. Without it, a patch that would replace a Share URL that is already set is refused.",
        +  "type": "boolean"
        +}
    • Changedgrowsurf_update_campaign_reward5 fields changed
      • addedInput schema / properties / commissionStructure / allOf
        Added value: +[
        +  {
        +    "if": {
        +      "properties": {
        +        "event": {
        +          "enum": [
        +            "CLICK",
        +            "LEAD"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "event"
        +      ]
        +    },
        +    "then": {
        +      "properties": {
        +        "amount": {
        +          "minimum": 1,
        +          "type": "integer"
        +        },
        +        "type": {
        +          "enum": [
        +            "FIXED"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "amount"
        +      ]
        +    }
        +  }
        +]
      • changedInput schema / properties / commissionStructure / description
        Previous value: -"Affiliate commission structure (AFFILIATE rewards only). Provide `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission."New value: +"Affiliate commission structure (AFFILIATE rewards only). Provide a positive `amount` (+ optional `amountISO`) for a FIXED commission, or `percent` for a PERCENT commission. CLICK and LEAD commissions must use FIXED."
      • addedInput schema / properties / commissionStructure / properties / amount / minimum
        Added value: +1
      • addedInput schema / properties / commissionStructure / properties / event / description
        Added value: +"The affiliate event that earns the commission. `CLICK` and `LEAD` must use `FIXED`."
      • addedInput schema / properties / event
        Added value: +{
        +  "description": "The referral event that earns this Campaign Reward. Use `LEAD` for a referred signup or `CONVERSION` for a qualifying action. A `LEAD` reward requires a later custom conversion trigger. Referral reward types only.",
        +  "enum": [
        +    "LEAD",
        +    "CONVERSION"
        +  ],
        +  "type": "string"
        +}
    • Changedgrowsurf_update_campaign_webhook1 field changed
      • addedInput schema / anyOf
        Added value: +[
        +  {
        +    "required": [
        +      "payloadUrl"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "events"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "secret"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "isEnabled"
        +    ]
        +  }
        +]
    • Addedgrowsurf_update_program_resource
  10. 54 tool updatesv0.12.2
    • First observedgrowsurf_add_participant
    • First observedgrowsurf_agent_program_creation_eval
    • First observedgrowsurf_api_library_snippets
    • First observedgrowsurf_bulk_delete_participants
    • First observedgrowsurf_cancel_delayed_referral
    • First observedgrowsurf_capture_referral_flow_screenshots
    • First observedgrowsurf_client_snippets
    • First observedgrowsurf_clone_campaign
    • First observedgrowsurf_create_account
    • First observedgrowsurf_create_campaign
    • First observedgrowsurf_create_campaign_reward
    • First observedgrowsurf_create_campaign_webhook
    • First observedgrowsurf_create_mobile_participant_token
    • First observedgrowsurf_delete_campaign_reward
    • First observedgrowsurf_delete_campaign_webhook
    • First observedgrowsurf_email_participant
    • First observedgrowsurf_embeddable_element_snippet
    • First observedgrowsurf_get_campaign
    • First observedgrowsurf_get_campaign_analytics
    • First observedgrowsurf_get_campaign_design
    • First observedgrowsurf_get_campaign_emails
    • First observedgrowsurf_get_campaign_installation
    • First observedgrowsurf_get_campaign_options
    • First observedgrowsurf_get_integration_connect_link
    • First observedgrowsurf_get_participant
    • First observedgrowsurf_get_participant_activity_logs
    • First observedgrowsurf_get_participant_analytics
    • First observedgrowsurf_get_participant_payout_destination
    • First observedgrowsurf_get_team
    • First observedgrowsurf_grsf_config_snippet
    • First observedgrowsurf_integration_guide
    • First observedgrowsurf_list_campaign_rewards
    • First observedgrowsurf_list_campaign_webhooks
    • First observedgrowsurf_list_campaigns
    • First observedgrowsurf_list_participants
    • First observedgrowsurf_mobile_sdk_guide
    • First observedgrowsurf_participant_auth_hash
    • First observedgrowsurf_record_sale
    • First observedgrowsurf_refund_transaction
    • First observedgrowsurf_request_participant_payout_destination_confirmation
    • First observedgrowsurf_request_team_verification
    • First observedgrowsurf_resend_team_owner_verification_email
    • First observedgrowsurf_test_campaign_webhook
    • First observedgrowsurf_trigger_referral
    • First observedgrowsurf_update_campaign
    • First observedgrowsurf_update_campaign_design
    • First observedgrowsurf_update_campaign_emails
    • First observedgrowsurf_update_campaign_installation
    • First observedgrowsurf_update_campaign_options
    • First observedgrowsurf_update_campaign_reward
    • First observedgrowsurf_update_campaign_webhook
    • First observedgrowsurf_update_participant
    • First observedgrowsurf_update_team
    • First observedgrowsurf_webhook_normalize

TDQS

A3.7/5.0

Scored across 63 tools

Disambiguation4/5

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.

Naming Consistency4/5

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.

Tool Count2/5

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.

Completeness5/5

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

ActivityActive
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    C
    maintenance
    Enables users to manage affiliate marketing directly within Claude by connecting to the Affilync platform. Affiliates can search campaigns and track earnings, while brands can create campaigns, monitor performance, and manage affiliate applications through natural language.
    20
    1
    -
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI agents to access affiliate marketing capabilities through AgentFuse's API, allowing them to browse affiliate programs, generate tracked links, and record conversions without writing HTTP code.
    7
    40 npm
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    Enables AI agents to automate sales outreach, research leads, and manage campaigns directly in OutreachPilot via natural language commands.
    31
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to manage GoHighLevel workspaces through natural language, with 508 tools across 18 domains for complete CRM, marketing, and workflow automation.
    Apache 2.0