VYG Docs

Changelog

Changes to the VYG API, MCP server and documentation, newest first.

2026-10-01

Email tools for AI assistants. Brands with email enabled can run the email channel from an assistant connected to https://agents-mcp.vyg.app/mcp: sending domains, templates with variables, test sends to your own inbox, abandoned checkout and other automated emails with an Email or Resend step, segments, scheduled broadcasts and deliverability monitoring. Saved templates are live immediately once they pass the template checks. See Email tools.

Business address and catalog sync for email tools. email_brand_address_get and email_brand_address_set read and save the postal address that every marketing email shows. Going live needs one. You can also set it in VYG under Settings → Email. email_catalog_sync_request queues a full product catalog sync. Template saves from an assistant now follow the same rules as saves in VYG: an edit that would overwrite a newer save is refused. See Email tools.

2026-09-28

Collection error format changed. Update integrations that read error responses. Errors from POST /cdp/events and POST /cdp/ingest on https://cdp.vyg.app are now {"error": {"code", "message"}}, the same format and codes as api.vyg.app, instead of {"error": "<code>", "error_description": "..."}. Success responses are unchanged.

  • batch_too_large, scope_binding and payload_too_large are bad_request. The size limit keeps its 413 status, and a scope-binding rejection still lists the events in rejected.
  • forbidden is insufficient_scope, internal_error is internal, and service_unavailable is unavailable.
  • service_unavailable_partial is a 503 unavailable that carries accepted and failed next to error. Resend only the events listed in failed.
  • Error responses with the envelope carry an X-Request-Id header, which browsers can send and read.
  • Some responses use a {"message": "..."} body: 404 for a method or path the host does not serve, 429 for the rate limit, and 500 or 503 when a request cannot be completed. Check the status, and read error.code only when the body has an error object.

The web pixel, the Shopify pixel and Shopify's compliance webhooks read only the status, so they need no change. Server integrations that read the error string on /cdp/events need to read error.code. Every old code and its replacement is in the migration guide. See Collect errors.

One list envelope, snake_case fields and cursor paging (breaking). A clean break with no aliases: old field names, old query parameters and old tool arguments are not accepted and not returned. Every change is listed in the migration guide.

  • One list envelope. Every list returns { data, next_cursor }. next_cursor is null on the last page and on lists that return everything at once. The other envelopes are gone: { data, nextCursor }, { list, totalSize, offset, pageSize, scope, nextCursor }, { list, scope }, { eventTypes, scope }, { properties, catalogVersion }, { insights, totalCount }, { workflows, totalCount } and the conversation search and insight conversation envelopes. Segment members keep generation and the customer field catalog has catalog_version beside the page.
  • Cursors instead of offsets. Commerce orders and subscriptions, customers at risk, conversation insights and the conversations for an insight take cursor (the previous page's next_cursor). The offset parameter is removed, and totalSize, pageSize, offset, scope, totalCount, totalFound and limit are no longer returned on lists.
  • Unknown list parameters are refused. Every list refuses a parameter or tool argument it does not take, such as offset, with 400 bad_request instead of ignoring it. GET /v1/segments pages with cursor too.
  • limit over 100 is a 400. Commerce orders, subscriptions and products and customers at risk answer 400 bad_request for a limit over 100; they used to reduce it to 100.
  • Single records are bare. Get a conversation or contact; get, create and update a provider or an event definition; and create, rotate and revoke a key return the record itself instead of { "data": { ... } }.
  • snake_case everywhere. Every query parameter, path parameter, body field, MCP tool argument and response key is snake_case. Path parameters are {provider_id} and {definition_id}, the /v1/keys parameter is key_class, and list_customers sorts by total_spend, orders_count, created_at, last_order_at or last_event_at.
  • MCP tool arguments. read_shopify, mutate_shopify and query_shopify take api_version (was apiVersion); learn_shopify_api, search_shopify_docs and validate_shopify_graphql take conversation_id (was conversationId); and validate_shopify_graphql takes codeblocks[].artifact_id (was artifactId).
  • Opaque values keep their inner keys: segment definition, event type schema, provider settings, event definition payload_schema and identifier_mappings, campaign rules and goals, checkout line_items and discount_codes, and the Shopify and Klaviyo payloads. The error envelope is unchanged.

Renamed fields by resource (old → new):

ResourceRenamed fields
Conversations and messagescreatedAt → created_at, updatedAt → updated_at, lastEngagedAt → last_engaged_at, lastReceivedAt → last_received_at, awaitingReply → awaiting_reply, cartValue → cart_value, cartCurrency → cart_currency, checkoutState → checkout_state, lastMessage → last_message, sentAt → sent_at, scheduledFor → scheduled_for
ContactsgivenName → given_name, familyName → family_name, acceptsSmsMarketing → accepts_sms_marketing, createdAt → created_at, updatedAt → updated_at
Conversation searchconversationId → conversation_id, textContent → text_content
get_conversation_detailscreatedAt → created_at, scheduledFor → scheduled_for, sentAt → sent_at, goalStateChanges → goal_state_changes, totalPrice → total_price, lineItems → line_items, discountCodes → discount_codes
ProviderslookupId → lookup_id, sourceTemplateKey → source_template_key, isEnabled → is_enabled, apiKey → api_key, webhookSecret → webhook_secret, webhookUrl → webhook_url
Event definitionsproviderId → provider_id, payloadSchema → payload_schema, identifierMappings → identifier_mappings, schemaVersion → schema_version, sourceTemplateKey → source_template_key, isEnabled → is_enabled, createdAt → created_at, updatedAt → updated_at
API keyskeyClass → key_class, firstKey → first_key, keyPrefix → key_prefix, brandId → brand_id, createdAt → created_at, lastUsedAt → last_used_at, expiresAt → expires_at, revokedAt → revoked_at
CustomerscreatedAt → created_at, ordersCount → orders_count, totalSpend → total_spend, totalRefunded → total_refunded, lastOrderAt → last_order_at, coverageFrom → coverage_from, events30d → events_30d, sessions30d → sessions_30d, productViews30d → product_views_30d, lastEventAt → last_event_at, mergedCustomerIds → merged_customer_ids, firstOrderAt → first_order_at
Customer activityeventKey → event_key, occurredAt → occurred_at, eventType → event_type, sourceSystem → source_system, entityKind → entity_kind, entityKey → entity_key, productKey → product_key, pagePath → page_path, pageTitle → page_title, referrerHost → referrer_host, utmSource → utm_source, utmMedium → utm_medium, utmCampaign → utm_campaign, sessionId → session_id
Customer orders and subscriptionsorderKey → order_key, subscriptionKey → subscription_key, sourceSystem → source_system, financialStatus → financial_status, fulfillmentStatus → fulfillment_status, billingInterval → billing_interval, nextBillingAt → next_billing_at, lineId → line_id, productKey → product_key, variantKey → variant_key, unitPrice → unit_price
Customer fieldscatalogVersion → catalog_version, readOnlyReason → read_only_reason
SegmentscurrentVersionId → current_version_id, createdBy → created_by, evaluationStatus → evaluation_status, memberCount → member_count, evaluatedAt → evaluated_at, lastRunAt → last_run_at, currentVersionEvaluated → current_version_evaluated, schemaVersion → schema_version, segmentId → segment_id, estimatedAt → estimated_at
Segment members and historycustomerId → customer_id, lrContactId → lr_contact_id, joinedAt → joined_at, currentCustomerId → current_customer_id, changedAt → changed_at
Productsimages[].altText → images[].alt_text
Brand (get_brand)companyWebsite → company_website, supportEmail → support_email, supportPhone → support_phone, escalationEmail → escalation_email, tosUrl → tos_url, privacyPolicyUrl → privacy_policy_url, faqPageUrl → faq_page_url, reEngagePeriod → re_engage_period, createdAt → created_at, planName → plan_name, planPrice → plan_price, usageChargePercentage → usage_charge_percentage, billingEmail → billing_email, paymentProvider → payment_provider, isEnabled → is_enabled, lookupId → lookup_id
Conversation insightsupdatedAt → updated_at, conversationId → conversation_id, createdAt → created_at, checkoutState → checkout_state, messagePreview → message_preview
Performance stats and campaign comparisoncurrentValue → current_value, previousValue → previous_value, comparisonChart → comparison_chart, dateRange → date_range, compareFrom → compare_from, compareTo → compare_to, brandId → brand_id, isPaused → is_paused, workflows → campaigns (comparison)
CampaignsisPaused → is_paused, startsAt → starts_at, endsAt → ends_at, delayMinutes → delay_minutes, delayType → delay_type, weekDays → week_days, specificTime → specific_time, nodeId → node_id, externalId → external_id, agentReply → agent_reply, replyWithMessage → reply_with_message, contactSupport → contact_support, supportEmail → support_email, flowMessages → flow_messages, knowledgeBase → knowledge_base
search_klaviyo_docsresultCount → result_count, operationId → operation_id, docUrl → doc_url, guideTopics → guide_topics, endpointFamilies → endpoint_families

Commerce orders and subscriptions, customers at risk, integrations and event types kept their item fields; only their list envelope changed. Message variants, discounts, campaign writes, campaign building options and the LTV, RFM and top-products reports are unchanged.

2026-09-27

Routes, tools and permissions renamed. Update existing integrations.

  • Campaign reads moved to /v1/campaigns: GET /v1/campaigns, GET /v1/campaigns/{campaign_id} and GET /v1/campaigns/compare (was POST /v1/workflows/compare).
  • Performance stats are GET /v1/stats (was POST /v1/dashboard/stats).
  • Conversation search is GET /v1/conversations/search (was GET /v1/search/conversations), and customer search takes query instead of q.
  • The customer field catalog is GET /v1/customers/fields (was GET /v1/traits).
  • The RFM tool is get_rfm_tiers (was get_customer_segments).
  • Parameters these routes and tools take are snake_case: campaign_id, campaign_ids, include_historical, compare_from, compare_to, day_limit, insight_id and conversation_id.
  • The old tool names from 2026-09-26 (list_workflows, customers_get and the rest) no longer work.
  • Scopes: workflows:read is campaigns:read and dashboard:read is stats:read. Existing sign-ins keep their access. Campaign building options accept campaigns:read or campaigns:write.

The old paths answer 404. Every change is listed in the migration guide.

API fixes.

  • A temporary failure in a LiveRecover read, such as performance stats or conversation search, now returns 500 internal or 503 unavailable instead of 400 bad_request.
  • GET /v1/commerce/orders/{id} and get_order accept the id that list_orders returns, as well as the Shopify order id.
  • GET /v1/providers and list_providers return an empty list, not 404, for a brand with no providers.
  • POST /v1/providers no longer returns a vyg_live_ key that api.vyg.app refused. Called with a sign-in token that has keys:manage, it returns a vyg_ba_ apiKey with providers:read and providers:write; called with an API key or any other token, apiKey is null.
  • The dashboard no longer shows a vyg_live_ value as a provider's API key. Connecting the integration, adding a provider and regenerating a provider's credentials issue a vyg_ba_ key with providers:read and providers:write, the key POST /v1/providers returns. Regenerating issues the new key before it revokes the old one. A user who is not a brand admin gets no key: adding a provider creates it without one, and regenerating replaces only the webhook secret and keeps the current key.
  • The per-brand provider limit answers 409 with the new code limit_reached instead of 429 rate_limited. See Errors.
  • The OpenAPI document types every limit and offset as an integer, and documents the fields of the brand, conversation insights, conversation search, performance stats, campaign and customer insights responses.

Documentation moved to docs.vyg.ai. Browse by task: Get started, Connect an AI assistant, REST API, Data collection, Custom Integration and this changelog. Every old page URL redirects to its new page.

  • The REST reference now covers every /v1 route, grouped by area, and marks the operations that need a sign-in.
  • The tool catalog lists all available MCP tools.
  • The OpenAPI document at https://api.vyg.app/v1/openapi.json now has a summary, description and tag for each operation, plus x-mcp-tool, x-scopes and x-oauth-only.

2026-09-26

One API at api.vyg.app. The REST API and the MCP server now run on one host:

  • REST: https://api.vyg.app/v1
  • MCP: https://api.vyg.app/mcp

It replaces:

RetiredReplacement
mcp.vyg.apphttps://api.vyg.app/mcp
cdp-mcp.vyg.apphttps://api.vyg.app/mcp
cdp.vyg.app read routeshttps://api.vyg.app/v1
brand-api.vyg.apphttps://api.vyg.app/v1. brand-api.vyg.app is being retired.

cdp.vyg.app stays up for event collection only (/cdp/ingest, /cdp/events, /cdp/vyg.js).

One MCP server. The conversation, campaign and analytics tools and the customer-data tools are on the same server. What a connection can use depends on its scopes, not on which server it connects to.

Renamed MCP tools. Tools now follow a verb_noun pattern, and campaign tools use "campaign" instead of "workflow", for example list_workflows is now list_campaigns and customers_get is now get_customer. The old names stopped working on 2026-09-27. The full list is in the migration guide.

Scopes. Sign-in tokens carry granular scopes such as customers:read and campaigns:write. mcp:tools, mcp:read and mcp:write are still accepted when signing in and expand to granular scopes. API keys carry a scope list chosen when they are created. See Scopes.

Saved segments on api.vyg.app. List, create, change, archive and estimate segments, and read their members and history, over /v1/segments and the matching MCP tools. See the Segments reference.

See the migration guide for what to change.

On this page