{"openapi":"3.1.0","info":{"title":"DigitalPublic Agent API","version":"1.0.0","description":"API for external AI agents to interact with DigitalPublic projects. Provides discovery, project context, Google Ads, Meta Ads, LinkedIn organic and LinkedIn Ads, Merchant Center, SEO, AEO, Search Console, WordPress, Analytics, Tag Manager, Business Profile, mailings, CRM, comments, reports, and scheduling.","contact":{"email":"soporte@digitalpublic.com"}},"servers":[{"url":"https://platform.digitalpublic.com","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Project API key starting with dpk_ or global agent token starting with dpa_. dpa_ requests must include projectId or X-DigitalPublic-Project-Id for project-scoped endpoints."}},"schemas":{"AgentRequest":{"type":"object","required":["tool"],"properties":{"tool":{"type":"string","description":"Tool name to execute"},"params":{"type":"object","description":"Tool-specific parameters","default":{}},"projectId":{"type":"string","description":"Required when using a dpa_ global agent token. dpk_ project API keys infer the project automatically."}}},"AgentResponse":{"type":"object","properties":{"ok":{"type":"boolean"},"data":{"type":"object"},"error":{"type":"string"}}}}},"paths":{"/api/agent/discover":{"post":{"summary":"Discover project capabilities","description":"Master discovery endpoint for external agents. Project API keys (dpk_) return the linked project. Global agent tokens (dpa_) return accessible projects when projectId is omitted, or project discovery when projectId/X-DigitalPublic-Project-Id is provided. Answers in two levels: with no parameters it returns the map (identity, active and inactive services, credential usage and one `areas[]` entry per available area); with `area` it returns that chapter in full in `endpoints[]` (tools, parameters, examples and flows). A service that is not connected never ships its tool manual — `project.activeServices.inactive[]` still declares that it exists and how to request activation.","tags":["Discovery"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","description":"Required for global agent tokens (dpa_) that need project-specific discovery."},"area":{"type":"string","description":"Return the full chapter of a single area instead of the map. Valid values are listed in `areas[].area` of the default response, for example googleAds, seo, analytics, mailings, tasks or reports. `module` is accepted as an alias."},"detail":{"type":"string","enum":["summary","full"],"description":"`summary` (default) returns the map. `full` returns every area at once and is discouraged: it is an order of magnitude larger and can consume a quarter of an agent context window."}}}}}},"responses":{"200":{"description":"Project map by default, or the requested area chapter / the full catalog"},"400":{"description":"UNKNOWN_DISCOVERY_AREA — the requested area does not exist; the response lists the valid ones"}}}},"/api/agent/projects":{"get":{"summary":"List accessible projects","description":"Lists the projects accessible with the presented credential, with per-project scopes. Project API keys (dpk_) return exactly their linked project; agent tokens (dpa_) return every project they can use (all current projects for global agents, or the explicit access list). Does not require projectId — call it first to learn which project ids you can use in the rest of the API.","tags":["Discovery"],"responses":{"200":{"description":"Accessible projects with per-project scopes"}}},"post":{"summary":"List accessible projects","description":"POST alias of GET /api/agent/projects for agents that send every request as POST.","tags":["Discovery"],"responses":{"200":{"description":"Accessible projects with per-project scopes"}}}},"/api/agent/navigator":{"post":{"summary":"Ask DigitalPublic Navigator, report a product signal or list the ones already reported","description":"Find implemented capabilities, plan non-executing workflows, check connections and scopes, explain errors, summarize a project, record deduplicated product feedback, or list the product signals already reported for this project with their status and resolution note. Navigator recommendations never execute operational writes by themselves.","tags":["Navigator"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["operation"],"properties":{"projectId":{"type":"string","description":"Required in the header/query for global agent tokens."},"operation":{"type":"string","enum":["ask","find_capabilities","plan_workflow","check_readiness","explain_error","summarize_project","report_product_signal","list_product_signals"]},"query":{"type":"string","maxLength":20000},"sessionId":{"type":"string","maxLength":200,"description":"Stable isolated Navigator session. Reuse the returned sessionId for follow-up context."},"status":{"type":"string","enum":["open","resolved","dismissed","all"],"description":"Only for list_product_signals. Defaults to all."},"limit":{"type":"integer","minimum":1,"maximum":25}}}}}},"responses":{"200":{"description":"Structured Navigator result with an isolated reusable session id"},"202":{"description":"Product signal recorded or routed"}}}},"/api/connections/agent-query":{"post":{"summary":"Discover and inspect provider connections","description":"Lists connectable providers, requirements, statuses, assets, approval actions and health. Connection discovery is a core capability and remains available before a business module is connected, and also for projects that are not linked to a commercial account yet (those are served in read-only legacy mode, with connection ids prefixed by 'legacy:').","tags":["Connections"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Connection information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"list_tools","description":"List Connection Center tools.","params":{},"x-mcp":{"channel":"connections","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_available_connections","description":"List all supported providers, modes, requirements, readiness and project entitlement state.","params":{},"x-mcp":{"channel":"connections","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_connection_requirements","description":"Explain human prerequisites, scopes and consent policy for one connector.","params":{"connectorKey":{"type":"string","required":true}},"x-mcp":{"channel":"connections","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_connection_status","description":"List connection states for the selected project. Works for projects without a commercial account: their existing integrations are returned in read-only legacy mode.","params":{"provider":{"type":"string","optional":true}},"x-mcp":{"channel":"connections","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_connection_assets","description":"List provider assets discovered under a project connection.","params":{"connectionId":{"type":"string","required":true}},"x-mcp":{"channel":"connections","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_connection_actions","description":"List supervised connection actions and their approval status.","params":{"limit":{"type":"number","optional":true}},"x-mcp":{"channel":"connections","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"test_connection","description":"Check token expiry, assets and local health state without mutating the provider.","params":{"connectionId":{"type":"string","required":true}},"x-mcp":{"channel":"connections","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}],"x-mcp":{"channel":"connections","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}},"/api/connections/agent-mutate":{"post":{"summary":"Start and supervise provider connections","description":"Agents may initiate onboarding and continue after human consent. OAuth consent is restricted to human account owners/admins. Disconnect requests are always supervised. Requires the project to be linked to a commercial account (409 COMMERCIAL_ACCOUNT_REQUIRED otherwise); reading connections does not.","tags":["Connections"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Connection workflow result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"start_connection","description":"Create a session and return humanAuthorizationUrl. Never request OAuth tokens in chat.","params":{"connectorKey":{"type":"string","required":true},"mode":{"type":"string","enum":["OAUTH","MANAGED","BYO","PAIRING"],"optional":true},"permission":{"type":"string","enum":["read","write"],"optional":true},"desiredAssetId":{"type":"string","optional":true},"desiredAssetName":{"type":"string","optional":true},"desiredDomain":{"type":"string","optional":true},"returnUrl":{"type":"string","optional":true}},"x-mcp":{"channel":"connections","effect":"write","requiredScope":"read","approval":"human","requestShape":"tool_params"}},{"name":"select_connection_asset","description":"Bind a selected asset to the project after consent.","params":{"assetId":{"type":"string","required":true},"module":{"type":"string","required":true},"permission":{"type":"string","enum":["read","write"],"optional":true}},"x-mcp":{"channel":"connections","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"request_disconnect","description":"Create a supervised disconnect request. Credentials remain active until approval and execution.","params":{"connectionId":{"type":"string","required":true},"reason":{"type":"string","optional":true},"idempotencyKey":{"type":"string","required":true}},"x-mcp":{"channel":"connections","effect":"write","requiredScope":"read","approval":"human","requestShape":"tool_params"}},{"name":"execute_approved_connection_action","description":"Execute an action only after OWNER/ADMIN approval.","params":{"actionId":{"type":"string","required":true}},"x-mcp":{"channel":"connections","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}}],"x-mcp":{"channel":"connections","effect":"write","requiredScope":"read","approval":"human","requestShape":"tool_params"}}},"/api/portfolio/agent-query":{"post":{"summary":"Portfolio-wide pending work","description":"Aggregated operational queue for every project within the effective global or group dpa_ credential. Uses bounded set queries, live freshness metadata and safe partial-failure codes. Project API keys and agents with only explicit project access are rejected.","tags":["Portfolio"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Portfolio summary or paginated detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"portfolio_pending_summary","description":"Return task, CRM, site issue, mutation, editorial review and email pending counts for all accessible projects. Distinguishes ok, disabled, not_configured and safe error coverage states.","params":{"asOf":{"type":"string","optional":true,"description":"Authoritative ISO instant. Defaults to now."},"timezone":{"type":"string","optional":true,"description":"IANA timezone used to calculate today. Defaults to Europe/Madrid."},"projectStatus":{"type":"string","enum":["active","inactive","all"],"optional":true,"description":"Defaults to active."},"groupId":{"type":"string","optional":true,"description":"Restrict to an accessible group."},"include":{"type":"array","items":{"type":"string","enum":["tasks","crm","siteIssues","mutations","revisionRequests","emails"]},"optional":true},"staleDays":{"type":"number","optional":true,"description":"CRM stale threshold, 1-365. Defaults to 7."},"actionableIssuesOnly":{"type":"boolean","optional":true,"description":"Use the actionable issue subset when deciding attention. Raw counts are always retained."},"countsOnly":{"type":"boolean","optional":true,"description":"Return compact project identities, counts and coverage."}},"x-mcp":{"channel":"portfolio","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"portfolio_pending_items","description":"Return a cursor-paginated, PII-minimized detail page for one portfolio category. The project set is always derived from the effective credential.","params":{"category":{"type":"string","required":true,"enum":["tasks","crm","siteIssues","mutations","revisionRequests","emails"]},"asOf":{"type":"string","optional":true},"timezone":{"type":"string","optional":true},"projectStatus":{"type":"string","enum":["active","inactive","all"],"optional":true},"projectId":{"type":"string","optional":true,"description":"May only narrow to an already accessible project."},"groupId":{"type":"string","optional":true,"description":"May only narrow to an already accessible group."},"status":{"type":"string","optional":true},"severity":{"type":"string","optional":true},"from":{"type":"string","optional":true},"to":{"type":"string","optional":true},"staleDays":{"type":"number","optional":true},"actionableIssuesOnly":{"type":"boolean","optional":true},"cursor":{"type":"string","optional":true,"description":"Opaque cursor from the previous response."},"limit":{"type":"number","optional":true,"description":"1-100, default 50."}},"x-mcp":{"channel":"portfolio","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"portfolio_agent_supervision_summary","description":"Return a snapshot-consistent health summary for scheduled agents and tasks across every accessible project. Includes task and execution states, stale runs, repeated blockers, current failures, start-delay and duration percentiles, trace completeness, pending human actions, safe coverage and partial failures.","params":{"asOf":{"type":"string","optional":true,"description":"Authoritative ISO instant shared with detail calls."},"timezone":{"type":"string","optional":true,"description":"IANA timezone. Defaults to Europe/Madrid."},"from":{"type":"string","optional":true,"description":"Execution window start. Defaults to 30 days before asOf; stale running executions remain visible."},"to":{"type":"string","optional":true,"description":"Execution window end. Defaults to asOf and cannot exceed it."},"projectStatus":{"type":"string","enum":["active","inactive","all"],"optional":true},"projectId":{"type":"string","optional":true,"description":"May only narrow effective access."},"groupId":{"type":"string","optional":true,"description":"May only narrow effective access."},"agentId":{"type":"string","optional":true},"taskStatus":{"type":"string","enum":["active","paused","completed"],"optional":true},"executionStatus":{"type":"string","enum":["running","completed","failed","skipped","deferred"],"optional":true},"staleRunningMinutes":{"type":"number","optional":true,"description":"5-43200, default 60."},"startDelayMinutes":{"type":"number","optional":true,"description":"1-43200, default 30."},"repeatedBlockerCount":{"type":"number","optional":true,"description":"2-20, default 2."},"manualInactivityDays":{"type":"number","optional":true,"description":"1-365, default 14."}},"x-mcp":{"channel":"portfolio","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"portfolio_agent_supervision_items","description":"Return cursor-paginated task supervision detail for the same snapshot and filters as the summary. Alerts include severity, reasonCode, safe evidence, age and recommendedHumanAction; equivalent parent/child alerts are deduplicated.","params":{"asOf":{"type":"string","optional":true,"description":"Reuse the exact summary asOf to obtain the same snapshotId."},"timezone":{"type":"string","optional":true},"from":{"type":"string","optional":true},"to":{"type":"string","optional":true},"projectStatus":{"type":"string","enum":["active","inactive","all"],"optional":true},"projectId":{"type":"string","optional":true},"groupId":{"type":"string","optional":true},"agentId":{"type":"string","optional":true},"taskStatus":{"type":"string","enum":["active","paused","completed"],"optional":true},"executionStatus":{"type":"string","enum":["running","completed","failed","skipped","deferred"],"optional":true},"staleRunningMinutes":{"type":"number","optional":true},"startDelayMinutes":{"type":"number","optional":true},"repeatedBlockerCount":{"type":"number","optional":true},"manualInactivityDays":{"type":"number","optional":true},"cursor":{"type":"string","optional":true,"description":"Opaque cursor bound to snapshotId and filters."},"limit":{"type":"number","optional":true,"description":"1-100, default 50."}},"x-mcp":{"channel":"portfolio","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}],"x-mcp":{"channel":"portfolio","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}},"/api/project-groups/agent-query":{"post":{"summary":"Project-group context and aggregated metrics","description":"Read groups available to a dpa_ agent. Group calls do not replace project scoping: all ordinary service endpoints still require a concrete projectId.","tags":["ProjectGroups"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"list_groups","description":"List accessible project groups and effective scopes.","params":{},"x-mcp":{"channel":"project_groups","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_group","description":"Read shared group context, reporting currency and timezone.","params":{"groupId":{"type":"string","required":true}},"x-mcp":{"channel":"project_groups","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_group_projects","description":"List current projects in a group. Group access automatically covers projects added later.","params":{"groupId":{"type":"string","required":true}},"x-mcp":{"channel":"project_groups","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_group_metrics","description":"Aggregate normalized source snapshots with project names, CRM leads, GA4/Search Console configuration states, daily GA4 traffic, key-event, channel and source/medium breakdowns, and weighted rates. Unique visitors and GA4 users are explicitly per-property sums.","params":{"groupId":{"type":"string","required":true},"from":{"type":"string","required":true},"to":{"type":"string","required":true}},"x-mcp":{"channel":"project_groups","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_group_funnel","description":"Read group lead, qualified-conversation, proposal and won-pilot funnel.","params":{"groupId":{"type":"string","required":true},"from":{"type":"string","required":true},"to":{"type":"string","required":true}},"x-mcp":{"channel":"project_groups","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_group_mailing_config","description":"Read safe group newsletter configuration and per-project permissions. Secrets are never returned.","params":{"groupId":{"type":"string","required":true}},"x-mcp":{"channel":"project_groups","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_group_shared_newsletters","description":"List project-owned newsletters shared by reference with the group.","params":{"groupId":{"type":"string","required":true}},"x-mcp":{"channel":"project_groups","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_mailing_conversion_preview","description":"Preview a complete project-to-group mailing conversion and its blockers.","params":{"groupId":{"type":"string","required":true},"projectId":{"type":"string","required":true}},"x-mcp":{"channel":"project_groups","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/project-groups/agent-mutate":{"post":{"summary":"Refresh project-group metrics","description":"Idempotently refresh normalized snapshots with bounded concurrency. Source failures are persisted independently instead of failing the whole refresh.","tags":["ProjectGroups"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Refresh result"}},"x-tools":[{"name":"refresh_group_metrics","description":"Refresh Landing/Sites, CRM, GA4, Search Console, Google Ads and AEO snapshots for every current group project. Requires group write scope.","params":{"groupId":{"type":"string","required":true},"from":{"type":"string","optional":true,"description":"ISO date; default 30 days before to."},"to":{"type":"string","optional":true,"description":"ISO date; default now."},"concurrency":{"type":"number","optional":true,"description":"1-5, default 2."}},"x-mcp":{"channel":"project_groups","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"set_group_mailing_project_permission","description":"Set NONE, READ or EDIT plus independent agent/form access for a project that currently belongs to the group.","params":{"groupId":{"type":"string","required":true},"projectId":{"type":"string","required":true},"accessLevel":{"type":"string","required":true,"enum":["NONE","READ","EDIT"]},"agentsEnabled":{"type":"boolean","required":true},"formsEnabled":{"type":"boolean","required":true}},"x-mcp":{"channel":"project_groups","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"move_subscriptions_to_group","description":"Copy active subscriptions with verified evidence from a project newsletter into a group newsletter after human approval.","params":{"groupId":{"type":"string","required":true},"projectId":{"type":"string","required":true},"sourceNewsletterId":{"type":"string","required":true},"targetNewsletterId":{"type":"string","required":true},"idempotency_key":{"type":"string","required":true},"agent_note":{"type":"string","required":true}},"x-mcp":{"channel":"project_groups","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"share_newsletter_with_group","description":"Share a project-owned newsletter with every project in its group without moving data.","params":{"groupId":{"type":"string","required":true},"projectId":{"type":"string","required":true},"newsletterId":{"type":"string","required":true},"legalConfirmation":{"type":"string","required":true},"idempotency_key":{"type":"string","required":true},"agent_note":{"type":"string","required":true}},"x-mcp":{"channel":"project_groups","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"unshare_newsletter_from_group","description":"Remove group access to a shared newsletter without deleting its project-owned data.","params":{"groupId":{"type":"string","required":true},"projectId":{"type":"string","required":true},"newsletterId":{"type":"string","required":true},"idempotency_key":{"type":"string","required":true},"agent_note":{"type":"string","required":true}},"x-mcp":{"channel":"project_groups","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"convert_project_mailings_to_group","description":"Convert the complete project mailing configuration into the group scope while preserving identifiers and history.","params":{"groupId":{"type":"string","required":true},"projectId":{"type":"string","required":true},"legalConfirmation":{"type":"string","required":true},"idempotency_key":{"type":"string","required":true},"agent_note":{"type":"string","required":true}},"x-mcp":{"channel":"project_groups","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}}]}},"/api/projects/agent-query":{"post":{"summary":"Project information","description":"Get metadata about the project linked to this API key and manage draft emails.","tags":["Project"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"get_project_info","description":"Returns project name, description, URL, context, email defaults, creation date, and connected services (Google Ads, SEO, Search Console, Analytics).","params":{},"x-mcp":{"channel":"projects","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"update_project_context","description":"Updates the free-form project context/instructions used by agents. Requires write scope.","params":{"content":{"type":"string","required":true}},"x-mcp":{"channel":"projects","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"list_activity","description":"List recent project activity/audit timeline entries visible to agents.","params":{"limit":{"type":"number","optional":true,"default":50},"actor":{"type":"string","optional":true,"enum":["USER","AGENT","SYSTEM"]},"area":{"type":"string","optional":true}},"x-mcp":{"channel":"projects","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_messages","description":"List recent project messages visible to agents, optionally filtered by channel slug.","params":{"channel":{"type":"string","optional":true},"limit":{"type":"number","optional":true,"default":50}},"x-mcp":{"channel":"projects","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"post_message","description":"Post a project message as the authenticated API key. Requires write scope.","params":{"content":{"type":"string","required":true},"channel":{"type":"string","optional":true,"default":"general"},"parentId":{"type":"string","optional":true},"visibility":{"type":"string","optional":true,"enum":["all","agents"]}},"x-mcp":{"channel":"projects","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"reply_message","description":"Reply to an existing project message as the authenticated API key. Requires write scope.","params":{"parentId":{"type":"string","required":true},"content":{"type":"string","required":true},"channel":{"type":"string","optional":true,"default":"general"},"visibility":{"type":"string","optional":true,"enum":["all","agents"]}},"x-mcp":{"channel":"projects","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"get_email_draft","description":"Reads an existing project email by ID. Read-only; does not require write scope. Returns full bodyHtml, derived bodyText, recipients, safe email account metadata, attachments, and audit dates. Agents should call this before updating a draft that may have been edited by a human.","params":{"id":{"type":"string","required":true}},"response":{"id":"string","projectId":"string","status":"DRAFT | AUTHORIZED | SENT","subject":"string","bodyHtml":"string","bodyText":"string","to":"array","cc":"array","bcc":"array","emailAccount":"{ id, name, fromName, fromEmail } | null","attachments":"array","createdAt":"ISO8601 string","updatedAt":"ISO8601 string","authorizedAt":"ISO8601 string | null","authorizedBy":"object | null"},"x-mcp":{"channel":"projects","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_email_drafts","description":"Lists project emails with a compact payload that omits full bodyHtml. Read-only; does not require write scope. Use it to find DRAFT, AUTHORIZED, or SENT emails before calling get_email_draft.","params":{"status":{"type":"string","optional":true,"enum":["DRAFT","AUTHORIZED","SENT"]},"limit":{"type":"number","optional":true,"default":20,"description":"Clamped between 1 and 100."},"since":{"type":"string","optional":true,"description":"ISO date; filters by updatedAt >= since."}},"x-mcp":{"channel":"projects","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"create_email_draft","description":"Creates a DRAFT email inside DigitalPublic for this project. Requires write scope. Omitted emailAccountId, cc, and bcc use project defaults; explicit cc: [] or bcc: [] clears those copies. The signature is always attached from the configured email account and cannot be overridden by agents. Agents cannot authorize drafts; a logged-in human must review and authorize in the UI before send_email_draft can send it.","params":{"subject":{"type":"string","required":true},"bodyHtml":{"type":"string","required":true},"to":{"type":"array","required":true},"cc":{"type":"array","optional":true},"bcc":{"type":"array","optional":true},"fromName":{"type":"string","optional":true},"fromEmail":{"type":"string","optional":true},"emailAccountId":{"type":"string","optional":true,"description":"If omitted, null, or blank, the project default email account is used when configured."},"reportId":{"type":"string","optional":true},"attachments":{"type":"array","optional":true,"description":"Report IDs belonging to this project, or internal attachment objects. Invalid or cross-project IDs return 400."}},"x-mcp":{"channel":"projects","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"create_email_reply_draft","description":"Creates a project-scoped reply draft linked to an existing email. Requires write scope. It preserves parentEmailId, In-Reply-To, References, provider thread metadata, recipients, and account. The draft still requires human review and authorization before platform sending.","params":{"id":{"type":"string","required":true,"description":"Existing email ID in this project."},"bodyHtml":{"type":"string","optional":true,"description":"Initial reply body; may be blank for later editing."},"includeQuotedHistory":{"type":"boolean","optional":true,"default":false}},"x-mcp":{"channel":"projects","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"update_email_draft","description":"Updates a DRAFT or AUTHORIZED email. Requires write scope. Missing account/CC/BCC are completed from project defaults when absent on the draft; explicit cc: [] or bcc: [] clears those copies. The signature is always attached from the configured email account and cannot be overridden by agents. If the email was AUTHORIZED, any update automatically reverts it to DRAFT and the response includes revertedFromAuthorized: true.","params":{"id":{"type":"string","required":true},"subject":{"type":"string","optional":true},"bodyHtml":{"type":"string","optional":true},"to":{"type":"array","optional":true},"cc":{"type":"array","optional":true},"bcc":{"type":"array","optional":true},"fromName":{"type":"string","optional":true},"fromEmail":{"type":"string","optional":true},"emailAccountId":{"type":"string","optional":true},"reportId":{"type":"string","optional":true},"attachments":{"type":"array","optional":true,"description":"Report IDs belonging to this project. Replaces draft attachments when present."}},"x-mcp":{"channel":"projects","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"delete_email_draft","description":"Deletes a DRAFT or AUTHORIZED email. Requires write scope. SENT emails cannot be deleted by this tool.","params":{"id":{"type":"string","required":true}},"x-mcp":{"channel":"projects","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"send_email_draft","description":"Sends an existing AUTHORIZED email for this project. Requires write scope. Hard security rule: this tool rejects DRAFT emails with HTTP 409. Only a logged-in human using the DigitalPublic UI can move DRAFT -> AUTHORIZED; there is intentionally no agent tool or parameter to authorize drafts.","params":{"id":{"type":"string","required":true},"emailAccountId":{"type":"string","optional":true,"description":"Optional explicitly assigned account. If omitted, the explicitly assigned project default is used."}},"response":{"id":"string","status":"SENT","sentAt":"ISO8601 string","to":"array","cc":"array","bcc":"array","subject":"string","bodyHtml":"string","attachments":"array","messageId":"string | null"},"x-mcp":{"channel":"projects","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"register_external_email_send","description":"Idempotently records an email that was sent outside DigitalPublic. Requires write scope. Stores the exact sanitized HTML body, account, sent date, RFC Message-ID and thread metadata; creates the CRM email_out interaction and reconciles linked processes. Repeating the same Message-ID in the project returns the existing registration.","params":{"id":{"type":"string","required":true,"description":"DRAFT or AUTHORIZED email ID in this project."},"sentAt":{"type":"string","required":true,"description":"ISO8601 send date."},"bodyHtml":{"type":"string","required":true,"description":"Exact HTML body that was sent."},"messageId":{"type":"string","required":true,"description":"RFC Message-ID supplied by the external provider."},"emailAccountId":{"type":"string","optional":true},"inReplyToMessageId":{"type":"string","optional":true},"references":{"type":"array","optional":true},"providerThreadId":{"type":"string","optional":true},"idempotencyKey":{"type":"string","optional":true,"description":"Caller-stable key for retries; deduplicated within the project."}},"x-mcp":{"channel":"projects","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"list_email_accounts","description":"Lists only the active email accounts explicitly assigned to this project. Historical use never grants access. Read-only; does not require write scope. Returns safe metadata, ownership scope (GLOBAL, GROUP or PROJECT), owner, assignment source, status and default flag, never passwords, tokens or SMTP/OAuth secrets. Use it to discover a permitted emailAccountId before creating or sending email.","params":{},"response":{"ok":true,"data":"array of { id, name, providerType, fromName, fromEmail, host, port, secure, oauthConnected, scopeType, ownerProject, ownerGroup, status, source, isDefault }"},"x-mcp":{"channel":"projects","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"test_email_account","description":"Runs a live connectivity check against one active account explicitly assigned to this project, reusing the same transport verification as the admin UI. Read-only; does not send any email and does not require write scope. Returns safe account metadata plus an actionable failureKind. Rejects unassigned, disabled or scope-incompatible accounts with a stable EMAIL_ACCOUNT_* code. Failures are recorded in the project activity log.","params":{"emailAccountId":{"type":"string","required":true,"description":"Id of an active account explicitly assigned to the project."}},"response":{"ok":true,"data":"{ account: { id, name, providerType, fromName, fromEmail, host, port, secure, oauthConnected, oauthEmail, oauthConnectedAt }, test: { ok: boolean, failureKind?, error? } }"},"x-mcp":{"channel":"projects","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"test_project_email_accounts","description":"Runs the connectivity check on every active account explicitly assigned to this project. Read-only; does not send any email and does not require write scope. Returns each account's safe metadata and test result plus a summary { total, passed, failed }. Historical use never adds an account to this list.","params":{},"response":{"ok":true,"data":"{ accounts: array of { account, test }, summary: { total, passed, failed } }"},"x-mcp":{"channel":"projects","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"request_email_account_assignment","description":"Proposes assigning a GLOBAL or compatible GROUP account to this project. Requires write scope and always creates a human approval; it never exposes credentials or grants access immediately.","params":{"emailAccountId":{"type":"string","required":true},"reason":{"type":"string","required":true},"idempotencyKey":{"type":"string","optional":true}},"x-mcp":{"channel":"projects","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"request_email_account_revocation","description":"Proposes revoking one explicitly assigned account. Requires write scope and human approval. Future drafts will be blocked if they still reference the revoked account.","params":{"emailAccountId":{"type":"string","required":true},"reason":{"type":"string","required":true},"idempotencyKey":{"type":"string","optional":true}},"x-mcp":{"channel":"projects","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"request_default_email_account","description":"Proposes making one already assigned active account the project default. Requires write scope and human approval.","params":{"emailAccountId":{"type":"string","required":true},"reason":{"type":"string","required":true},"idempotencyKey":{"type":"string","optional":true}},"x-mcp":{"channel":"projects","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}}]}},"/api/mailings/agent-query":{"post":{"summary":"Mailing campaigns and metrics","description":"Read DigitalPublic mailing campaigns, reconciled Brevo audiences, consent audits without PII, immutable editorial reviews, and normalized metrics. Agents must use DigitalPublic instead of calling Brevo directly.","tags":["Mailings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"list_newsletters","description":"List project or group newsletters in the explicit X-Project-Id or X-Group-Id scope.","params":{},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_newsletter","description":"Get one newsletter and its counters.","params":{"newsletterId":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_newsletter_issues","description":"List newsletter issues.","params":{"newsletterId":{"type":"string","optional":true},"status":{"type":"string","optional":true},"limit":{"type":"number","default":50}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_newsletter_issue","description":"Get one structured newsletter issue.","params":{"campaignId":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"preview_newsletter_issue","description":"Return generated HTML, plain text and NewsletterDocumentV1.","params":{"campaignId":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"validate_newsletter_issue","description":"Validate sender, legal footer, content and active audience before approval.","params":{"campaignId":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_subscriber_summary","description":"Return aggregate subscription counts and source-project breakdown without PII.","params":{},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_subscribers","description":"List masked subscribers with filters.","params":{"newsletterId":{"type":"string","optional":true},"status":{"type":"string","optional":true},"sourceProjectId":{"type":"string","optional":true},"q":{"type":"string","optional":true},"limit":{"type":"number","default":50}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_delivery_status","description":"Get a frozen delivery and its provider status.","params":{"deliveryId":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_newsletter_metrics","description":"Get newsletter delivery metrics.","params":{"newsletterId":{"type":"string","optional":true}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_mailing_campaigns","description":"List mailing campaigns for the project.","params":{"limit":{"type":"number","default":20}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_mailing_campaign","description":"Get campaign detail and recent metrics.","params":{"campaignId":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_audiences","description":"List Brevo audiences/lists synchronized into DigitalPublic.","params":{},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_mailing_images","description":"List mailing images registered for the project with public Brevo CDN URLs.","params":{"limit":{"type":"number","default":50},"includeDeleted":{"type":"boolean","default":false}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"sync_audiences","description":"Sync Brevo lists into DigitalPublic.","params":{},"x-mcp":{"channel":"mailings","effect":"sync","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_mailing_metrics","description":"Sync and return metrics: sent, delivered, opens, clicks, bounces, unsubscribes, complaints.","params":{"campaignId":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"sync","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"audit_audience_consent","description":"Return aggregate consent evidence and reconciled provider count without subscriber PII.","params":{"audienceId":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_mailing_review","description":"Return an immutable editorial review, its content hash, audience, locale, and validity window.","params":{"reviewId":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_mutation_status","description":"Check one pending mailing send.","params":{"mutationId":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pending_mutations","description":"List pending mailing sends.","params":{"limit":{"type":"number","default":20}},"x-mcp":{"channel":"mailings","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/mailings/agent-mutate":{"post":{"summary":"Create, design, and send mailing campaigns","description":"Create and update DigitalPublic mailing campaigns backed by Brevo. Record verifiable consent and freeze an immutable editorial review before requesting TEST or SEND authorization. approvalMode=REQUIRED always forces exact human approval and cannot be bypassed by project auto-approval.","tags":["Mailings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Executed or queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"create_newsletter","description":"Create a newsletter in the explicit project or group scope.","params":{"name":{"type":"string","required":true},"slug":{"type":"string","optional":true},"locale":{"type":"string","optional":true},"cadence":{"type":"string","optional":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"update_newsletter","description":"Update newsletter identity, cadence, sender or state.","params":{"newsletterId":{"type":"string","required":true},"status":{"type":"string","optional":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"create_newsletter_issue","description":"Create an issue from NewsletterDocumentV1. This never sends it.","params":{"newsletterId":{"type":"string","required":true},"name":{"type":"string","required":true},"subject":{"type":"string","required":true},"contentDocument":{"type":"object","required":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"update_newsletter_issue","description":"Update an issue and invalidate previous review or authorization.","params":{"campaignId":{"type":"string","required":true},"contentDocument":{"type":"object","optional":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"send_newsletter_test","description":"Send a test only to explicit addresses.","params":{"campaignId":{"type":"string","required":true},"emailTo":{"type":"array","required":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"request_newsletter_send","description":"Freeze content and recipients and request mandatory human approval.","params":{"campaignId":{"type":"string","required":true},"idempotency_key":{"type":"string","required":true},"agent_note":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"schedule_newsletter_send","description":"Freeze and schedule a delivery after mandatory human approval.","params":{"campaignId":{"type":"string","required":true},"scheduledAt":{"type":"string","required":true},"idempotency_key":{"type":"string","required":true},"agent_note":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"cancel_newsletter_delivery","description":"Cancel a delivery that has not been sent.","params":{"deliveryId":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"request_subscription","description":"Start double opt-in. Never infer consent from a CRM lead.","params":{"newsletterId":{"type":"string","required":true},"email":{"type":"string","required":true},"noticeVersion":{"type":"string","required":true},"sourceProjectId":{"type":"string","optional":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"unsubscribe_subscriber","description":"Immediately record a local newsletter unsubscribe.","params":{"subscriberId":{"type":"string","required":true},"newsletterId":{"type":"string","required":true},"reason":{"type":"string","optional":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"import_subscribers","description":"Simulate and request approval for a consent-evidenced import.","params":{"newsletterId":{"type":"string","required":true},"records":{"type":"array","required":true},"idempotency_key":{"type":"string","required":true},"agent_note":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"create_mailing_campaign","description":"Create a mailing campaign and synchronize it as a Brevo draft.","params":{"name":{"type":"string","required":true},"subject":{"type":"string","required":true},"bodyHtml":{"type":"string","required":true},"audienceId":{"type":"string","optional":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"update_mailing_design","description":"Update campaign subject, HTML, name, preview text, or audience.","params":{"campaignId":{"type":"string","required":true},"subject":{"type":"string","optional":true},"bodyHtml":{"type":"string","optional":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"record_consent_evidence","description":"Record hashed, project-scoped consent evidence; raw subscriber email is not accepted.","params":{"audienceId":{"type":"string","required":true},"subjectHash":{"type":"string","required":true,"description":"64-character SHA-256 hex digest."},"purpose":{"type":"string","required":true},"locale":{"type":"string","required":true},"source":{"type":"string","required":true},"consentedAt":{"type":"string","required":true},"noticeVersion":{"type":"string","required":true},"legalBasis":{"type":"string","required":true},"evidenceRef":{"type":"string","required":true},"scope":{"type":"string","required":true},"status":{"type":"string","optional":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"create_mailing_review","description":"Freeze provider, audience, locale, subject, preview, body, links and sender into an immutable SHA-256 review.","params":{"campaignId":{"type":"string","required":true},"locale":{"type":"string","required":true},"validUntil":{"type":"string","optional":true,"description":"At most 48 hours."}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"send_test_mailing","description":"Request a separately authorized test send. With approvalMode=REQUIRED it always queues exact human approval.","params":{"campaignId":{"type":"string","required":true},"reviewId":{"type":"string","required":true},"emailTo":{"type":"array","required":true},"approvalMode":{"type":"string","required":true,"enum":["REQUIRED"]},"idempotency_key":{"type":"string","required":true},"validUntil":{"type":"string","optional":true,"description":"At most 24 hours."}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"send_mailing","description":"Request a separately authorized real send. With approvalMode=REQUIRED it always queues exact human approval.","params":{"campaignId":{"type":"string","required":true},"reviewId":{"type":"string","required":true},"approvalMode":{"type":"string","required":true,"enum":["REQUIRED"]},"idempotency_key":{"type":"string","required":true},"validUntil":{"type":"string","optional":true,"description":"At most 24 hours."},"agent_note":{"type":"string","optional":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"upload_mailing_image","description":"Upload an image to Brevo's gallery/CDN from imageUrl, base64, or multipart file.","params":{"name":{"type":"string","required":true},"imageUrl":{"type":"string","optional":true},"base64":{"type":"string","optional":true},"filename":{"type":"string","optional":true},"agent_note":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"update_mailing_image","description":"Rename or replace a registered mailing image.","params":{"imageId":{"type":"string","required":true},"name":{"type":"string","optional":true},"imageUrl":{"type":"string","optional":true},"base64":{"type":"string","optional":true},"agent_note":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"delete_mailing_image","description":"Remove a mailing image from the project's inventory.","params":{"imageId":{"type":"string","required":true},"agent_note":{"type":"string","required":true}},"x-mcp":{"channel":"mailings","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}}]}},"/api/apify/agent-query":{"post":{"summary":"Apify actors, usage and runs","description":"Read the closed Actor catalog and strict global/project usage accounting. Credentials are never returned.","tags":["Apify"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success"},"403":{"description":"APIFY_DISABLED or ACTOR_NOT_ALLOWED"}},"x-tools":[{"name":"list_apify_actors","description":"List only Actors authorized for this project with effective limits.","params":{},"x-mcp":{"channel":"apify","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_apify_usage","description":"Global actual, attributed, reserved, unattributed and remaining USD.","params":{"refresh":{"type":"boolean","default":false}},"x-mcp":{"channel":"apify","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_apify_runs","description":"List project runs.","params":{"limit":{"type":"number","default":50}},"x-mcp":{"channel":"apify","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_apify_run","description":"Get run state, reservation, final cost and imported collection.","params":{"id":{"type":"string","required":true}},"x-mcp":{"channel":"apify","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/apify/agent-mutate":{"post":{"summary":"Request an authorized Apify run","description":"Agent-only run request. Human approval is required by default; admins can enable Apify auto-approval independently.","tags":["Apify"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Validated or auto-approved"},"202":{"description":"Pending human approval"},"409":{"description":"BUDGET_EXCEEDED or IDEMPOTENCY_CONFLICT"},"503":{"description":"GLOBAL_USAGE_STALE"}},"x-tools":[{"name":"request_apify_run","description":"Request one on-demand run from the project allowlist with strict USD and item caps.","params":{"actorCatalogId":{"type":"string","required":true},"collectionName":{"type":"string","required":true},"input":{"type":"object","required":true},"maxTotalChargeUsd":{"type":"number","required":true},"maxItems":{"type":"number","optional":true},"purpose":{"type":"string","required":true},"legalBasis":{"type":"string","required":true},"retentionDays":{"type":"number","optional":true,"minimum":30,"maximum":3650},"idempotency_key":{"type":"string","required":true},"agent_note":{"type":"string","optional":true},"validate_only":{"type":"boolean","default":false}},"x-mcp":{"channel":"apify","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}}]}},"/api/research-data/agent-query":{"post":{"summary":"Shared research database","description":"Read canonical companies, contacts, collections, observations and import status from the project's private or current group data space.","tags":["Research Data"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success"},"403":{"description":"DATA_ACCESS_DENIED"}},"x-tools":[{"name":"list_research_collections","description":"List visible collections.","params":{"limit":{"type":"number","default":50},"cursor":{"type":"string","optional":true}},"x-mcp":{"channel":"research_data","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_research_collection","description":"Collection detail and provenance.","params":{"collectionId":{"type":"string","required":true}},"x-mcp":{"channel":"research_data","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_collection_items","description":"Paginate sanitized original items.","params":{"collectionId":{"type":"string","required":true},"limit":{"type":"number","default":20},"cursor":{"type":"string","optional":true}},"x-mcp":{"channel":"research_data","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"search_companies","description":"Search deduplicated companies.","params":{"q":{"type":"string","optional":true},"country":{"type":"string","optional":true},"sector":{"type":"string","optional":true},"limit":{"type":"number","default":20},"cursor":{"type":"string","optional":true}},"x-mcp":{"channel":"research_data","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"search_contacts","description":"Search deduplicated contacts.","params":{"q":{"type":"string","optional":true},"limit":{"type":"number","default":20},"cursor":{"type":"string","optional":true}},"x-mcp":{"channel":"research_data","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_research_entity","description":"Entity detail with observations and conflicts.","params":{"id":{"type":"string","required":true}},"x-mcp":{"channel":"research_data","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_research_imports","description":"List visible workbook imports.","params":{"limit":{"type":"number","default":50}},"x-mcp":{"channel":"research_data","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_research_import_status","description":"Import status, mapping and statistics.","params":{"importBatchId":{"type":"string","required":true}},"x-mcp":{"channel":"research_data","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_research_import_errors","description":"Row-level import errors.","params":{"importBatchId":{"type":"string","required":true},"limit":{"type":"number","default":100}},"x-mcp":{"channel":"research_data","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_visibility_progress","description":"Aggregate distinct domains, valid observations, explicit failures, engines and methodology versions against panel targets.","params":{"stableKey":{"type":"string","required":true},"targetDomains":{"type":"number","default":30},"targetObservations":{"type":"number","default":300}},"x-mcp":{"channel":"research_data","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_visibility_observations","description":"Paginate traceable AI Visibility observations. UNAVAILABLE and ERROR remain distinct from numeric zero.","params":{"stableKey":{"type":"string","required":true},"limit":{"type":"number","default":50},"cursor":{"type":"string","optional":true}},"x-mcp":{"channel":"research_data","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/research-data/import":{"post":{"summary":"Preview a historical research workbook","description":"Accepts XLSX, XLS or CSV up to configured limits. It never evaluates formulas, macros, links or code and only creates an AWAITING_MAPPING preview.","tags":["Research Data"],"responses":{"201":{"description":"Mapping preview"},"400":{"description":"INVALID_WORKBOOK"},"413":{"description":"IMPORT_LIMIT_EXCEEDED"}},"x-tools":[{"name":"upload_research_workbook","description":"Upload a historical workbook and receive sheet previews plus proposed Spanish/English column mappings.","params":{"file":{"type":"string","format":"binary","required":true},"filename":{"type":"string","required":true}},"x-mcp":{"channel":"research_data","effect":"write","requiredScope":"write","approval":"none","requestShape":"multipart_upload"}}]}},"/api/research-data/agent-mutate":{"post":{"summary":"Import research data or promote selected records","description":"Workbook execution requires preview and human approval by default. Promotion is limited to visible selected entities and is idempotent.","tags":["Research Data"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Executed or validated"},"202":{"description":"Pending approval"},"400":{"description":"IMPORT_MAPPING_REQUIRED"}},"x-tools":[{"name":"execute_research_import","description":"Request asynchronous import of a previously previewed workbook.","params":{"importBatchId":{"type":"string","required":true},"collectionName":{"type":"string","required":true},"selectedSheets":{"type":"array","required":true},"mappingBySheet":{"type":"object","required":true},"purpose":{"type":"string","required":true},"legalBasis":{"type":"string","required":true},"retentionDays":{"type":"number","optional":true},"tags":{"type":"array","optional":true},"idempotency_key":{"type":"string","required":true},"agent_note":{"type":"string","optional":true},"validate_only":{"type":"boolean","default":false}},"x-mcp":{"channel":"research_data","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"promote_records_to_crm","description":"Promote selected visible research entities into CRM with researchEntityId and email deduplication.","params":{"researchEntityIds":{"type":"array","required":true,"maxItems":100},"tags":{"type":"array","optional":true}},"x-mcp":{"channel":"research_data","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"resolve_visibility_collection","description":"Create or resolve a stable project or group scoped collection for an AI Visibility Index panel.","params":{"stableKey":{"type":"string","required":true},"name":{"type":"string","optional":true},"description":{"type":"string","optional":true},"purpose":{"type":"string","required":true},"legalBasis":{"type":"string","required":true},"retentionDays":{"type":"number","default":365,"minimum":30,"maximum":3650}},"x-mcp":{"channel":"research_data","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"append_visibility_observations","description":"Append a PII-free incremental batch with idempotency and mandatory deduplication by domain, prompt, engine, date and methodology version.","params":{"stableKey":{"type":"string","required":true},"source":{"type":"string","required":true},"sourceRunId":{"type":"string","optional":true},"piiFree":{"type":"boolean","required":true},"observations":{"type":"array","required":true,"maxItems":300},"idempotency_key":{"type":"string","required":true}},"x-mcp":{"channel":"research_data","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}}]}},"/api/crm/agent-query":{"post":{"summary":"CRM leads and pipeline data","description":"Read project leads, configured stage semantics, interactions, pipeline summary, and exportable segments. Call get_pipeline_stages before moving leads. Pending means action required from us: stages with pendingMode=when_follow_up_due are not pending while nextActionAt is in the future and become pending when it expires or is missing.","tags":["CRM"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"get_pipeline_stages","description":"Get configured stages, operational semantics, pendingMode, and recommended transitions. when_follow_up_due is excluded from pending counts while nextActionAt is future, then automatically becomes pending when due or missing.","params":{},"x-mcp":{"channel":"crm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_inbound_form_config","description":"Get the public form webhook configuration for server-side integrations. The returned URL contains a revocable token and must be stored as a deployment secret, never logged or exposed in client-side code.","params":{},"x-mcp":{"channel":"crm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_leads","description":"Paginated lead list with filters.","params":{"stage":{"type":"string","optional":true},"type":{"type":"string","optional":true,"enum":["LEAD","CLIENT","PARTNER","HISTORIC"]},"tag":{"type":"string","optional":true},"source":{"type":"string","optional":true},"q":{"type":"string","optional":true},"ownerUserId":{"type":"string","optional":true},"nextActionBefore":{"type":"string","optional":true},"limit":{"type":"number","default":20},"offset":{"type":"number","default":0}},"x-mcp":{"channel":"crm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_lead","description":"Full lead detail with the latest 20 interactions.","params":{"id":{"type":"string","optional":true},"email":{"type":"string","optional":true}},"x-mcp":{"channel":"crm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"search_leads","description":"Text search across name, company, and email.","params":{"q":{"type":"string","required":true},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"crm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_interactions","description":"Paginated interaction history for one lead.","params":{"leadId":{"type":"string","required":true},"limit":{"type":"number","default":20},"offset":{"type":"number","default":0}},"x-mcp":{"channel":"crm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"pipeline_summary","description":"Lead counts by stage and type plus stale leads.","params":{"staleDays":{"type":"number","default":14}},"x-mcp":{"channel":"crm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"export_segment","description":"Emails and names for a segment. Always excludes opted-out leads.","params":{"stage":{"type":"string","optional":true},"type":{"type":"string","optional":true},"tag":{"type":"string","optional":true},"limit":{"type":"number","default":1000}},"x-mcp":{"channel":"crm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_mutation_status","description":"Check one CRM configuration mutation.","params":{"mutationId":{"type":"string","required":true}},"x-mcp":{"channel":"crm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pending_mutations","description":"List pending CRM configuration mutations.","params":{"limit":{"type":"number","default":20}},"x-mcp":{"channel":"crm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_mutation_history","description":"List CRM configuration mutation history.","params":{"status":{"type":"string","default":"all"},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"crm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/crm/agent-mutate":{"post":{"summary":"Manage CRM leads","description":"Create and edit leads, progress the commercial workflow, log interactions, schedule next actions, and handle GDPR opt-outs. Mandatory workflow: after sending or replying to an email, call progress_lead with the resulting stage and follow-up. DigitalPublic automatically moves new emailed leads to awaiting_reply as a fallback, but the agent remains responsible for reviewing nextActionAt. Waiting stages are removed from pending counts while that date is future and become pending again when it expires.","tags":["CRM"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Executed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"create_lead","description":"Create a lead with email deduplication; returns { deduplicated: true, leadId } when the email already exists.","params":{"email":{"type":"string","optional":true},"name":{"type":"string","optional":true},"company":{"type":"string","optional":true},"type":{"type":"string","optional":true,"default":"LEAD"},"stage":{"type":"string","optional":true},"tags":{"type":"array","optional":true},"source":{"type":"string","optional":true},"sourceDetail":{"type":"string","optional":true},"legalBasis":{"type":"string","optional":true,"enum":["consent","legitimate_interest","contract"]},"interactionSummary":{"type":"string","optional":true},"agent_note":{"type":"string","optional":true}},"x-mcp":{"channel":"crm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"submit_web_lead","description":"Server-to-server ingestion for a website form already validated by the originating site. Idempotently records the submission, quarantines review-risk entries, and creates an auditable notification outbox item for accepted leads.","params":{"idempotencyKey":{"type":"string","required":true},"fields":{"type":"object","required":true},"riskLevel":{"type":"string","optional":true,"enum":["accepted","review"]},"riskReasons":{"type":"array","optional":true}},"x-mcp":{"channel":"crm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"update_lead","description":"Partially update lead fields. Stage changes are rejected; use progress_lead.","params":{"id":{"type":"string","required":true}},"x-mcp":{"channel":"crm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"progress_lead","description":"Recommended after every commercial action. Atomically changes stage, logs the reason, and schedules follow-up. awaiting_reply requires a future nextActionAt and nextActionNote. Waiting stages do not count as pending until the follow-up expires; won/lost/spam close the lead and clear follow-up.","params":{"id":{"type":"string","required":true},"stage":{"type":"string","required":true,"enum":["new","awaiting_reply","qualified","meeting_scheduled","proposal_sent","won","lost","spam"]},"note":{"type":"string","required":true},"nextActionAt":{"type":"string","optional":true},"nextActionNote":{"type":"string","optional":true},"authorName":{"type":"string","optional":true}},"x-mcp":{"channel":"crm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"change_stage","description":"Basic compatibility stage change. awaiting_reply is rejected because it requires progress_lead with follow-up.","params":{"id":{"type":"string","required":true},"stage":{"type":"string","required":true},"note":{"type":"string","optional":true}},"x-mcp":{"channel":"crm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"add_interaction","description":"Log an interaction on a lead. For email_in/email_out it accepts the FULL email (subject, sender, recipients, complete body) plus base64 attachments; attachments download at GET /api/crm/attachments/{attachmentId}.","params":{"leadId":{"type":"string","required":true},"kind":{"type":"string","required":true,"enum":["form_submission","email_out","email_in","call","note","stage_change","import"]},"summary":{"type":"string","required":true},"occurredAt":{"type":"string","optional":true},"data":{"type":"object","optional":true},"email":{"type":"object","optional":true,"description":"Only email_in/email_out: { subject, from, to[], cc[], bodyText, bodyHtml }"},"attachments":{"type":"array","optional":true,"description":"Only email_in/email_out, max 10 x 10MB: [{ filename, contentType?, contentBase64 }]"}},"x-mcp":{"channel":"crm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"set_next_action","description":"Schedule the next commercial action.","params":{"id":{"type":"string","required":true},"nextActionAt":{"type":"string","required":true},"nextActionNote":{"type":"string","optional":true}},"x-mcp":{"channel":"crm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"opt_out_lead","description":"Mark GDPR communication opt-out.","params":{"id":{"type":"string","optional":true},"email":{"type":"string","optional":true}},"x-mcp":{"channel":"crm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"archive_lead","description":"Soft-delete a lead (trash).","params":{"id":{"type":"string","required":true}},"x-mcp":{"channel":"crm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"sync_segment_to_audience","description":"Create or update a Brevo list from a CRM segment (always excludes opted-out leads). Requires verified Brevo mailings config.","params":{"name":{"type":"string","optional":true},"audienceId":{"type":"string","optional":true},"stage":{"type":"string","optional":true},"type":{"type":"string","optional":true},"tag":{"type":"string","optional":true}},"x-mcp":{"channel":"crm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"sync_brevo_unsubscribes","description":"Push Brevo blacklisted contacts into the CRM as GDPR opt-outs.","params":{"sinceDays":{"type":"number","default":30}},"x-mcp":{"channel":"crm","effect":"sync","requiredScope":"read","approval":"auto_approval_possible","requestShape":"tool_params"}}],"x-resources":[{"resource":"crm_config","operations":["update"],"description":"Enable or configure CRM. This requires human approval unless CRM auto-approval is enabled.","params":{"data":{"type":"array","required":true,"description":"[{ enabled?, inboundEnabled?, pipelineStages?, notifyEmails? }]"},"validate_only":{"type":"boolean","default":false},"agent_note":{"type":"string","optional":true}},"x-mcp":{"channel":"crm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}}]}},"/api/social/agent-query":{"post":{"summary":"Social organic channel data","description":"Read connected organic social accounts through DigitalPublic. X is the first supported provider.","tags":["Social Organic"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"list_tools","description":"List available organic social tools.","params":{},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_accounts","description":"List connected social accounts.","params":{"provider":{"type":"string","default":"X"}},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_profile","description":"Get the connected X account profile, verify its remote identity, and refresh the cached name and handle.","params":{"accountId":{"type":"string","optional":true}},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_x_profile_settings","description":"Read the complete editable X profile metadata, current profile hash, platform limits, and machine-readable update capability gap.","params":{"accountId":{"type":"string","optional":true}},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_recent_posts","description":"List recent posts from the connected X account.","params":{"accountId":{"type":"string","optional":true},"max_results":{"type":"number","default":10}},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_mentions","description":"List recent mentions for the connected X account.","params":{"accountId":{"type":"string","optional":true},"max_results":{"type":"number","default":10}},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_followers","description":"List followers of the connected X account.","params":{"accountId":{"type":"string","optional":true},"max_results":{"type":"number","default":10}},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_following","description":"List accounts followed by the connected X account.","params":{"accountId":{"type":"string","optional":true},"max_results":{"type":"number","default":10}},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"search_recent_posts","description":"Search recent posts on X.","params":{"query":{"type":"string","required":true},"max_results":{"type":"number","default":10}},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_mutation_status","description":"Check one pending social mutation.","params":{"mutationId":{"type":"string","required":true}},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pending_mutations","description":"List pending social mutations.","params":{"limit":{"type":"number","default":20}},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_mutation_history","description":"List social mutation history including pending, expired, rejected, cancelled, executed, and error states.","params":{"status":{"type":"string","default":"all","enum":["all","pending","processing","executing","approved","expired","rejected","cancelled","executed","error"]},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_linkedin_connection_status","description":"Estado, scopes y capacidades de LinkedIn.","params":{},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_linkedin_identities","description":"Lista perfiles y páginas vinculadas.","params":{"identityType":"MEMBER | ORGANIZATION (opcional)"},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_linkedin_profile","description":"Obtiene una identidad LinkedIn.","params":{"identityId":"opcional"},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_linkedin_organization_profile_settings","description":"Lee el perfil corporativo administrado, sus locales, versionTag, hash canónico y capacidad de actualización.","params":{"identityId":"organización exacta requerida"},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"verify_linkedin_organization_profile_update","description":"Verifica por lectura un paquete de perfil aprobado y aplicado manualmente en LinkedIn.","params":{"mutationId":"paquete aprobado requerido"},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_linkedin_organizations","description":"Lista páginas administradas sincronizadas.","params":{},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"sync_linkedin_assets","description":"Sincroniza páginas y cuentas publicitarias accesibles.","params":{},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_linkedin_posts","description":"Lista publicaciones de una identidad.","params":{"identityId":"requerido si hay varias","count":20},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_linkedin_post","description":"Obtiene una publicación por URN.","params":{"postUrn":"requerido"},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_linkedin_social_metadata","description":"Resumen de comentarios y reacciones cuando el scope social feed correspondiente está concedido.","params":{"identityId":"requerido","entityUrn":"requerido"},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_linkedin_comments","description":"Lista comentarios cuando LinkedIn concedió el scope social feed correspondiente.","params":{"identityId":"requerido","entityUrn":"requerido","count":20},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_linkedin_reactions","description":"Lista reacciones cuando LinkedIn concedió el scope social feed correspondiente.","params":{"identityId":"requerido","entityUrn":"requerido","count":20},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_linkedin_page_statistics","description":"Estadísticas de página. Sin fechas devuelve el acumulado histórico.","params":{"identityId":"requerido","start":"ISO opcional","end":"ISO opcional","granularity":"DAY | MONTH"},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_linkedin_follower_statistics","description":"Estadísticas de seguidores de página. Sin fechas devuelve el acumulado histórico.","params":{"identityId":"requerido","start":"ISO opcional","end":"ISO opcional","granularity":"DAY | MONTH"},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_linkedin_post_statistics","description":"Estadísticas orgánicas por publicación (ventana máxima de 12 meses). Sin fechas devuelve el acumulado histórico.","params":{"identityId":"requerido","start":"ISO opcional","end":"ISO opcional","granularity":"DAY | MONTH"},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_linkedin_member_statistics","description":"Analítica del miembro cuando LinkedIn concede el permiso cerrado.","params":{"metric":"POST_IMPRESSION | POST_VIEW | POST_REACTION | POST_COMMENT | POST_REPOST | POST_SEND | POST_SAVE","start":"ISO","end":"ISO"},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_linkedin_scheduled_posts","description":"Lista borradores y publicaciones programadas.","params":{"status":"opcional","limit":50},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_linkedin_publication_status","description":"Estado local de una publicación.","params":{"publicationId":"requerido"},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/social/agent-mutate":{"post":{"summary":"Queue organic social actions","description":"Queue or execute organic X actions through DigitalPublic. Requires write scope. Relational actions accept validUntil and are capped to a server-controlled window of 48 hours by default. Visible brand actions default to human approval.","tags":["Social Organic"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Queued or executed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-resources":[{"resource":"social_x_post","operations":["create","reply","delete","repost","undo_repost"],"example":{"resource":"social_x_post","operation":"reply","data":[{"text":"Respuesta contextual.","tweetId":"123456789"}],"validUntil":"2026-07-30T00:00:00Z","idempotency_key":"social-reply-cycle-1","agent_note":"Responder dentro de la ventana observada."},"x-mcp":{"channel":"social","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"social_x_follow","operations":["create","delete"],"example":{"resource":"social_x_follow","operation":"create","data":[{"target_user_id":"123456789"}],"validUntil":"2026-07-30T00:00:00Z","idempotency_key":"social-follow-cycle-1","agent_note":"Seguir cuenta institucional relevante."},"x-mcp":{"channel":"social","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"social_x_like","operations":["create","delete"],"example":{"resource":"social_x_like","operation":"create","data":[{"tweet_id":"123456789"}],"validUntil":"2026-07-30T00:00:00Z","idempotency_key":"social-like-cycle-1","agent_note":"Marcar interacción orgánica relevante."},"x-mcp":{"channel":"social","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"social_x_profile","operations":["update"],"description":"Propose an X profile metadata update. Always requires human approval. Execution fails closed with a capability gap while the connected OAuth 2 flow cannot edit profiles.","example":{"resource":"social_x_profile","operation":"update","data":[{"expectedProfileHash":"sha256-from-get_x_profile_settings","displayName":"Acme","bio":"Nueva biografía","website":"https://acme.example","location":"España","avatarFileId":"existing-creative-file-id","headerFileId":"existing-creative-file-id"}],"agent_note":"Actualizar identidad de marca tras revisión humana."},"x-mcp":{"channel":"social","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"social_linkedin_organization_profile","operations":["update"],"approval":"human_approval_required","executionMode":"MANUAL_LINKEDIN_UI_REQUIRED","description":"Create an immutable, exact-version organization profile package for human approval and manual application in LinkedIn. DigitalPublic never calls undocumented profile write APIs.","example":{"resource":"social_linkedin_organization_profile","operation":"update","idempotency_key":"linkedin-profile-acme-v2649829925","data":[{"identityId":"linkedin-organization-identity-id","expectedVersionTag":"versionTag-from-settings","currentProfileHash":"sha256-from-settings","fields":{"name":{"es_ES":"Acme","en_US":"Acme"},"description":{"es_ES":"Descripción aprobada","en_US":"Approved description"},"website":{"es_ES":"https://www.acme.example/","en_US":"https://www.acme.example/en/"},"specialties":{"es_ES":["Agentes de IA"],"en_US":["AI agents"]}}}],"agent_note":"Preparar el paquete bilingüe para aplicación manual y verificación posterior."},"x-mcp":{"channel":"social","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"social_linkedin_post","operations":["create","schedule","reschedule","cancel","update","delete","reshare"],"x-mcp":{"channel":"social","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"social_linkedin_comment","operations":["create","reply","delete"],"approval":"human_approval_required","description":"Create a comment or prepare an exact nested reply. Replies require actorIdentityId, immutable approval, a short validity window, and an idempotency key.","params":{"actorIdentityId":"Verified MEMBER or ORGANIZATION identity ID, required for reply.","entityUrn":"Post/activity URN.","commentUrn":"Composite parent comment URN, required for reply/delete.","text":"Exact reply text.","idempotency_key":"Caller-stable unique key."},"x-mcp":{"channel":"social","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"social_linkedin_reaction","operations":["create","delete"],"x-mcp":{"channel":"social","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"social_linkedin_webhook","operations":["subscribe","unsubscribe"],"x-mcp":{"channel":"social","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}}]}},"/api/social/automation/agent":{"post":{"summary":"Social editorial automation","description":"Prepare and revise internal social drafts for X, LinkedIn organizations, and Facebook Pages. These tools never approve or publish content.","tags":["Social Organic"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"list_social_automation_plans","description":"Lista los planes editoriales sociales activos del proyecto.","params":{},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_social_automation_plan_settings","description":"Inspecciona la configuración de un plan social activo o pausado sin habilitar la generación.","params":{"planId":{"type":"string","required":true}},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_social_generation_brief","description":"Obtiene destinos, reglas editoriales y restricciones para preparar una publicación social.","params":{"planId":{"type":"string","required":true},"occurrenceKey":{"type":"string","optional":true}},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"submit_social_draft","description":"Entrega un borrador social interno con una hora propuesta. No publica ni solicita una mutación externa.","params":{"planId":{"type":"string","required":true},"taskExecutionId":{"type":"string","required":true},"occurrenceKey":{"type":"string","required":true},"idempotencyKey":{"type":"string","required":true},"topic":{"type":"string","optional":true},"objective":{"type":"string","optional":true},"variants":{"type":"array","required":true}},"x-mcp":{"channel":"social","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"submit_social_revision","description":"Entrega una revisión nueva para una variante devuelta por un revisor humano.","params":{"variantId":{"type":"string","required":true},"baseRevisionNumber":{"type":"number","required":true},"idempotencyKey":{"type":"string","required":true},"topic":{"type":"string","optional":true},"objective":{"type":"string","optional":true},"payload":{"type":"object","required":true},"proposedPublishAt":{"type":"string","required":true},"rationale":{"type":"string","optional":true}},"x-mcp":{"channel":"social","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"get_social_content_status","description":"Consulta el estado editorial y de entrega de un contenido social.","params":{"contentId":{"type":"string","required":true}},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_social_revision_requests","description":"Lista variantes que necesitan una nueva revisión del agente.","params":{},"x-mcp":{"channel":"social","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/web-editorial/agent":{"post":{"summary":"Web editorial automation","description":"Prepare immutable web drafts and revisions for WordPress or repository-backed sites. Agents never approve, publish, merge, or deploy. Administrative approval always targets the exact SHA-256 revision.","tags":["Web Editorial"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"submit_web_draft","description":"Crea un borrador web inmutable. Nunca aprueba, publica, fusiona ni despliega.","params":{"cycleKey":{"type":"string","required":true},"idempotencyKey":{"type":"string","required":true},"taskExecutionId":{"type":"string","optional":true},"topic":{"type":"string","optional":true},"objective":{"type":"string","optional":true},"producer":{"type":"string","optional":true},"variants":{"type":"array","required":true}},"x-mcp":{"channel":"web_editorial","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"submit_web_revision","description":"Entrega una revisión nueva y deja obsoleta cualquier autorización anterior.","params":{"variantId":{"type":"string","required":true},"baseRevisionNumber":{"type":"number","required":true},"idempotencyKey":{"type":"string","required":true},"payload":{"type":"object","required":true}},"x-mcp":{"channel":"web_editorial","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"get_web_content_status","description":"Consulta revisiones, decisiones y entregas de un contenido web del proyecto.","params":{"contentId":{"type":"string","required":true}},"x-mcp":{"channel":"web_editorial","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_web_revision_requests","description":"Lista variantes web que requieren una revisión nueva del agente.","params":{},"x-mcp":{"channel":"web_editorial","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/linkedin-ads/agent-query":{"post":{"summary":"LinkedIn Ads data and diagnostics","description":"Query linked ad accounts, Campaign Groups, campaigns, creatives, targeting, forecasts, audiences, conversions, leads, and reporting. Capability-gated by the LinkedIn products/scopes granted to the connection.","tags":["LinkedIn Ads"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"list_tools","description":"Lista herramientas LinkedIn Ads.","params":{},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_connection_status","description":"Estado, scopes y capacidades.","params":{},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_ad_accounts","description":"Lista cuentas asignadas al proyecto.","params":{},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_ad_account","description":"Obtiene una cuenta.","params":{"adAccountId":"opcional si solo hay una"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_account_users","description":"Lista usuarios y roles de una cuenta.","params":{"adAccountId":"opcional"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_account_capabilities","description":"Devuelve formatos/tipos permitidos y capacidades del token.","params":{"adAccountId":"opcional"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_campaign_groups","description":"Lista Campaign Groups.","params":{"adAccountId":"opcional","pageSize":100,"pageToken":"opcional"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_campaign_group","description":"Obtiene un Campaign Group.","params":{"adAccountId":"opcional","campaignGroupId":"requerido"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_campaigns","description":"Lista campañas.","params":{"adAccountId":"opcional","campaignGroupId":"opcional","pageSize":100,"pageToken":"opcional"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_campaign","description":"Obtiene una campaña.","params":{"adAccountId":"opcional","campaignId":"requerido"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_creatives","description":"Lista creatividades/anuncios.","params":{"adAccountId":"opcional","campaignId":"opcional","pageSize":100,"pageToken":"opcional"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_creative","description":"Obtiene una creatividad/anuncio.","params":{"adAccountId":"opcional","creativeId":"requerido"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_campaign_capabilities","description":"Compatibilidad de objetivo, formato y cuenta.","params":{"adAccountId":"opcional","campaignId":"opcional"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_objectives","description":"Objetivos soportados por la integración.","params":{},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_ad_formats","description":"Formatos soportados por la integración.","params":{},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"search_targeting_facets","description":"Busca entidades de targeting profesional.","params":{"type":"requerido","query":"requerido","limit":25},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_audience_count","description":"Calcula tamaño de audiencia.","params":{"targetingCriteria":"Rest.li targeting criteria requerido"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_budget_pricing","description":"Obtiene rangos de presupuesto/puja.","params":{"objectiveType":"requerido","targetingCriteria":"requerido"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_supply_forecast","description":"Obtiene previsión de entrega.","params":{"targetingCriteria":"requerido"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_images","description":"Lista imágenes de la cuenta.","params":{"adAccountId":"opcional"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_videos","description":"Lista vídeos de la cuenta.","params":{"adAccountId":"opcional"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_documents","description":"Lista documentos de la cuenta.","params":{"adAccountId":"opcional"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_sponsored_posts","description":"Lista posts patrocinables de una organización.","params":{"organizationUrn":"requerido","count":50},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"diagnose_account","description":"Diagnóstico de cuenta, conexión y campañas.","params":{"adAccountId":"opcional"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"diagnose_campaign","description":"Diagnóstico de campaña.","params":{"adAccountId":"opcional","campaignId":"requerido"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_delivery_issues","description":"Campañas con delivery limitado o estado no activo.","params":{"adAccountId":"opcional"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"preflight_campaign_bundle","description":"Valida bundle y audiencia sin publicar.","params":{"adAccountId":"opcional","data":"bundle requerido"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_ad_segments","description":"Lista segmentos disponibles.","params":{"adAccountId":"opcional"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_dmp_segments","description":"Lista DMP segments aprobados.","params":{"adAccountId":"opcional"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_conversion_rules","description":"Lista reglas de conversión.","params":{"adAccountId":"opcional"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_conversion_rule","description":"Obtiene una regla de conversión.","params":{"conversionId":"requerido"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_lead_forms","description":"Lista formularios Lead Gen.","params":{"ownerUrn":"requerido"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_lead_responses","description":"Lista respuestas Lead Gen.","params":{"ownerUrn":"requerido","leadType":"SPONSORED"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_ad_analytics","description":"Métricas por un pivot.","params":{"pivot":"ACCOUNT | CAMPAIGN_GROUP | CAMPAIGN | CREATIVE","dateRange":"requerido","timeGranularity":"DAILY | MONTHLY | ALL"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_ad_statistics","description":"Métricas por hasta tres pivots.","params":{"pivots":"List(...) requerido","dateRange":"requerido"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_attributed_revenue","description":"Métricas de ingresos atribuidos.","params":{"dateRange":"requerido"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_mutation_status","description":"Estado de una mutación LinkedIn Ads.","params":{"mutationId":"requerido"},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pending_mutations","description":"Lista mutaciones LinkedIn Ads pendientes.","params":{"limit":20},"x-mcp":{"channel":"linkedin_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/linkedin-ads/agent-mutate":{"post":{"summary":"LinkedIn Ads campaign actions","description":"Create and manage LinkedIn Ads resources. New groups, campaigns, and creatives are forced to DRAFT. High-impact actions require human approval unless linkedin_ads auto-approval is enabled.","tags":["LinkedIn Ads"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Validated, queued, or executed"}},"x-tools":[{"name":"resource_mutation","description":"Structured LinkedIn Ads mutation.","params":{"resource":{"type":"string","required":true},"operation":{"type":"string","required":true},"data":{"type":"array","required":true},"adAccountId":{"type":"string","optional":true},"validate_only":{"type":"boolean","optional":true},"remote_validate":{"type":"boolean","optional":true},"idempotency_key":{"type":"string","optional":true},"agent_note":{"type":"string","optional":true}},"x-mcp":{"channel":"linkedin_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}}],"x-resources":[{"resource":"linkedin_campaign_groups","operations":["create","update_name","update_status","update_budget","update_schedule","archive"],"x-mcp":{"channel":"linkedin_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"linkedin_campaigns","operations":["create","update_status","update_name","update_budget","update_schedule","update_targeting","update_bid","copy","archive"],"x-mcp":{"channel":"linkedin_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"linkedin_creatives","operations":["create","update_status","copy","delete"],"x-mcp":{"channel":"linkedin_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"linkedin_campaign_bundle","operations":["create"],"x-mcp":{"channel":"linkedin_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"linkedin_media","operations":["upload_image","upload_video","upload_document"],"x-mcp":{"channel":"linkedin_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"linkedin_conversion_rules","operations":["create","update","associate_campaigns"],"x-mcp":{"channel":"linkedin_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"linkedin_conversion_events","operations":["send"],"x-mcp":{"channel":"linkedin_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"linkedin_matched_audiences","operations":["create","upload_list","add_members","remove_members","delete"],"x-mcp":{"channel":"linkedin_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}}]}},"/api/aeo/agent-query":{"post":{"summary":"AEO / AI search visibility","description":"Query AI search visibility for the project's configured brand, prompts, and engines.","tags":["AEO"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"aeo_overview","description":"Brand visibility overview by configured AI engine.","params":{"from":{"type":"string","optional":true},"to":{"type":"string","optional":true},"top":{"type":"number","optional":true}},"x-mcp":{"channel":"aeo","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"aeo_prompt_rankings","description":"Prompt ranking rows for ChatGPT, Gemini, Perplexity, Google AI Overview, or Google AI Mode.","params":{"engine":{"type":"string","optional":true},"date_from":{"type":"string","optional":true},"date_to":{"type":"string","optional":true},"limit":{"type":"number","default":100},"offset":{"type":"number","default":0},"mode":{"type":"string","optional":true}},"x-mcp":{"channel":"aeo","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"aeo_prompt_answer","description":"Cached AI answer for a specific prompt ranking ID.","params":{"engine":{"type":"string","optional":true},"prompt_llm_id":{"type":"string","required":true},"date":{"type":"string","optional":true}},"x-mcp":{"channel":"aeo","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_aeo_reports","description":"List generated AEO reports.","params":{"limit":{"type":"number","default":10}},"x-mcp":{"channel":"aeo","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_mutation_status","description":"Check one AEO mutation.","params":{"mutationId":{"type":"string","required":true}},"x-mcp":{"channel":"aeo","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pending_mutations","description":"List pending AEO mutations.","params":{"limit":{"type":"number","default":20}},"x-mcp":{"channel":"aeo","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_mutation_history","description":"List AEO mutation history.","params":{"status":{"type":"string","default":"all"},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"aeo","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/aeo/agent-mutate":{"post":{"summary":"Configure AEO and prompts","description":"Queue AEO configuration and prompt changes. The AEO site must already exist in DigitalPublic. Requires write scope and human approval unless AEO auto-approval is enabled.","tags":["AEO"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Validated, queued, or executed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-resources":[{"resource":"aeo_config","operations":["update"],"description":"Update brandName, countryCode, langCode, regionName, enabledEngines, and the optional existing AEO site identifier (field name `seRankingSiteId`, kept for API compatibility).","x-mcp":{"channel":"aeo","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"aeo_prompts","operations":["add","remove"],"description":"Add or remove promptKeywords across enabled AEO engines.","x-mcp":{"channel":"aeo","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}}]}},"/api/wordpress-seo/agent-query":{"post":{"summary":"WordPress SEO and content data","description":"Read WordPress SEO data, editable page content, builder detection, and menus through the DigitalPublic proxy. Agents must not call the WordPress plugin directly.","tags":["WordPress"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"wp_site_status","description":"Plugin compatibility and site status. Check ready/initializing/retry_after before read-after-write SEO verification; if ready=false, retry wp_list_posts/wp_get_post_seo later instead of trusting empty SEO fields. Also check supports.pagePublishing/menuManagement/builderCloneReplace/yoastContentTypes/customizerSettings/widgets/pluginManagement before content publishing, theme UI, or plugin changes.","params":{},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_list_taxonomies","description":"List public SEO-editable taxonomies: category, post_tag and custom taxonomies.","params":{},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_list_terms","description":"List terms of a taxonomy with Yoast SEO summary (seo_title, meta_description, focus_keyword, OG, URL).","params":{"taxonomy":{"type":"string","required":true},"page":{"type":"number","default":1},"per_page":{"type":"number","default":20},"search":{"type":"string","optional":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_get_term_seo","description":"Full SEO data of a term. Use term_id returned by wp_list_terms.","params":{"taxonomy":{"type":"string","required":true},"term_id":{"type":"number","required":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_get_post_schema","description":"Configured/active schema of a post: Yoast types, detected FAQ blocks and stored FAQ meta.","params":{"post_id":{"type":"number","required":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_list_faq_blocks","description":"List Yoast FAQ blocks in a post Gutenberg content with normalized questions/answers.","params":{"post_id":{"type":"number","required":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_content_analysis","description":"Content analysis from the public rendered permalink when available: headings, word count, keyword density, readability, content_source/rendered/reliability. If rendered HTML is unavailable for builder/composed content, assessment is omitted instead of returning unsafe recommendations.","params":{"post_id":{"type":"number","required":true},"keyword":{"type":"string","optional":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_link_analysis","description":"Internal and external link analysis from rendered HTML when available. Check rendered, content_source, analysis_reliable and warning before acting.","params":{"post_id":{"type":"number","required":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_image_analysis","description":"Image inventory with alt text status and coverage.","params":{"post_id":{"type":"number","required":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_site_audit","description":"Multilingual site SEO audit. Audits all languages by default and returns languages_audited plus lang/language per issue.","params":{"limit":{"type":"number","default":50},"lang":{"type":"string","default":"all","description":"Language code or all."},"language":{"type":"string","optional":true,"description":"Alias of lang."},"wpml_language":{"type":"string","optional":true,"description":"Alias of lang."}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_robots_txt","description":"Read the robots.txt content of the WordPress site.","params":{},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_sitemap_url","description":"Get the detected XML sitemap URL of the WordPress site.","params":{},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_list_posts","description":"List posts/pages. Supports category/tag/date filters and scheduled posts. May return dp_seo_initializing if the plugin is in its short post-update readiness window; call wp_site_status and retry after retry_after instead of treating missing SEO fields as real. On multilingual sites (WPML/Polylang, plugin >= 1.1.0) lang defaults to 'all' so inventories include translations; pass lang, language, or wpml_language to list a specific language (e.g. 'de'). Each item includes language, lang, and a translations map usable with wp_get_post_seo and SEO mutations.","params":{"post_type":{"type":"string","enum":["post","page","any"],"default":"any"},"status":{"type":"string","default":"publish"},"search":{"type":"string","optional":true},"category":{"type":"string","optional":true},"tag":{"type":"string","optional":true},"orderby":{"type":"string","enum":["date","modified","title"],"optional":true},"order":{"type":"string","enum":["asc","desc"],"optional":true},"after":{"type":"string","optional":true},"before":{"type":"string","optional":true},"lang":{"type":"string","optional":true,"description":"Language code ('de') or 'all'. Default: all."},"language":{"type":"string","optional":true,"description":"Alias of lang."},"wpml_language":{"type":"string","optional":true,"description":"Alias of lang."}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_list_categories","description":"List blog categories with id/name/slug/count/parent and SEO summary.","params":{"search":{"type":"string","optional":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_list_tags","description":"List blog tags with id/name/slug/count and SEO summary.","params":{"search":{"type":"string","optional":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_get_post_content","description":"Get editable post_content and builder detection for a page/post. For Elementor/Divi, prefer clone-and-replace mutations.","params":{"post_id":{"type":"number","required":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_list_menus","description":"List WordPress menus, assigned theme locations, and current menu items before linking pages.","params":{},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_get_reading_settings","description":"Read WordPress Reading settings including page_for_posts.","params":{},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_list_users","description":"List WordPress users for authorship/byline management.","params":{"page":{"type":"number","default":1},"per_page":{"type":"number","default":20},"search":{"type":"string","optional":true},"role":{"type":"string","optional":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_yoast_content_types.list","description":"List Yoast Search Appearance settings for registered post types, taxonomies, and archives, including show_in_search, title/metadesc templates, and schema defaults.","params":{},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_customizer.list_settings","description":"List editable active-theme Customizer settings, prioritizing footer/copyright-like keys.","params":{},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_widgets.list","description":"List sidebars and text/custom HTML widgets, optionally filtered by sidebar such as footer-1.","params":{"sidebar":{"type":"string","optional":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_get_post_seo","description":"Get SEO metadata for a post/page or its requested translation. Returns language and lang. May return dp_seo_initializing immediately after a plugin update; retry after wp_site_status.retry_after.","params":{"post_id":{"type":"number","required":true},"lang":{"type":"string","optional":true,"description":"Translation language."},"language":{"type":"string","optional":true,"description":"Alias of lang."},"wpml_language":{"type":"string","optional":true,"description":"Alias of lang."}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_preview_changes","description":"Preview SEO-only changes without applying them.","params":{"post_id":{"type":"number","required":true},"changes":{"type":"object","required":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_cache.detect","description":"Detect supported WordPress cache plugins and active status.","params":{},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_htaccess.read","description":"Read the current WordPress .htaccess file.","params":{},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_images.audit","description":"Audit large media library images and WebP availability.","params":{"min_size_kb":{"type":"number","default":100},"page":{"type":"number","default":1},"per_page":{"type":"number","default":50}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_assets.nginx_webp_snippet","description":"Return an nginx snippet for WebP delivery of static uploads before Apache.","params":{},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_plugins.list","description":"List installed WordPress plugins with slug, file, name, version, active, category, must_use, network_active, and managed flags.","params":{},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_headers.diagnose","description":"Measure public URL status, TTFB, total time, size, and response headers from the WordPress server and return cache-broken heuristics.","params":{"url":{"type":"string","optional":true},"iterations":{"type":"number","default":3}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_performance.psi","description":"Run Google PageSpeed Insights for a URL. Requires GOOGLE_PSI_API_KEY.","params":{"url":{"type":"string","optional":true},"strategy":{"type":"string","enum":["mobile","desktop","both"],"default":"both"}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_performance.crux","description":"Query Chrome UX Report field data for an origin. Requires GOOGLE_PSI_API_KEY.","params":{"origin":{"type":"string","optional":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"wp_performance.compare","description":"Compare two PSI snapshots returned by wp_performance.psi.","params":{"before":{"type":"object","required":true},"after":{"type":"object","required":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_mutation_status","description":"Check one pending WordPress mutation.","params":{"mutationId":{"type":"string","required":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pending_mutations","description":"List pending WordPress mutations.","params":{"limit":{"type":"number","default":20}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_mutation_history","description":"List WordPress mutation history.","params":{"status":{"type":"string","default":"all"},"limit":{"type":"number","default":20},"resource":{"type":"string","optional":true}},"x-mcp":{"channel":"wordpress","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"update_pending_mutation","description":"Update a pending WordPress mutation.","params":{"mutationId":{"type":"string","required":true},"agent_note":{"type":"string","optional":true},"data":{"type":"array","optional":true}},"x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"cancel_pending_mutation","description":"Cancel a pending WordPress mutation.","params":{"mutationId":{"type":"string","required":true},"reason":{"type":"string","optional":true}},"x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}}]}},"/api/wordpress-seo/agent-mutate":{"post":{"summary":"WordPress SEO, page publishing, and menu mutations","description":"Execute WordPress mutations through DigitalPublic. Page publishing, content editing, clone-and-replace, and menu changes always return pending_approval and execute only after a human approves in DigitalPublic.","tags":["WordPress"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["resource","operation","data"],"properties":{"resource":{"type":"string","enum":["wp_page","wp_page_with_menu","wp_post","wp_post_with_menu","wp_category","wp_tag","wp_page_featured_image","wp_menu_item","wp_media","wp_meta_description","wp_title","wp_seo_title","wp_faq_schema","wp_reading_settings","wp_discussion_settings","wp_user","wp_cache","wp_htaccess","wp_images","wp_assets","wp_yoast_content_types","wp_customizer","wp_widgets","wp_plugins"]},"operation":{"type":"string","description":"For media: upload. For pages/posts: create_publish, clone_publish, update_content, with *_and_link variants for menu links. For posts also assign_terms, set_featured_image, bulk_comment_status. For categories/tags/users: create/update. For menu items: create/update/move/delete/bulk_reorder. For performance: wp_cache purge/configure, wp_htaccess upsert_block, wp_images convert_webp/regenerate_thumbnails/bulk_lazy, wp_assets rewrite_html_webp/undo_html_webp. For Yoast and Customizer: update/undo. For widgets: update_text/undo_text. For plugins: activate/deactivate. For settings and SEO: update."},"data":{"type":"array","description":"Array of mutation payloads. Media accepts filename/mime_type/base64. Page payloads accept title/slug/content/status ('publish'|'draft'|'future', default publish)/post_date/post_id/source_page_id/replacements/menu/comment_status/ping_status/post_author. Post payloads accept title/content/status/post_date/source_post_id/categories/tags/featured_media/comment_status/ping_status/post_author/SEO fields. bulk_comment_status accepts post_ids/comment_status/ping_status. Category/tag payloads accept name/slug/description/parent/term_id. Menu items accept menu_id/menu_slug/theme_location plus page_id/post_id/term_id+taxonomy/url, or menu_item_id for update/move/delete. wp_user accepts username/email/display_name/role or user_id profile fields. Performance payloads accept cache toggles, browser_cache_ttl_seconds, attachment_ids, post_ids, post_types, backup_id, batch_size, and dry_run where applicable. wp_yoast_content_types.update accepts kind, slug, show_in_search, title_template, metadesc_template, schema_page_type, schema_article_type; undo accepts backup_id. wp_customizer.update accepts key/value/type? and undo accepts backup_id. wp_widgets.update_text accepts sidebar?, widget_id, title?, content and undo_text accepts backup_id. wp_plugins accepts slug or file and always requires approval."},"agent_note":{"type":"string","description":"Recommended explanation for the human approver."},"validate_only":{"type":"boolean","default":false}}}}}},"responses":{"200":{"description":"Executed immediately or queued for approval","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-resources":{"wp_page":{"operations":["create_publish","clone_publish","update_content"],"description":"Publish or edit pages without touching menus. Always approval_required.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_page_with_menu":{"operations":["create_publish_and_link","clone_publish_and_link","update_content_and_link"],"description":"Publish/edit a page and add it to an existing menu in the same approved execution.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_post":{"operations":["create_publish","clone_publish","update_content","assign_terms","set_featured_image","bulk_comment_status"],"description":"Create, clone, update, schedule, categorize, tag, set authors/comment status, and set featured images for blog posts. Visible content changes are approval_required; assign_terms/set_featured_image/bulk_comment_status are auto.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_category":{"operations":["create","update"],"description":"Create/update categories idempotently by slug. approval_required.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_tag":{"operations":["create","update"],"description":"Create/update tags idempotently by slug. approval_required.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_page_featured_image":{"operations":["set_featured_image"],"description":"Set or remove a page featured image by attachment_id. auto.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_menu_item":{"operations":["create","update","move","delete","bulk_reorder"],"description":"Create custom URL, page, post, or taxonomy menu links; update labels/URLs/parents/positions; move, delete, and bulk reorder items. Always approval_required. Since plugin 1.1.5, create validates parent_item_id upfront (existing item of the same menu) and verifies it persisted (read-after-write) — it errors instead of silently creating the item at top level.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_media":{"operations":["upload"],"description":"Upload a base64 image to the WordPress media library immediately and return id/url/alt.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_seo_title":{"operations":["update"],"description":"Update a post or page SEO title and verify that WordPress persisted it. data: [{ post_id, value | seo_title }]. auto.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_meta_description":{"operations":["update"],"description":"Update a post or page meta description and verify that WordPress persisted it. data: [{ post_id, value | meta_description }]. auto.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_reading_settings":{"operations":["update"],"description":"Update Reading settings such as page_for_posts. approval_required.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_discussion_settings":{"operations":["update"],"description":"Update global comment defaults and notifications. approval_required.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_user":{"operations":["create","update"],"description":"Create/update WordPress users for post author bylines. approval_required.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_cache":{"operations":["purge","configure"],"description":"Purge supported cache plugins/object cache automatically, or configure conservative cache toggles after approval.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_htaccess":{"operations":["upsert_block"],"description":"Insert/update only the managed dp-seo-perf .htaccess block with backup. approval_required.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_images":{"operations":["convert_webp","regenerate_thumbnails","bulk_lazy"],"description":"Generate WebP files, regenerate thumbnails, or add lazy/async attributes to saved HTML in batches. approval_required.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_assets":{"operations":["rewrite_html_webp","undo_html_webp"],"description":"Wrap saved post/page img tags with picture/source WebP markup and restore automatic backups. approval_required.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_yoast_content_types":{"operations":["update","undo"],"description":"Update or restore Yoast Search Appearance settings for registered post types, taxonomies, and archives. Creates an automatic backup and always requires approval.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_customizer":{"operations":["update","undo"],"description":"Update or restore active-theme Customizer settings such as footer/copyright text. Creates an automatic backup and always requires approval.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_widgets":{"operations":["update_text","undo_text"],"description":"Update or restore text/custom HTML widgets in footer sidebars. Creates an automatic backup and always requires approval.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"wp_plugins":{"operations":["activate","deactivate"],"description":"Activate or deactivate installed WordPress plugins by slug or file. Must-use, network-active, and DP SEO Manager itself are protected. Creates an automatic backup and always requires approval.","x-mcp":{"channel":"wordpress","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}}},"x-examples":[{"description":"Upload an image to the media library","body":{"resource":"wp_media","operation":"upload","data":[{"filename":"hero-seo-agencias.jpg","mime_type":"image/jpeg","base64":"...","alt":"Equipo revisando estrategia SEO para agencias","attach_to_post_id":3421}],"agent_note":"Subir imagen a la mediateca para usarla en una landing."}},{"description":"Create, publish, and link a new Gutenberg/native page","body":{"resource":"wp_page_with_menu","operation":"create_publish_and_link","data":[{"title":"Mantenimiento WordPress","slug":"mantenimiento-wordpress","content":"<!-- wp:paragraph --><p>Servicio de mantenimiento WordPress.</p><!-- /wp:paragraph -->","seo_title":"Mantenimiento WordPress profesional","meta_description":"Servicio de mantenimiento WordPress para empresas.","menu":{"theme_location":"primary","label":"Mantenimiento WordPress"}}],"agent_note":"Publicar nueva página y enlazarla al menú principal."}},{"description":"Clone an Elementor/Divi template and replace text","body":{"resource":"wp_page_with_menu","operation":"clone_publish_and_link","data":[{"source_page_id":123,"title":"SEO Local","slug":"seo-local","replacements":[{"find":"Nombre del servicio","replace":"SEO Local"}],"menu":{"theme_location":"primary","label":"SEO Local"}}],"agent_note":"Clono una plantilla para preservar el diseño del builder."}}]}},"/api/landing-pages/agent-query":{"post":{"summary":"Native landing pages data","description":"Read native DigitalPublic landing pages: block-based content, immutable versions, domains, brand theme, and signed preview URLs. Landing pages are hosted by DigitalPublic on wildcard subdomains; no external CMS involved. Cookie consent and non-essential tracking gating are enabled by default for every landing; only explicit meta.cookieConsent.enabled:false disables them and produces a validation warning.","tags":["LandingPages"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"list_pages","description":"List landing pages of the project with status, hostname, published/latest version numbers.","params":{"status":{"type":"string","enum":["draft","published","archived"],"optional":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_page","description":"Full detail of one landing page: domains, published version, latest version with contentJson.","params":{"id":{"type":"string","optional":true},"slug":{"type":"string","optional":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_domain_cutover","description":"Read the recoverable custom-domain cutover state, timestamps, error and next action.","params":{"domainId":{"type":"string","required":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_versions","description":"Immutable version history of a landing page.","params":{"pageId":{"type":"string","required":true},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_version","description":"One version with its contentJson (default: latest).","params":{"pageId":{"type":"string","required":true},"versionNumber":{"type":"number","optional":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_block_types","description":"Available block types with fields and limits, the content document guide, and the brand theme schema. Call this before composing content. Cookie consent is always enabled by default and gates lp_vid/tracking until analytics consent; agents must not set meta.cookieConsent.enabled:false without an explicit user instruction. Includes safe editorial Markdown/GFM, image, gallery, stats, logos, video and chart blocks; hero urlCapture for a domain-first lead flow; sitePages for full commercial routes such as /pricing and /contact with their own SEO metadata; auxPages for legal copy; media backgrounds; CRM lead forms; JSON-LD; global navigation; quick contact; favicon; and multi-language subdirectories with reciprocal hreflang.","params":{},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_theme","description":"Brand design tokens of the project (colors, fonts, radius, logo).","params":{},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"preview_url","description":"Signed preview URL (7 days) of any version, including drafts. Share it with humans or use it to inspect the rendered page. An optional path opens a sitePage, auxiliary page, or draft blog index, and preview navigation preserves the signed token across the whole site.","params":{"pageId":{"type":"string","required":true},"versionId":{"type":"string","optional":true},"path":{"type":"string","optional":true,"description":"sitePage, auxiliary page, or blog path such as pricing, about-us, contact, privacy, or blog"}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_metrics","description":"First-party metrics of a landing: pageviews, unique visitors, conversions by goal (form_submit, cta_click, custom), visitor-deduped conversion rate, and daily series. Form submissions also create CRM leads (source web_form, sourceDetail landing:<slug>).","params":{"pageId":{"type":"string","required":true},"from":{"type":"string","optional":true,"description":"ISO date, default 30 days ago"},"to":{"type":"string","optional":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_experiment_results","description":"A/B experiment results: visitors and conversions per variant (visitor-deduped), rate, Wilson 95% CI, lift vs control, and two-proportion p-value with a plain-language note. The platform never auto-declares a winner: when results are conclusive, propose landing_experiment.declare_winner (human approval).","params":{"experimentId":{"type":"string","required":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_site_pages","description":"List Sites v2 pages under routes of one LandingPage site container.","params":{"landingPageId":{"type":"string","required":true},"status":{"type":"string","optional":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_site_page","description":"Read a Sites v2 page, published version and latest immutable draft.","params":{"pageId":{"type":"string","required":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_site_shared_sections","description":"List site-level shared sections and independent SitePage consumers.","params":{"landingPageId":{"type":"string","required":true},"version":{"type":"string","enum":["latest","published"],"optional":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_site_shared_section","description":"Read one site-level shared section and its consumers.","params":{"landingPageId":{"type":"string","required":true},"key":{"type":"string","required":true},"version":{"type":"string","enum":["latest","published"],"optional":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_site_page_versions","description":"List immutable Sites v2 page versions.","params":{"pageId":{"type":"string","required":true},"limit":{"type":"number","optional":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"site_page_preview_url","description":"Create a public, signed, noindex preview URL for a Sites v2 page version. It needs no session and fails closed when the signature is missing, expired, or invalid. Preview navigation keeps signed URLs for known draft pages.","params":{"pageId":{"type":"string","required":true},"versionId":{"type":"string","optional":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_redirects","description":"List redirects with HTTP code, total uses, last use, and linked issue.","params":{"pageId":{"type":"string","optional":true,"description":"LandingPage id"},"q":{"type":"string","optional":true},"page":{"type":"number","optional":true},"pageSize":{"type":"number","optional":true},"sort":{"type":"string","optional":true},"order":{"type":"string","optional":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_site_health_summary","description":"Operational summary of actionable 404s, critical errors, form failures, observations, redirects, and filtered scanner noise.","params":{"pageId":{"type":"string","optional":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_site_issues","description":"List durable site issues with filters, sorting, and pagination. Do not propose a redirect from one isolated 404 or automated scanner traffic. Prioritize broken internal links, confirmed browsers, and search crawlers.","params":{"pageId":{"type":"string","optional":true},"status":{"type":"string","optional":true},"severity":{"type":"string","optional":true},"outcome":{"type":"string","optional":true},"statusCode":{"type":"number","optional":true},"hostname":{"type":"string","optional":true},"source":{"type":"string","optional":true,"enum":["confirmed_browser","person","search_engine","internal","bot","unknown"]},"q":{"type":"string","optional":true},"from":{"type":"string","optional":true},"to":{"type":"string","optional":true},"page":{"type":"number","optional":true},"pageSize":{"type":"number","optional":true},"sort":{"type":"string","optional":true},"order":{"type":"string","optional":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_site_issue","description":"Read one issue and its recent hourly evolution without personal data, query strings, stack traces, or form bodies.","params":{"issueId":{"type":"string","required":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_site_request_log","description":"List privacy-safe hourly buckets for errors, rate limits, and redirect uses.","params":{"pageId":{"type":"string","optional":true},"outcome":{"type":"string","optional":true},"statusCode":{"type":"number","optional":true},"hostname":{"type":"string","optional":true},"q":{"type":"string","optional":true},"from":{"type":"string","optional":true},"to":{"type":"string","optional":true},"page":{"type":"number","optional":true},"pageSize":{"type":"number","optional":true},"sort":{"type":"string","optional":true},"order":{"type":"string","optional":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_site_noise_summary","description":"Summarize filtered automated probes by site and family. This is security telemetry, not actionable redirect work.","params":{"pageId":{"type":"string","optional":true},"hostname":{"type":"string","optional":true},"q":{"type":"string","optional":true},"from":{"type":"string","optional":true},"to":{"type":"string","optional":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pending_mutations","description":"List landing mutations of this project.","params":{"status":{"type":"string","optional":true},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_mutation_status","description":"Check one landing mutation by id.","params":{"mutationId":{"type":"string","required":true}},"x-mcp":{"channel":"landing_pages","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/landing-pages/agent-mutate":{"post":{"summary":"Native landing pages mutations","description":"Create and iterate landing pages as block-based JSON documents. Drafts are auto-executed; publishing, rollback, archive, and brand theme changes queue for human approval with a rendered preview. Content is validated against the block schema before persisting.","tags":["LandingPages"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["resource","operation","data"],"properties":{"resource":{"type":"string","enum":["landing_page","site_page","site_shared_section","site_redirect","site_issue","landing_theme","landing_variant","landing_experiment","landing_domain"]},"operation":{"type":"string","description":"landing_page: create/update_draft/publish/rollback/archive. site_page: create/update_draft/publish/rollback/change_path/archive. site_shared_section: create/update/archive. site_redirect: create/update/remove. site_issue: ignore/resolve/reopen. landing_theme: update. landing_variant: create/update/archive. landing_experiment: create/start/stop/declare_winner. landing_domain zero-downtime flow: add, verify_ownership (verify alias), prepare, arm, check_dns, activate, rollback, disarm, set_primary, remove."},"data":{"type":"array","maxItems":200,"description":"Array of payloads. For domains, verify ownership before prepare; arm with approval immediately before the DNS cut; check_dns validates HTTP, TLS and signed routing; activate finalizes canonical. rollback keeps a warm fallback until DNS is restored and disarm is safe. Site content follows the list_block_types guide."},"agent_note":{"type":"string","description":"Recommended explanation for the human approver."},"validate_only":{"type":"boolean","default":false,"description":"Validate slug/content (including image ownership) or dry-run a complete site_redirect.create manifest without persisting."}}}}}},"responses":{"200":{"description":"Executed immediately or queued for approval","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-resources":{"landing_page":{"operations":["create","update_draft","publish","rollback","archive"],"description":"Native landing page lifecycle. create/update_draft are auto (drafts are invisible to visitors); publish/rollback/archive are approval_required with a signed preview attached for the reviewer.","operationParams":{"create":{"data":{"type":"array","required":true,"items":{"type":"object","properties":{"pageId":{"type":"string","description":"Requerido para update_draft."},"name":{"type":"string","description":"Requerido para create."},"slug":{"type":"string","description":"Requerido para create."},"content":{"type":"object","required":true,"description":"Documento JSON validado por la plataforma. Los bloques disponibles y sus campos son los mismos que devuelve list_block_types.","blockTypes":[{"type":"hero","description":"Cabecera principal. Uno por página, normalmente el primero. layout 'split' muestra la imagen al lado del texto.","fields":{"id":"string [a-z0-9_-] único en la página (todos los bloques lo llevan)","eyebrow":"string ≤80 opcional (texto pequeño sobre el headline)","headline":"string 1-120 requerido","subheadline":"string ≤300 opcional","image":"{ fileId: CreativeFile.id de imagen del proyecto, alt: string } opcional","layout":"'center' | 'split' (default center)","ctas":"hasta 2 × { label ≤60, href, style: 'primary'|'secondary' }","urlCapture":"opcional: { placeholder, buttonLabel, destination ('/contact'), queryParam (default website), ariaLabel } — primer paso dominio → formulario"}},{"type":"features","description":"Rejilla de beneficios/características.","fields":{"title":"string ≤120 opcional","columns":"2 | 3 | 4 (default 3)","items":"2-12 × { icon?: uno de [check, star, zap, shield, heart, rocket, target, trending-up, clock, users, mail, phone, globe, award, thumbs-up, lightbulb, bar-chart, lock, gift, sparkles], title ≤80, description ≤300 }"}},{"type":"testimonials","description":"Testimonios de clientes.","fields":{"title":"string ≤120 opcional","items":"1-6 × { quote ≤400, author ≤80, role? ≤120, avatar?: { fileId, alt } }"}},{"type":"faq","description":"Preguntas frecuentes (se renderiza con schema.org FAQPage).","fields":{"title":"string ≤120 opcional","items":"1-12 × { question ≤200, answer ≤1000 }"}},{"type":"editorial","description":"Contenido editorial largo en Markdown/GFM seguro y semántico. Ideal para migrar páginas con texto, tablas e imágenes intercaladas.","fields":{"markdown":"Markdown/GFM string 1-50000 requerido; admite ## H2, ### H3, párrafos, negrita, cursiva, listas, enlaces, citas, tablas e imágenes ![alt](creative:<fileId>). No admite H1 ni saltos H2→H3; HTML raw queda inerte."}},{"type":"cta","description":"Llamada a la acción intermedia o final.","fields":{"eyebrow":"string ≤80 opcional","headline":"string 1-120 requerido","subtext":"string ≤300 opcional","button":"{ label ≤60, href }","note":"string ≤120 opcional (microcopy bajo el botón)","tone":"'default' | 'inverted' (inverted usa el color primario de fondo)","variant":"'standard' | 'spotlight' (spotlight usa una tarjeta editorial con composición responsive)"}},{"type":"pricing","description":"Tabla de precios/planes.","fields":{"title":"string ≤120 opcional","plans":"1-4 × { name ≤60, price ≤30 (texto, ej. '49 €'), period? ≤30, features: ≤10 strings, cta: { label, href }, highlighted?: boolean }"}},{"type":"leadForm","description":"Formulario de captación. Máximo uno por página. El envío crea un lead en el CRM del proyecto y registra una conversión con el goal indicado.","fields":{"title":"string ≤120 opcional","subtitle":"string ≤300 opcional","fields":"1-6 × { key: name|email|phone|company|website|message, label? ≤60, required: boolean } — email es obligatorio siempre","consentText":"string 10-500 requerido (texto RGPD junto al checkbox de consentimiento)","privacyPolicyPath":"path de una auxPage de privacidad; se configura junto con privacyLinkText","privacyLinkText":"subcadena exacta de consentText que se enlaza a privacyPolicyPath en una pestaña nueva","newsletterPublicId":"opcional, ID público nl_... de una newsletter de proyecto o grupo; requiere newsletterConsentText","newsletterConsentText":"opcional, consentimiento separado para recibir la newsletter; no es obligatorio para enviar el lead","newsletterNoticeVersion":"versión del aviso legal aceptado para la newsletter (default 'v1')","submitLabel":"string ≤60 (default 'Enviar')","successTitle":"string ≤80 (default '¡Solicitud enviada!') — título del card de éxito","successMessage":"string ≤300","successNextSteps":"opcional, 1-4 × string ≤150 — lista con checks de qué pasará ahora, mostrada en el card de éxito","goal":"string [a-z0-9_] (default 'form_submit') — nombre del goal de conversión"}},{"type":"footer","description":"Pie de página global y responsive. Admite enlaces simples heredados y hasta 6 columnas tituladas; legalLinks queda separado para privacidad, cookies y aviso legal. Los href internos tipo '/privacy' deben corresponder a una auxPage.","fields":{"text":"string ≤300 opcional (ej. copyright)","links":"≤8 × { label ≤60, href }","groups":"opcional, ≤6 × { title ≤60, links: 1-10 × { label ≤60, href } }; máximo 60 destinos en total","legalLinks":"≤8 × { label ≤60, href }"}},{"type":"image","description":"Imagen suelta con caption opcional.","fields":{"image":"{ fileId, alt } requerido","caption":"string ≤200 opcional","width":"'compact' (560px) | 'normal' (760px) | 'wide' (1080px)"}},{"type":"gallery","description":"Galería de imágenes en rejilla (propiedades, regiones, oficina…).","fields":{"title":"string ≤120 opcional","columns":"2 | 3 | 4 (default 3)","images":"2-12 × { fileId, alt, caption? ≤200 }"}},{"type":"stats","description":"Cifras destacadas que generan confianza (años, clientes, propiedades…).","fields":{"title":"string ≤120 opcional","items":"2-6 × { value ≤20 (ej. '15+', '98 %'), label ≤80 }"}},{"type":"chart","description":"Gráfica comparativa accesible con animación progresiva de barras.","fields":{"title":"string ≤120 opcional","description":"string ≤300 opcional","variant":"'bars' | 'progress'","items":"2-8 × { label ≤80, value 0-100, displayValue? ≤30, accent?: boolean }"}},{"type":"logos","description":"Logos de confianza: asociaciones, medios, certificaciones. En escala de grises con hover.","fields":{"title":"string ≤120 opcional (ej. 'Confían en nosotros')","items":"2-10 × { fileId, alt, href? (enlace externo opcional) }"}},{"type":"video","description":"Vídeo embebido: YouTube (youtube-nocookie), Vimeo (dnt) o un CreativeFile de vídeo del proyecto.","fields":{"title":"string ≤120 opcional","provider":"'youtube' | 'vimeo' | 'file'","videoId":"id del vídeo (youtube/vimeo)","fileId":"CreativeFile kind video (provider 'file')","poster":"{ fileId, alt } opcional (imagen de póster)"}}],"contentGuide":{"schemaVersion":1,"maxBlocks":20,"document":"{ schemaVersion: 1, meta: { title ≤70, siteName? ≤40 (marca pública corta, independiente de Project.name), description? ≤160, ogImageFileId?, faviconFileId?, locale ('es', 'nl-BE'…), robots: 'index'|'noindex', alternates?, xDefaultSlug?, languageSelector?, structuredData?, cookieConsent?, nav?, quickContact? }, themeOverrides?: <themeSchema parcial>, sharedSections?: { key: block|blocks }, blocks: [1..20 bloques], sitePages?: [≤8 páginas comerciales], auxPages?: [≤5 páginas auxiliares] }","cookieConsent":{"description":"OBLIGATORIO POR DEFECTO para todas las landings europeas, nuevas y existentes: aunque meta.cookieConsent se omita, el renderer muestra el banner y bloquea lp_vid, pageviews, conversiones y futuros píxeles hasta consentir su categoría. El agente NO debe desactivarlo salvo instrucción explícita del usuario. Config opcional: { enabled (default true), policyVersion (default '1'; cambiarla vuelve a solicitar consentimiento), cookiePolicyPath (default 'cookies'), privacyPolicyPath (default 'privacy'), text?: overrides i18n }. Solo meta.cookieConsent.enabled:false lo desactiva y la validación emitirá un warning legal.","categories":"necessary siempre activa; analytics controla lp_vid y beacons first-party; marketing controla Google Consent Mode v2 y futuros píxeles Google/Meta.","example":"{ cookieConsent: { policyVersion: \"2026-07\", cookiePolicyPath: \"cookies\", privacyPolicyPath: \"privacy\" } }"},"favicon":"meta.faviconFileId (CreativeFile de imagen del proyecto, idealmente cuadrado ~512×512) se emite como <link rel='icon'> en TODAS las páginas del sitio (home, blog, artículos). Sube o genera el icono con /api/creatives/upload o /api/creatives/generate.","structuredData":{"description":"JSON-LD de la identidad editorial y la entidad dueña del sitio (SEO/AEO). meta.structuredData = { type: 'Organization'|'LocalBusiness'|'WebSite', name ≤120, url?, areaServed?: [códigos de país ISO-2, ≤10], telephone?, email?, address?: { streetAddress, addressLocality, postalCode?, addressRegion?, addressCountry? (ISO-2) }, priceRange? (solo LocalBusiness, ej. 'desde 34,99 €/mes'), sameAs?: [urls de perfiles sociales, ≤10] }. No hay país por defecto: Service usa areaServed explícito, addressCountry o la región inequívoca de meta.locale (p.ej. en-US), y lo omite si no puede determinarlo. Article publisher usa esta organización o meta.siteName, el dominio canónico activo y el logo del tema. En previews sin canonical público no se inventan URLs.","example":"{ type: \"LocalBusiness\", name: \"Domiciliación de Empresas Alicante\", areaServed: [\"ES\"], telephone: \"+34 600 000 000\", priceRange: \"desde 34,99 €/mes\", address: { streetAddress: \"Calle Mayor 1\", addressLocality: \"Alicante\", postalCode: \"03001\", addressCountry: \"ES\" } }"},"hrefFormats":"http(s)://..., /ruta (sitePage o auxPage, ej. '/contact' o '/privacy'), /blog, #id-de-bloque (ancla interna en la página), mailto:..., tel:...","nav":{"description":"Cabecera global jerárquica y accesible, compartida por home, sitePages, auxPages y blog. meta.nav admite hasta 12 elementos de primer nivel: enlaces { label ≤60, href, cta? } o grupos { label ≤40, children: 1-10 enlaces }. Máximo 40 destinos. Los grupos se muestran como dropdowns de escritorio y submenús equivalentes en móvil, con foco, Escape y estado activo. La forma plana anterior sigue siendo válida. Para secciones de la home usa '/#precio', no '#precio'; enlaza blog, tags, RSS y páginas legales con sus rutas.","example":"{ nav: [{ label: \"Inicio\", href: \"/\" }, { label: \"Soluciones\", children: [{ label: \"Servicios\", href: \"/#servicios\" }, { label: \"Precios\", href: \"/pricing\" }] }, { label: \"Recursos\", children: [{ label: \"Blog\", href: \"/blog\" }, { label: \"RSS\", href: \"/blog/feed.xml\" }] }, { label: \"Contacto\", href: \"/#form\", cta: true }] }"},"quickContact":{"description":"Accesos rápidos de contacto como botones-icono redondos a la derecha de la cabecera (también en el blog). meta.quickContact = [{ href, label? }] (≤4). El icono se deriva automáticamente del href: tel:→teléfono, wa.me/whatsapp→WhatsApp, mailto:→email. Úsalo para teléfono y WhatsApp de acceso directo. NOTA: los enlaces del footer (block footer.links) también muestran icono automático según su href (tel/WhatsApp/mailto/blog), sin configuración extra.","example":"{ quickContact: [{ href: \"tel:+34600000000\", label: \"Llamar\" }, { href: \"https://wa.me/34600000000\", label: \"WhatsApp\" }] }"},"images":"Sube imágenes con POST /api/creatives/upload (multipart) o genera con POST /api/creatives/generate (IA, gpt-image-2) y usa el fileId devuelto. Solo ficheros del mismo proyecto. En editorial usa ![texto alt](creative:<fileId>); el renderer genera srcset responsive. Fondos de hero/cta: backgroundImage { fileId, overlay?: { color hex, opacity 0-0.9 } }.","multiLanguage":{"description":"Sitio multi-idioma servido en SUBDIRECTORIOS de un único host (mejor para SEO/GEO: consolida la autoridad de dominio). La landing PRINCIPAL (la del host apex) declara meta.locale (idioma principal, en la raíz /) y meta.alternates = [{ locale, slug }] con los slugs de las landings traducidas del MISMO proyecto. Cada idioma secundario se sirve bajo su prefijo de path (/en/, /fr/…) del mismo host; las hermanas NO necesitan dominio propio (basta con que estén publicadas). Emite hreflang recíprocos con URLs de subdirectorio + x-default → raíz. languageSelector: true muestra un DESPLEGABLE de idioma en la cabecera (nombre nativo de cada idioma), presente también en el blog. Solo se enlazan las hermanas publicadas.","example":"{ locale: \"es\", alternates: [{ locale: \"en\", slug: \"company-registration-alicante\" }, { locale: \"fr\", slug: \"domiciliation-entreprises-alicante\" }], xDefaultSlug: \"domiciliacion-de-empresas\", languageSelector: true }"},"auxPages":{"description":"Páginas auxiliares servidas en el mismo host (issue #392): privacidad, aviso legal, cookies. En un sitio multi-idioma se sirven bajo el prefijo del idioma (/en/privacy). Cada una: { path ('privacy'), title, robots (default noindex), sections: [{ heading?, text ≤5000 (párrafos separados por línea en blanco) }] }. Heredan header global y footer raíz. Enlázalas desde footer.legalLinks con href '/privacy'.","gdprTemplate":"Secciones recomendadas para la política de privacidad RGPD: 1) Responsable del tratamiento (nombre, NIF, domicilio, email); 2) Finalidad (gestionar la solicitud del formulario y el envío de información comercial); 3) Legitimación (consentimiento del interesado); 4) Destinatarios (no se ceden datos salvo obligación legal; encargados de tratamiento con quien se haya contratado hosting/CRM); 5) Derechos (acceso, rectificación, supresión, oposición, limitación y portabilidad, ante el responsable o la AEPD); 6) Conservación (mientras dure la relación o hasta la retirada del consentimiento). Personaliza con los datos reales del proyecto ANTES de publicar."},"sharedSections":{"description":"Secciones compartidas reutilizables: define sharedSections: { 'footer-legal': block|blocks } en la home o usa site_shared_section.create/update/archive, y colócalas en la home o cualquier SitePage independiente con { id, type:'include', ref:'footer-legal' }. El id del include es un destino de ancla válido (por ejemplo href:'#contacto') y los bloques internos se acotan como includeId-blockId. Las SitePages heredan la versión latest/published correspondiente de la home. El renderer expande referencias anidadas y rechaza ciclos e IDs duplicados."},"sitePages":{"description":"Páginas comerciales completas bajo el mismo dominio y tema. Cada una: { path, title ≤70, description? ≤160, robots (default index), blocks: [1..20] }. Se sirven en /<path>, tienen canonical propio y aparecen en sitemap. Úsalas para pricing, technology, about-us y contact; reserva auxPages para textos legales.","example":"{ path: \"contact\", title: \"Contacto · Mi empresa\", description: \"Habla con el equipo\", blocks: [{ id: \"contact-hero\", type: \"hero\", headline: \"Hablemos\" }, { id: \"contact-form\", type: \"leadForm\", fields: [{ key: \"website\" }, { key: \"name\" }, { key: \"email\", required: true }], consentText: \"Acepto la política de privacidad y el tratamiento de mis datos.\", privacyPolicyPath: \"privacy\", privacyLinkText: \"política de privacidad\" }] }"},"theme":{"description":"Design tokens del proyecto (landing_theme.update, requiere aprobación). themeOverrides por página acepta los mismos campos.","colors":"primary, primaryContrast, background, surface, text, muted, accent (hex)","fonts":"heading/body: uno de [system, inter, georgia, mono, serif-display, geometric, humanist]","radius":"'none' | 'sm' | 'md' | 'full'","logoFileId":"CreativeFile.id opcional. Si está presente (en el tema del proyecto o en themeOverrides de la página), el renderer muestra un header ligero con el logo enlazado a la raíz (y el selector de idioma a la derecha si languageSelector: true) y repite el logo en el footer junto al copyright."}}}}}}},"update_draft":{"data":{"type":"array","required":true,"items":{"type":"object","properties":{"pageId":{"type":"string","description":"Requerido para update_draft."},"name":{"type":"string","description":"Requerido para create."},"slug":{"type":"string","description":"Requerido para create."},"content":{"type":"object","required":true,"description":"Documento JSON validado por la plataforma. Los bloques disponibles y sus campos son los mismos que devuelve list_block_types.","blockTypes":[{"type":"hero","description":"Cabecera principal. Uno por página, normalmente el primero. layout 'split' muestra la imagen al lado del texto.","fields":{"id":"string [a-z0-9_-] único en la página (todos los bloques lo llevan)","eyebrow":"string ≤80 opcional (texto pequeño sobre el headline)","headline":"string 1-120 requerido","subheadline":"string ≤300 opcional","image":"{ fileId: CreativeFile.id de imagen del proyecto, alt: string } opcional","layout":"'center' | 'split' (default center)","ctas":"hasta 2 × { label ≤60, href, style: 'primary'|'secondary' }","urlCapture":"opcional: { placeholder, buttonLabel, destination ('/contact'), queryParam (default website), ariaLabel } — primer paso dominio → formulario"}},{"type":"features","description":"Rejilla de beneficios/características.","fields":{"title":"string ≤120 opcional","columns":"2 | 3 | 4 (default 3)","items":"2-12 × { icon?: uno de [check, star, zap, shield, heart, rocket, target, trending-up, clock, users, mail, phone, globe, award, thumbs-up, lightbulb, bar-chart, lock, gift, sparkles], title ≤80, description ≤300 }"}},{"type":"testimonials","description":"Testimonios de clientes.","fields":{"title":"string ≤120 opcional","items":"1-6 × { quote ≤400, author ≤80, role? ≤120, avatar?: { fileId, alt } }"}},{"type":"faq","description":"Preguntas frecuentes (se renderiza con schema.org FAQPage).","fields":{"title":"string ≤120 opcional","items":"1-12 × { question ≤200, answer ≤1000 }"}},{"type":"editorial","description":"Contenido editorial largo en Markdown/GFM seguro y semántico. Ideal para migrar páginas con texto, tablas e imágenes intercaladas.","fields":{"markdown":"Markdown/GFM string 1-50000 requerido; admite ## H2, ### H3, párrafos, negrita, cursiva, listas, enlaces, citas, tablas e imágenes ![alt](creative:<fileId>). No admite H1 ni saltos H2→H3; HTML raw queda inerte."}},{"type":"cta","description":"Llamada a la acción intermedia o final.","fields":{"eyebrow":"string ≤80 opcional","headline":"string 1-120 requerido","subtext":"string ≤300 opcional","button":"{ label ≤60, href }","note":"string ≤120 opcional (microcopy bajo el botón)","tone":"'default' | 'inverted' (inverted usa el color primario de fondo)","variant":"'standard' | 'spotlight' (spotlight usa una tarjeta editorial con composición responsive)"}},{"type":"pricing","description":"Tabla de precios/planes.","fields":{"title":"string ≤120 opcional","plans":"1-4 × { name ≤60, price ≤30 (texto, ej. '49 €'), period? ≤30, features: ≤10 strings, cta: { label, href }, highlighted?: boolean }"}},{"type":"leadForm","description":"Formulario de captación. Máximo uno por página. El envío crea un lead en el CRM del proyecto y registra una conversión con el goal indicado.","fields":{"title":"string ≤120 opcional","subtitle":"string ≤300 opcional","fields":"1-6 × { key: name|email|phone|company|website|message, label? ≤60, required: boolean } — email es obligatorio siempre","consentText":"string 10-500 requerido (texto RGPD junto al checkbox de consentimiento)","privacyPolicyPath":"path de una auxPage de privacidad; se configura junto con privacyLinkText","privacyLinkText":"subcadena exacta de consentText que se enlaza a privacyPolicyPath en una pestaña nueva","newsletterPublicId":"opcional, ID público nl_... de una newsletter de proyecto o grupo; requiere newsletterConsentText","newsletterConsentText":"opcional, consentimiento separado para recibir la newsletter; no es obligatorio para enviar el lead","newsletterNoticeVersion":"versión del aviso legal aceptado para la newsletter (default 'v1')","submitLabel":"string ≤60 (default 'Enviar')","successTitle":"string ≤80 (default '¡Solicitud enviada!') — título del card de éxito","successMessage":"string ≤300","successNextSteps":"opcional, 1-4 × string ≤150 — lista con checks de qué pasará ahora, mostrada en el card de éxito","goal":"string [a-z0-9_] (default 'form_submit') — nombre del goal de conversión"}},{"type":"footer","description":"Pie de página global y responsive. Admite enlaces simples heredados y hasta 6 columnas tituladas; legalLinks queda separado para privacidad, cookies y aviso legal. Los href internos tipo '/privacy' deben corresponder a una auxPage.","fields":{"text":"string ≤300 opcional (ej. copyright)","links":"≤8 × { label ≤60, href }","groups":"opcional, ≤6 × { title ≤60, links: 1-10 × { label ≤60, href } }; máximo 60 destinos en total","legalLinks":"≤8 × { label ≤60, href }"}},{"type":"image","description":"Imagen suelta con caption opcional.","fields":{"image":"{ fileId, alt } requerido","caption":"string ≤200 opcional","width":"'compact' (560px) | 'normal' (760px) | 'wide' (1080px)"}},{"type":"gallery","description":"Galería de imágenes en rejilla (propiedades, regiones, oficina…).","fields":{"title":"string ≤120 opcional","columns":"2 | 3 | 4 (default 3)","images":"2-12 × { fileId, alt, caption? ≤200 }"}},{"type":"stats","description":"Cifras destacadas que generan confianza (años, clientes, propiedades…).","fields":{"title":"string ≤120 opcional","items":"2-6 × { value ≤20 (ej. '15+', '98 %'), label ≤80 }"}},{"type":"chart","description":"Gráfica comparativa accesible con animación progresiva de barras.","fields":{"title":"string ≤120 opcional","description":"string ≤300 opcional","variant":"'bars' | 'progress'","items":"2-8 × { label ≤80, value 0-100, displayValue? ≤30, accent?: boolean }"}},{"type":"logos","description":"Logos de confianza: asociaciones, medios, certificaciones. En escala de grises con hover.","fields":{"title":"string ≤120 opcional (ej. 'Confían en nosotros')","items":"2-10 × { fileId, alt, href? (enlace externo opcional) }"}},{"type":"video","description":"Vídeo embebido: YouTube (youtube-nocookie), Vimeo (dnt) o un CreativeFile de vídeo del proyecto.","fields":{"title":"string ≤120 opcional","provider":"'youtube' | 'vimeo' | 'file'","videoId":"id del vídeo (youtube/vimeo)","fileId":"CreativeFile kind video (provider 'file')","poster":"{ fileId, alt } opcional (imagen de póster)"}}],"contentGuide":{"schemaVersion":1,"maxBlocks":20,"document":"{ schemaVersion: 1, meta: { title ≤70, siteName? ≤40 (marca pública corta, independiente de Project.name), description? ≤160, ogImageFileId?, faviconFileId?, locale ('es', 'nl-BE'…), robots: 'index'|'noindex', alternates?, xDefaultSlug?, languageSelector?, structuredData?, cookieConsent?, nav?, quickContact? }, themeOverrides?: <themeSchema parcial>, sharedSections?: { key: block|blocks }, blocks: [1..20 bloques], sitePages?: [≤8 páginas comerciales], auxPages?: [≤5 páginas auxiliares] }","cookieConsent":{"description":"OBLIGATORIO POR DEFECTO para todas las landings europeas, nuevas y existentes: aunque meta.cookieConsent se omita, el renderer muestra el banner y bloquea lp_vid, pageviews, conversiones y futuros píxeles hasta consentir su categoría. El agente NO debe desactivarlo salvo instrucción explícita del usuario. Config opcional: { enabled (default true), policyVersion (default '1'; cambiarla vuelve a solicitar consentimiento), cookiePolicyPath (default 'cookies'), privacyPolicyPath (default 'privacy'), text?: overrides i18n }. Solo meta.cookieConsent.enabled:false lo desactiva y la validación emitirá un warning legal.","categories":"necessary siempre activa; analytics controla lp_vid y beacons first-party; marketing controla Google Consent Mode v2 y futuros píxeles Google/Meta.","example":"{ cookieConsent: { policyVersion: \"2026-07\", cookiePolicyPath: \"cookies\", privacyPolicyPath: \"privacy\" } }"},"favicon":"meta.faviconFileId (CreativeFile de imagen del proyecto, idealmente cuadrado ~512×512) se emite como <link rel='icon'> en TODAS las páginas del sitio (home, blog, artículos). Sube o genera el icono con /api/creatives/upload o /api/creatives/generate.","structuredData":{"description":"JSON-LD de la identidad editorial y la entidad dueña del sitio (SEO/AEO). meta.structuredData = { type: 'Organization'|'LocalBusiness'|'WebSite', name ≤120, url?, areaServed?: [códigos de país ISO-2, ≤10], telephone?, email?, address?: { streetAddress, addressLocality, postalCode?, addressRegion?, addressCountry? (ISO-2) }, priceRange? (solo LocalBusiness, ej. 'desde 34,99 €/mes'), sameAs?: [urls de perfiles sociales, ≤10] }. No hay país por defecto: Service usa areaServed explícito, addressCountry o la región inequívoca de meta.locale (p.ej. en-US), y lo omite si no puede determinarlo. Article publisher usa esta organización o meta.siteName, el dominio canónico activo y el logo del tema. En previews sin canonical público no se inventan URLs.","example":"{ type: \"LocalBusiness\", name: \"Domiciliación de Empresas Alicante\", areaServed: [\"ES\"], telephone: \"+34 600 000 000\", priceRange: \"desde 34,99 €/mes\", address: { streetAddress: \"Calle Mayor 1\", addressLocality: \"Alicante\", postalCode: \"03001\", addressCountry: \"ES\" } }"},"hrefFormats":"http(s)://..., /ruta (sitePage o auxPage, ej. '/contact' o '/privacy'), /blog, #id-de-bloque (ancla interna en la página), mailto:..., tel:...","nav":{"description":"Cabecera global jerárquica y accesible, compartida por home, sitePages, auxPages y blog. meta.nav admite hasta 12 elementos de primer nivel: enlaces { label ≤60, href, cta? } o grupos { label ≤40, children: 1-10 enlaces }. Máximo 40 destinos. Los grupos se muestran como dropdowns de escritorio y submenús equivalentes en móvil, con foco, Escape y estado activo. La forma plana anterior sigue siendo válida. Para secciones de la home usa '/#precio', no '#precio'; enlaza blog, tags, RSS y páginas legales con sus rutas.","example":"{ nav: [{ label: \"Inicio\", href: \"/\" }, { label: \"Soluciones\", children: [{ label: \"Servicios\", href: \"/#servicios\" }, { label: \"Precios\", href: \"/pricing\" }] }, { label: \"Recursos\", children: [{ label: \"Blog\", href: \"/blog\" }, { label: \"RSS\", href: \"/blog/feed.xml\" }] }, { label: \"Contacto\", href: \"/#form\", cta: true }] }"},"quickContact":{"description":"Accesos rápidos de contacto como botones-icono redondos a la derecha de la cabecera (también en el blog). meta.quickContact = [{ href, label? }] (≤4). El icono se deriva automáticamente del href: tel:→teléfono, wa.me/whatsapp→WhatsApp, mailto:→email. Úsalo para teléfono y WhatsApp de acceso directo. NOTA: los enlaces del footer (block footer.links) también muestran icono automático según su href (tel/WhatsApp/mailto/blog), sin configuración extra.","example":"{ quickContact: [{ href: \"tel:+34600000000\", label: \"Llamar\" }, { href: \"https://wa.me/34600000000\", label: \"WhatsApp\" }] }"},"images":"Sube imágenes con POST /api/creatives/upload (multipart) o genera con POST /api/creatives/generate (IA, gpt-image-2) y usa el fileId devuelto. Solo ficheros del mismo proyecto. En editorial usa ![texto alt](creative:<fileId>); el renderer genera srcset responsive. Fondos de hero/cta: backgroundImage { fileId, overlay?: { color hex, opacity 0-0.9 } }.","multiLanguage":{"description":"Sitio multi-idioma servido en SUBDIRECTORIOS de un único host (mejor para SEO/GEO: consolida la autoridad de dominio). La landing PRINCIPAL (la del host apex) declara meta.locale (idioma principal, en la raíz /) y meta.alternates = [{ locale, slug }] con los slugs de las landings traducidas del MISMO proyecto. Cada idioma secundario se sirve bajo su prefijo de path (/en/, /fr/…) del mismo host; las hermanas NO necesitan dominio propio (basta con que estén publicadas). Emite hreflang recíprocos con URLs de subdirectorio + x-default → raíz. languageSelector: true muestra un DESPLEGABLE de idioma en la cabecera (nombre nativo de cada idioma), presente también en el blog. Solo se enlazan las hermanas publicadas.","example":"{ locale: \"es\", alternates: [{ locale: \"en\", slug: \"company-registration-alicante\" }, { locale: \"fr\", slug: \"domiciliation-entreprises-alicante\" }], xDefaultSlug: \"domiciliacion-de-empresas\", languageSelector: true }"},"auxPages":{"description":"Páginas auxiliares servidas en el mismo host (issue #392): privacidad, aviso legal, cookies. En un sitio multi-idioma se sirven bajo el prefijo del idioma (/en/privacy). Cada una: { path ('privacy'), title, robots (default noindex), sections: [{ heading?, text ≤5000 (párrafos separados por línea en blanco) }] }. Heredan header global y footer raíz. Enlázalas desde footer.legalLinks con href '/privacy'.","gdprTemplate":"Secciones recomendadas para la política de privacidad RGPD: 1) Responsable del tratamiento (nombre, NIF, domicilio, email); 2) Finalidad (gestionar la solicitud del formulario y el envío de información comercial); 3) Legitimación (consentimiento del interesado); 4) Destinatarios (no se ceden datos salvo obligación legal; encargados de tratamiento con quien se haya contratado hosting/CRM); 5) Derechos (acceso, rectificación, supresión, oposición, limitación y portabilidad, ante el responsable o la AEPD); 6) Conservación (mientras dure la relación o hasta la retirada del consentimiento). Personaliza con los datos reales del proyecto ANTES de publicar."},"sharedSections":{"description":"Secciones compartidas reutilizables: define sharedSections: { 'footer-legal': block|blocks } en la home o usa site_shared_section.create/update/archive, y colócalas en la home o cualquier SitePage independiente con { id, type:'include', ref:'footer-legal' }. El id del include es un destino de ancla válido (por ejemplo href:'#contacto') y los bloques internos se acotan como includeId-blockId. Las SitePages heredan la versión latest/published correspondiente de la home. El renderer expande referencias anidadas y rechaza ciclos e IDs duplicados."},"sitePages":{"description":"Páginas comerciales completas bajo el mismo dominio y tema. Cada una: { path, title ≤70, description? ≤160, robots (default index), blocks: [1..20] }. Se sirven en /<path>, tienen canonical propio y aparecen en sitemap. Úsalas para pricing, technology, about-us y contact; reserva auxPages para textos legales.","example":"{ path: \"contact\", title: \"Contacto · Mi empresa\", description: \"Habla con el equipo\", blocks: [{ id: \"contact-hero\", type: \"hero\", headline: \"Hablemos\" }, { id: \"contact-form\", type: \"leadForm\", fields: [{ key: \"website\" }, { key: \"name\" }, { key: \"email\", required: true }], consentText: \"Acepto la política de privacidad y el tratamiento de mis datos.\", privacyPolicyPath: \"privacy\", privacyLinkText: \"política de privacidad\" }] }"},"theme":{"description":"Design tokens del proyecto (landing_theme.update, requiere aprobación). themeOverrides por página acepta los mismos campos.","colors":"primary, primaryContrast, background, surface, text, muted, accent (hex)","fonts":"heading/body: uno de [system, inter, georgia, mono, serif-display, geometric, humanist]","radius":"'none' | 'sm' | 'md' | 'full'","logoFileId":"CreativeFile.id opcional. Si está presente (en el tema del proyecto o en themeOverrides de la página), el renderer muestra un header ligero con el logo enlazado a la raíz (y el selector de idioma a la derecha si languageSelector: true) y repite el logo en el footer junto al copyright."}}}}}}}},"x-mcp":{"channel":"landing_pages","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"landing_theme":{"operations":["update"],"description":"Project brand design tokens applied to all landings. approval_required (affects published pages).","x-mcp":{"channel":"landing_pages","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"landing_variant":{"operations":["create","update","archive"],"description":"A/B variants pointing to immutable versions of the same page. All auto: variants are invisible to visitors until an experiment starts.","x-mcp":{"channel":"landing_pages","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"landing_experiment":{"operations":["create","start","stop","declare_winner"],"description":"Server-side A/B experiments with deterministic sticky assignment (hash of visitor+experiment vs weights). create/stop auto; start and declare_winner approval_required. Traffic split is immutable while running (changing it would re-assign visitors); stop and create a new experiment instead.","x-mcp":{"channel":"landing_pages","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"landing_domain":{"operations":["add","verify","verify_ownership","prepare","arm","check_dns","activate","rollback","disarm","set_primary","remove"],"description":"Recoverable zero-downtime custom-domain cutover through Cloudflare and the nginx catch-all. add returns ownership TXT and CNAME target without changing canonical. verify/verify_ownership checks TXT only; prepare validates the published site, current canonical and critical routes. arm is approval_required and enables a warm route before DNS changes, preventing a DigitalPublic 404 on the first request. check_dns validates HTTP-to-HTTPS, public TLS and the signed endpoint; activate is approval_required and atomically finalizes active/canonical state. rollback restores the previous canonical but keeps the warm fallback until DNS is restored; disarm refuses while DNS still reaches DigitalPublic. Read with get_domain_cutover. Unowned custom domains never serve content.","x-mcp":{"channel":"landing_pages","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"site_page":{"operations":["create","update_draft","publish","rollback","change_path","archive"],"description":"Sites v2 pages on same-domain routes. create/update_draft are auto; publish/rollback/change_path/archive require human approval. Path changes create a permanent redirect. A/B remains home-only.","operationParams":{"create":{"data":{"type":"array","required":true,"items":{"type":"object","properties":{"pageId":{"type":"string","description":"Requerido para update_draft."},"landingPageId":{"type":"string","description":"Requerido para create."},"path":{"type":"string","description":"Requerido para create."},"name":{"type":"string","description":"Requerido para create."},"kind":{"type":"string","description":"Tipo editorial de la página."},"content":{"type":"object","required":true,"description":"Documento JSON validado por la plataforma. Los bloques disponibles y sus campos son los mismos que devuelve list_block_types.","blockTypes":[{"type":"hero","description":"Cabecera principal. Uno por página, normalmente el primero. layout 'split' muestra la imagen al lado del texto.","fields":{"id":"string [a-z0-9_-] único en la página (todos los bloques lo llevan)","eyebrow":"string ≤80 opcional (texto pequeño sobre el headline)","headline":"string 1-120 requerido","subheadline":"string ≤300 opcional","image":"{ fileId: CreativeFile.id de imagen del proyecto, alt: string } opcional","layout":"'center' | 'split' (default center)","ctas":"hasta 2 × { label ≤60, href, style: 'primary'|'secondary' }","urlCapture":"opcional: { placeholder, buttonLabel, destination ('/contact'), queryParam (default website), ariaLabel } — primer paso dominio → formulario"}},{"type":"features","description":"Rejilla de beneficios/características.","fields":{"title":"string ≤120 opcional","columns":"2 | 3 | 4 (default 3)","items":"2-12 × { icon?: uno de [check, star, zap, shield, heart, rocket, target, trending-up, clock, users, mail, phone, globe, award, thumbs-up, lightbulb, bar-chart, lock, gift, sparkles], title ≤80, description ≤300 }"}},{"type":"testimonials","description":"Testimonios de clientes.","fields":{"title":"string ≤120 opcional","items":"1-6 × { quote ≤400, author ≤80, role? ≤120, avatar?: { fileId, alt } }"}},{"type":"faq","description":"Preguntas frecuentes (se renderiza con schema.org FAQPage).","fields":{"title":"string ≤120 opcional","items":"1-12 × { question ≤200, answer ≤1000 }"}},{"type":"editorial","description":"Contenido editorial largo en Markdown/GFM seguro y semántico. Ideal para migrar páginas con texto, tablas e imágenes intercaladas.","fields":{"markdown":"Markdown/GFM string 1-50000 requerido; admite ## H2, ### H3, párrafos, negrita, cursiva, listas, enlaces, citas, tablas e imágenes ![alt](creative:<fileId>). No admite H1 ni saltos H2→H3; HTML raw queda inerte."}},{"type":"cta","description":"Llamada a la acción intermedia o final.","fields":{"eyebrow":"string ≤80 opcional","headline":"string 1-120 requerido","subtext":"string ≤300 opcional","button":"{ label ≤60, href }","note":"string ≤120 opcional (microcopy bajo el botón)","tone":"'default' | 'inverted' (inverted usa el color primario de fondo)","variant":"'standard' | 'spotlight' (spotlight usa una tarjeta editorial con composición responsive)"}},{"type":"pricing","description":"Tabla de precios/planes.","fields":{"title":"string ≤120 opcional","plans":"1-4 × { name ≤60, price ≤30 (texto, ej. '49 €'), period? ≤30, features: ≤10 strings, cta: { label, href }, highlighted?: boolean }"}},{"type":"leadForm","description":"Formulario de captación. Máximo uno por página. El envío crea un lead en el CRM del proyecto y registra una conversión con el goal indicado.","fields":{"title":"string ≤120 opcional","subtitle":"string ≤300 opcional","fields":"1-6 × { key: name|email|phone|company|website|message, label? ≤60, required: boolean } — email es obligatorio siempre","consentText":"string 10-500 requerido (texto RGPD junto al checkbox de consentimiento)","privacyPolicyPath":"path de una auxPage de privacidad; se configura junto con privacyLinkText","privacyLinkText":"subcadena exacta de consentText que se enlaza a privacyPolicyPath en una pestaña nueva","newsletterPublicId":"opcional, ID público nl_... de una newsletter de proyecto o grupo; requiere newsletterConsentText","newsletterConsentText":"opcional, consentimiento separado para recibir la newsletter; no es obligatorio para enviar el lead","newsletterNoticeVersion":"versión del aviso legal aceptado para la newsletter (default 'v1')","submitLabel":"string ≤60 (default 'Enviar')","successTitle":"string ≤80 (default '¡Solicitud enviada!') — título del card de éxito","successMessage":"string ≤300","successNextSteps":"opcional, 1-4 × string ≤150 — lista con checks de qué pasará ahora, mostrada en el card de éxito","goal":"string [a-z0-9_] (default 'form_submit') — nombre del goal de conversión"}},{"type":"footer","description":"Pie de página global y responsive. Admite enlaces simples heredados y hasta 6 columnas tituladas; legalLinks queda separado para privacidad, cookies y aviso legal. Los href internos tipo '/privacy' deben corresponder a una auxPage.","fields":{"text":"string ≤300 opcional (ej. copyright)","links":"≤8 × { label ≤60, href }","groups":"opcional, ≤6 × { title ≤60, links: 1-10 × { label ≤60, href } }; máximo 60 destinos en total","legalLinks":"≤8 × { label ≤60, href }"}},{"type":"image","description":"Imagen suelta con caption opcional.","fields":{"image":"{ fileId, alt } requerido","caption":"string ≤200 opcional","width":"'compact' (560px) | 'normal' (760px) | 'wide' (1080px)"}},{"type":"gallery","description":"Galería de imágenes en rejilla (propiedades, regiones, oficina…).","fields":{"title":"string ≤120 opcional","columns":"2 | 3 | 4 (default 3)","images":"2-12 × { fileId, alt, caption? ≤200 }"}},{"type":"stats","description":"Cifras destacadas que generan confianza (años, clientes, propiedades…).","fields":{"title":"string ≤120 opcional","items":"2-6 × { value ≤20 (ej. '15+', '98 %'), label ≤80 }"}},{"type":"chart","description":"Gráfica comparativa accesible con animación progresiva de barras.","fields":{"title":"string ≤120 opcional","description":"string ≤300 opcional","variant":"'bars' | 'progress'","items":"2-8 × { label ≤80, value 0-100, displayValue? ≤30, accent?: boolean }"}},{"type":"logos","description":"Logos de confianza: asociaciones, medios, certificaciones. En escala de grises con hover.","fields":{"title":"string ≤120 opcional (ej. 'Confían en nosotros')","items":"2-10 × { fileId, alt, href? (enlace externo opcional) }"}},{"type":"video","description":"Vídeo embebido: YouTube (youtube-nocookie), Vimeo (dnt) o un CreativeFile de vídeo del proyecto.","fields":{"title":"string ≤120 opcional","provider":"'youtube' | 'vimeo' | 'file'","videoId":"id del vídeo (youtube/vimeo)","fileId":"CreativeFile kind video (provider 'file')","poster":"{ fileId, alt } opcional (imagen de póster)"}}],"contentGuide":{"schemaVersion":1,"maxBlocks":20,"document":"{ schemaVersion: 1, meta: { title ≤70, siteName? ≤40 (marca pública corta, independiente de Project.name), description? ≤160, ogImageFileId?, faviconFileId?, locale ('es', 'nl-BE'…), robots: 'index'|'noindex', alternates?, xDefaultSlug?, languageSelector?, structuredData?, cookieConsent?, nav?, quickContact? }, themeOverrides?: <themeSchema parcial>, sharedSections?: { key: block|blocks }, blocks: [1..20 bloques], sitePages?: [≤8 páginas comerciales], auxPages?: [≤5 páginas auxiliares] }","cookieConsent":{"description":"OBLIGATORIO POR DEFECTO para todas las landings europeas, nuevas y existentes: aunque meta.cookieConsent se omita, el renderer muestra el banner y bloquea lp_vid, pageviews, conversiones y futuros píxeles hasta consentir su categoría. El agente NO debe desactivarlo salvo instrucción explícita del usuario. Config opcional: { enabled (default true), policyVersion (default '1'; cambiarla vuelve a solicitar consentimiento), cookiePolicyPath (default 'cookies'), privacyPolicyPath (default 'privacy'), text?: overrides i18n }. Solo meta.cookieConsent.enabled:false lo desactiva y la validación emitirá un warning legal.","categories":"necessary siempre activa; analytics controla lp_vid y beacons first-party; marketing controla Google Consent Mode v2 y futuros píxeles Google/Meta.","example":"{ cookieConsent: { policyVersion: \"2026-07\", cookiePolicyPath: \"cookies\", privacyPolicyPath: \"privacy\" } }"},"favicon":"meta.faviconFileId (CreativeFile de imagen del proyecto, idealmente cuadrado ~512×512) se emite como <link rel='icon'> en TODAS las páginas del sitio (home, blog, artículos). Sube o genera el icono con /api/creatives/upload o /api/creatives/generate.","structuredData":{"description":"JSON-LD de la identidad editorial y la entidad dueña del sitio (SEO/AEO). meta.structuredData = { type: 'Organization'|'LocalBusiness'|'WebSite', name ≤120, url?, areaServed?: [códigos de país ISO-2, ≤10], telephone?, email?, address?: { streetAddress, addressLocality, postalCode?, addressRegion?, addressCountry? (ISO-2) }, priceRange? (solo LocalBusiness, ej. 'desde 34,99 €/mes'), sameAs?: [urls de perfiles sociales, ≤10] }. No hay país por defecto: Service usa areaServed explícito, addressCountry o la región inequívoca de meta.locale (p.ej. en-US), y lo omite si no puede determinarlo. Article publisher usa esta organización o meta.siteName, el dominio canónico activo y el logo del tema. En previews sin canonical público no se inventan URLs.","example":"{ type: \"LocalBusiness\", name: \"Domiciliación de Empresas Alicante\", areaServed: [\"ES\"], telephone: \"+34 600 000 000\", priceRange: \"desde 34,99 €/mes\", address: { streetAddress: \"Calle Mayor 1\", addressLocality: \"Alicante\", postalCode: \"03001\", addressCountry: \"ES\" } }"},"hrefFormats":"http(s)://..., /ruta (sitePage o auxPage, ej. '/contact' o '/privacy'), /blog, #id-de-bloque (ancla interna en la página), mailto:..., tel:...","nav":{"description":"Cabecera global jerárquica y accesible, compartida por home, sitePages, auxPages y blog. meta.nav admite hasta 12 elementos de primer nivel: enlaces { label ≤60, href, cta? } o grupos { label ≤40, children: 1-10 enlaces }. Máximo 40 destinos. Los grupos se muestran como dropdowns de escritorio y submenús equivalentes en móvil, con foco, Escape y estado activo. La forma plana anterior sigue siendo válida. Para secciones de la home usa '/#precio', no '#precio'; enlaza blog, tags, RSS y páginas legales con sus rutas.","example":"{ nav: [{ label: \"Inicio\", href: \"/\" }, { label: \"Soluciones\", children: [{ label: \"Servicios\", href: \"/#servicios\" }, { label: \"Precios\", href: \"/pricing\" }] }, { label: \"Recursos\", children: [{ label: \"Blog\", href: \"/blog\" }, { label: \"RSS\", href: \"/blog/feed.xml\" }] }, { label: \"Contacto\", href: \"/#form\", cta: true }] }"},"quickContact":{"description":"Accesos rápidos de contacto como botones-icono redondos a la derecha de la cabecera (también en el blog). meta.quickContact = [{ href, label? }] (≤4). El icono se deriva automáticamente del href: tel:→teléfono, wa.me/whatsapp→WhatsApp, mailto:→email. Úsalo para teléfono y WhatsApp de acceso directo. NOTA: los enlaces del footer (block footer.links) también muestran icono automático según su href (tel/WhatsApp/mailto/blog), sin configuración extra.","example":"{ quickContact: [{ href: \"tel:+34600000000\", label: \"Llamar\" }, { href: \"https://wa.me/34600000000\", label: \"WhatsApp\" }] }"},"images":"Sube imágenes con POST /api/creatives/upload (multipart) o genera con POST /api/creatives/generate (IA, gpt-image-2) y usa el fileId devuelto. Solo ficheros del mismo proyecto. En editorial usa ![texto alt](creative:<fileId>); el renderer genera srcset responsive. Fondos de hero/cta: backgroundImage { fileId, overlay?: { color hex, opacity 0-0.9 } }.","multiLanguage":{"description":"Sitio multi-idioma servido en SUBDIRECTORIOS de un único host (mejor para SEO/GEO: consolida la autoridad de dominio). La landing PRINCIPAL (la del host apex) declara meta.locale (idioma principal, en la raíz /) y meta.alternates = [{ locale, slug }] con los slugs de las landings traducidas del MISMO proyecto. Cada idioma secundario se sirve bajo su prefijo de path (/en/, /fr/…) del mismo host; las hermanas NO necesitan dominio propio (basta con que estén publicadas). Emite hreflang recíprocos con URLs de subdirectorio + x-default → raíz. languageSelector: true muestra un DESPLEGABLE de idioma en la cabecera (nombre nativo de cada idioma), presente también en el blog. Solo se enlazan las hermanas publicadas.","example":"{ locale: \"es\", alternates: [{ locale: \"en\", slug: \"company-registration-alicante\" }, { locale: \"fr\", slug: \"domiciliation-entreprises-alicante\" }], xDefaultSlug: \"domiciliacion-de-empresas\", languageSelector: true }"},"auxPages":{"description":"Páginas auxiliares servidas en el mismo host (issue #392): privacidad, aviso legal, cookies. En un sitio multi-idioma se sirven bajo el prefijo del idioma (/en/privacy). Cada una: { path ('privacy'), title, robots (default noindex), sections: [{ heading?, text ≤5000 (párrafos separados por línea en blanco) }] }. Heredan header global y footer raíz. Enlázalas desde footer.legalLinks con href '/privacy'.","gdprTemplate":"Secciones recomendadas para la política de privacidad RGPD: 1) Responsable del tratamiento (nombre, NIF, domicilio, email); 2) Finalidad (gestionar la solicitud del formulario y el envío de información comercial); 3) Legitimación (consentimiento del interesado); 4) Destinatarios (no se ceden datos salvo obligación legal; encargados de tratamiento con quien se haya contratado hosting/CRM); 5) Derechos (acceso, rectificación, supresión, oposición, limitación y portabilidad, ante el responsable o la AEPD); 6) Conservación (mientras dure la relación o hasta la retirada del consentimiento). Personaliza con los datos reales del proyecto ANTES de publicar."},"sharedSections":{"description":"Secciones compartidas reutilizables: define sharedSections: { 'footer-legal': block|blocks } en la home o usa site_shared_section.create/update/archive, y colócalas en la home o cualquier SitePage independiente con { id, type:'include', ref:'footer-legal' }. El id del include es un destino de ancla válido (por ejemplo href:'#contacto') y los bloques internos se acotan como includeId-blockId. Las SitePages heredan la versión latest/published correspondiente de la home. El renderer expande referencias anidadas y rechaza ciclos e IDs duplicados."},"sitePages":{"description":"Páginas comerciales completas bajo el mismo dominio y tema. Cada una: { path, title ≤70, description? ≤160, robots (default index), blocks: [1..20] }. Se sirven en /<path>, tienen canonical propio y aparecen en sitemap. Úsalas para pricing, technology, about-us y contact; reserva auxPages para textos legales.","example":"{ path: \"contact\", title: \"Contacto · Mi empresa\", description: \"Habla con el equipo\", blocks: [{ id: \"contact-hero\", type: \"hero\", headline: \"Hablemos\" }, { id: \"contact-form\", type: \"leadForm\", fields: [{ key: \"website\" }, { key: \"name\" }, { key: \"email\", required: true }], consentText: \"Acepto la política de privacidad y el tratamiento de mis datos.\", privacyPolicyPath: \"privacy\", privacyLinkText: \"política de privacidad\" }] }"},"theme":{"description":"Design tokens del proyecto (landing_theme.update, requiere aprobación). themeOverrides por página acepta los mismos campos.","colors":"primary, primaryContrast, background, surface, text, muted, accent (hex)","fonts":"heading/body: uno de [system, inter, georgia, mono, serif-display, geometric, humanist]","radius":"'none' | 'sm' | 'md' | 'full'","logoFileId":"CreativeFile.id opcional. Si está presente (en el tema del proyecto o en themeOverrides de la página), el renderer muestra un header ligero con el logo enlazado a la raíz (y el selector de idioma a la derecha si languageSelector: true) y repite el logo en el footer junto al copyright."}}}}}}},"update_draft":{"data":{"type":"array","required":true,"items":{"type":"object","properties":{"pageId":{"type":"string","description":"Requerido para update_draft."},"landingPageId":{"type":"string","description":"Requerido para create."},"path":{"type":"string","description":"Requerido para create."},"name":{"type":"string","description":"Requerido para create."},"kind":{"type":"string","description":"Tipo editorial de la página."},"content":{"type":"object","required":true,"description":"Documento JSON validado por la plataforma. Los bloques disponibles y sus campos son los mismos que devuelve list_block_types.","blockTypes":[{"type":"hero","description":"Cabecera principal. Uno por página, normalmente el primero. layout 'split' muestra la imagen al lado del texto.","fields":{"id":"string [a-z0-9_-] único en la página (todos los bloques lo llevan)","eyebrow":"string ≤80 opcional (texto pequeño sobre el headline)","headline":"string 1-120 requerido","subheadline":"string ≤300 opcional","image":"{ fileId: CreativeFile.id de imagen del proyecto, alt: string } opcional","layout":"'center' | 'split' (default center)","ctas":"hasta 2 × { label ≤60, href, style: 'primary'|'secondary' }","urlCapture":"opcional: { placeholder, buttonLabel, destination ('/contact'), queryParam (default website), ariaLabel } — primer paso dominio → formulario"}},{"type":"features","description":"Rejilla de beneficios/características.","fields":{"title":"string ≤120 opcional","columns":"2 | 3 | 4 (default 3)","items":"2-12 × { icon?: uno de [check, star, zap, shield, heart, rocket, target, trending-up, clock, users, mail, phone, globe, award, thumbs-up, lightbulb, bar-chart, lock, gift, sparkles], title ≤80, description ≤300 }"}},{"type":"testimonials","description":"Testimonios de clientes.","fields":{"title":"string ≤120 opcional","items":"1-6 × { quote ≤400, author ≤80, role? ≤120, avatar?: { fileId, alt } }"}},{"type":"faq","description":"Preguntas frecuentes (se renderiza con schema.org FAQPage).","fields":{"title":"string ≤120 opcional","items":"1-12 × { question ≤200, answer ≤1000 }"}},{"type":"editorial","description":"Contenido editorial largo en Markdown/GFM seguro y semántico. Ideal para migrar páginas con texto, tablas e imágenes intercaladas.","fields":{"markdown":"Markdown/GFM string 1-50000 requerido; admite ## H2, ### H3, párrafos, negrita, cursiva, listas, enlaces, citas, tablas e imágenes ![alt](creative:<fileId>). No admite H1 ni saltos H2→H3; HTML raw queda inerte."}},{"type":"cta","description":"Llamada a la acción intermedia o final.","fields":{"eyebrow":"string ≤80 opcional","headline":"string 1-120 requerido","subtext":"string ≤300 opcional","button":"{ label ≤60, href }","note":"string ≤120 opcional (microcopy bajo el botón)","tone":"'default' | 'inverted' (inverted usa el color primario de fondo)","variant":"'standard' | 'spotlight' (spotlight usa una tarjeta editorial con composición responsive)"}},{"type":"pricing","description":"Tabla de precios/planes.","fields":{"title":"string ≤120 opcional","plans":"1-4 × { name ≤60, price ≤30 (texto, ej. '49 €'), period? ≤30, features: ≤10 strings, cta: { label, href }, highlighted?: boolean }"}},{"type":"leadForm","description":"Formulario de captación. Máximo uno por página. El envío crea un lead en el CRM del proyecto y registra una conversión con el goal indicado.","fields":{"title":"string ≤120 opcional","subtitle":"string ≤300 opcional","fields":"1-6 × { key: name|email|phone|company|website|message, label? ≤60, required: boolean } — email es obligatorio siempre","consentText":"string 10-500 requerido (texto RGPD junto al checkbox de consentimiento)","privacyPolicyPath":"path de una auxPage de privacidad; se configura junto con privacyLinkText","privacyLinkText":"subcadena exacta de consentText que se enlaza a privacyPolicyPath en una pestaña nueva","newsletterPublicId":"opcional, ID público nl_... de una newsletter de proyecto o grupo; requiere newsletterConsentText","newsletterConsentText":"opcional, consentimiento separado para recibir la newsletter; no es obligatorio para enviar el lead","newsletterNoticeVersion":"versión del aviso legal aceptado para la newsletter (default 'v1')","submitLabel":"string ≤60 (default 'Enviar')","successTitle":"string ≤80 (default '¡Solicitud enviada!') — título del card de éxito","successMessage":"string ≤300","successNextSteps":"opcional, 1-4 × string ≤150 — lista con checks de qué pasará ahora, mostrada en el card de éxito","goal":"string [a-z0-9_] (default 'form_submit') — nombre del goal de conversión"}},{"type":"footer","description":"Pie de página global y responsive. Admite enlaces simples heredados y hasta 6 columnas tituladas; legalLinks queda separado para privacidad, cookies y aviso legal. Los href internos tipo '/privacy' deben corresponder a una auxPage.","fields":{"text":"string ≤300 opcional (ej. copyright)","links":"≤8 × { label ≤60, href }","groups":"opcional, ≤6 × { title ≤60, links: 1-10 × { label ≤60, href } }; máximo 60 destinos en total","legalLinks":"≤8 × { label ≤60, href }"}},{"type":"image","description":"Imagen suelta con caption opcional.","fields":{"image":"{ fileId, alt } requerido","caption":"string ≤200 opcional","width":"'compact' (560px) | 'normal' (760px) | 'wide' (1080px)"}},{"type":"gallery","description":"Galería de imágenes en rejilla (propiedades, regiones, oficina…).","fields":{"title":"string ≤120 opcional","columns":"2 | 3 | 4 (default 3)","images":"2-12 × { fileId, alt, caption? ≤200 }"}},{"type":"stats","description":"Cifras destacadas que generan confianza (años, clientes, propiedades…).","fields":{"title":"string ≤120 opcional","items":"2-6 × { value ≤20 (ej. '15+', '98 %'), label ≤80 }"}},{"type":"chart","description":"Gráfica comparativa accesible con animación progresiva de barras.","fields":{"title":"string ≤120 opcional","description":"string ≤300 opcional","variant":"'bars' | 'progress'","items":"2-8 × { label ≤80, value 0-100, displayValue? ≤30, accent?: boolean }"}},{"type":"logos","description":"Logos de confianza: asociaciones, medios, certificaciones. En escala de grises con hover.","fields":{"title":"string ≤120 opcional (ej. 'Confían en nosotros')","items":"2-10 × { fileId, alt, href? (enlace externo opcional) }"}},{"type":"video","description":"Vídeo embebido: YouTube (youtube-nocookie), Vimeo (dnt) o un CreativeFile de vídeo del proyecto.","fields":{"title":"string ≤120 opcional","provider":"'youtube' | 'vimeo' | 'file'","videoId":"id del vídeo (youtube/vimeo)","fileId":"CreativeFile kind video (provider 'file')","poster":"{ fileId, alt } opcional (imagen de póster)"}}],"contentGuide":{"schemaVersion":1,"maxBlocks":20,"document":"{ schemaVersion: 1, meta: { title ≤70, siteName? ≤40 (marca pública corta, independiente de Project.name), description? ≤160, ogImageFileId?, faviconFileId?, locale ('es', 'nl-BE'…), robots: 'index'|'noindex', alternates?, xDefaultSlug?, languageSelector?, structuredData?, cookieConsent?, nav?, quickContact? }, themeOverrides?: <themeSchema parcial>, sharedSections?: { key: block|blocks }, blocks: [1..20 bloques], sitePages?: [≤8 páginas comerciales], auxPages?: [≤5 páginas auxiliares] }","cookieConsent":{"description":"OBLIGATORIO POR DEFECTO para todas las landings europeas, nuevas y existentes: aunque meta.cookieConsent se omita, el renderer muestra el banner y bloquea lp_vid, pageviews, conversiones y futuros píxeles hasta consentir su categoría. El agente NO debe desactivarlo salvo instrucción explícita del usuario. Config opcional: { enabled (default true), policyVersion (default '1'; cambiarla vuelve a solicitar consentimiento), cookiePolicyPath (default 'cookies'), privacyPolicyPath (default 'privacy'), text?: overrides i18n }. Solo meta.cookieConsent.enabled:false lo desactiva y la validación emitirá un warning legal.","categories":"necessary siempre activa; analytics controla lp_vid y beacons first-party; marketing controla Google Consent Mode v2 y futuros píxeles Google/Meta.","example":"{ cookieConsent: { policyVersion: \"2026-07\", cookiePolicyPath: \"cookies\", privacyPolicyPath: \"privacy\" } }"},"favicon":"meta.faviconFileId (CreativeFile de imagen del proyecto, idealmente cuadrado ~512×512) se emite como <link rel='icon'> en TODAS las páginas del sitio (home, blog, artículos). Sube o genera el icono con /api/creatives/upload o /api/creatives/generate.","structuredData":{"description":"JSON-LD de la identidad editorial y la entidad dueña del sitio (SEO/AEO). meta.structuredData = { type: 'Organization'|'LocalBusiness'|'WebSite', name ≤120, url?, areaServed?: [códigos de país ISO-2, ≤10], telephone?, email?, address?: { streetAddress, addressLocality, postalCode?, addressRegion?, addressCountry? (ISO-2) }, priceRange? (solo LocalBusiness, ej. 'desde 34,99 €/mes'), sameAs?: [urls de perfiles sociales, ≤10] }. No hay país por defecto: Service usa areaServed explícito, addressCountry o la región inequívoca de meta.locale (p.ej. en-US), y lo omite si no puede determinarlo. Article publisher usa esta organización o meta.siteName, el dominio canónico activo y el logo del tema. En previews sin canonical público no se inventan URLs.","example":"{ type: \"LocalBusiness\", name: \"Domiciliación de Empresas Alicante\", areaServed: [\"ES\"], telephone: \"+34 600 000 000\", priceRange: \"desde 34,99 €/mes\", address: { streetAddress: \"Calle Mayor 1\", addressLocality: \"Alicante\", postalCode: \"03001\", addressCountry: \"ES\" } }"},"hrefFormats":"http(s)://..., /ruta (sitePage o auxPage, ej. '/contact' o '/privacy'), /blog, #id-de-bloque (ancla interna en la página), mailto:..., tel:...","nav":{"description":"Cabecera global jerárquica y accesible, compartida por home, sitePages, auxPages y blog. meta.nav admite hasta 12 elementos de primer nivel: enlaces { label ≤60, href, cta? } o grupos { label ≤40, children: 1-10 enlaces }. Máximo 40 destinos. Los grupos se muestran como dropdowns de escritorio y submenús equivalentes en móvil, con foco, Escape y estado activo. La forma plana anterior sigue siendo válida. Para secciones de la home usa '/#precio', no '#precio'; enlaza blog, tags, RSS y páginas legales con sus rutas.","example":"{ nav: [{ label: \"Inicio\", href: \"/\" }, { label: \"Soluciones\", children: [{ label: \"Servicios\", href: \"/#servicios\" }, { label: \"Precios\", href: \"/pricing\" }] }, { label: \"Recursos\", children: [{ label: \"Blog\", href: \"/blog\" }, { label: \"RSS\", href: \"/blog/feed.xml\" }] }, { label: \"Contacto\", href: \"/#form\", cta: true }] }"},"quickContact":{"description":"Accesos rápidos de contacto como botones-icono redondos a la derecha de la cabecera (también en el blog). meta.quickContact = [{ href, label? }] (≤4). El icono se deriva automáticamente del href: tel:→teléfono, wa.me/whatsapp→WhatsApp, mailto:→email. Úsalo para teléfono y WhatsApp de acceso directo. NOTA: los enlaces del footer (block footer.links) también muestran icono automático según su href (tel/WhatsApp/mailto/blog), sin configuración extra.","example":"{ quickContact: [{ href: \"tel:+34600000000\", label: \"Llamar\" }, { href: \"https://wa.me/34600000000\", label: \"WhatsApp\" }] }"},"images":"Sube imágenes con POST /api/creatives/upload (multipart) o genera con POST /api/creatives/generate (IA, gpt-image-2) y usa el fileId devuelto. Solo ficheros del mismo proyecto. En editorial usa ![texto alt](creative:<fileId>); el renderer genera srcset responsive. Fondos de hero/cta: backgroundImage { fileId, overlay?: { color hex, opacity 0-0.9 } }.","multiLanguage":{"description":"Sitio multi-idioma servido en SUBDIRECTORIOS de un único host (mejor para SEO/GEO: consolida la autoridad de dominio). La landing PRINCIPAL (la del host apex) declara meta.locale (idioma principal, en la raíz /) y meta.alternates = [{ locale, slug }] con los slugs de las landings traducidas del MISMO proyecto. Cada idioma secundario se sirve bajo su prefijo de path (/en/, /fr/…) del mismo host; las hermanas NO necesitan dominio propio (basta con que estén publicadas). Emite hreflang recíprocos con URLs de subdirectorio + x-default → raíz. languageSelector: true muestra un DESPLEGABLE de idioma en la cabecera (nombre nativo de cada idioma), presente también en el blog. Solo se enlazan las hermanas publicadas.","example":"{ locale: \"es\", alternates: [{ locale: \"en\", slug: \"company-registration-alicante\" }, { locale: \"fr\", slug: \"domiciliation-entreprises-alicante\" }], xDefaultSlug: \"domiciliacion-de-empresas\", languageSelector: true }"},"auxPages":{"description":"Páginas auxiliares servidas en el mismo host (issue #392): privacidad, aviso legal, cookies. En un sitio multi-idioma se sirven bajo el prefijo del idioma (/en/privacy). Cada una: { path ('privacy'), title, robots (default noindex), sections: [{ heading?, text ≤5000 (párrafos separados por línea en blanco) }] }. Heredan header global y footer raíz. Enlázalas desde footer.legalLinks con href '/privacy'.","gdprTemplate":"Secciones recomendadas para la política de privacidad RGPD: 1) Responsable del tratamiento (nombre, NIF, domicilio, email); 2) Finalidad (gestionar la solicitud del formulario y el envío de información comercial); 3) Legitimación (consentimiento del interesado); 4) Destinatarios (no se ceden datos salvo obligación legal; encargados de tratamiento con quien se haya contratado hosting/CRM); 5) Derechos (acceso, rectificación, supresión, oposición, limitación y portabilidad, ante el responsable o la AEPD); 6) Conservación (mientras dure la relación o hasta la retirada del consentimiento). Personaliza con los datos reales del proyecto ANTES de publicar."},"sharedSections":{"description":"Secciones compartidas reutilizables: define sharedSections: { 'footer-legal': block|blocks } en la home o usa site_shared_section.create/update/archive, y colócalas en la home o cualquier SitePage independiente con { id, type:'include', ref:'footer-legal' }. El id del include es un destino de ancla válido (por ejemplo href:'#contacto') y los bloques internos se acotan como includeId-blockId. Las SitePages heredan la versión latest/published correspondiente de la home. El renderer expande referencias anidadas y rechaza ciclos e IDs duplicados."},"sitePages":{"description":"Páginas comerciales completas bajo el mismo dominio y tema. Cada una: { path, title ≤70, description? ≤160, robots (default index), blocks: [1..20] }. Se sirven en /<path>, tienen canonical propio y aparecen en sitemap. Úsalas para pricing, technology, about-us y contact; reserva auxPages para textos legales.","example":"{ path: \"contact\", title: \"Contacto · Mi empresa\", description: \"Habla con el equipo\", blocks: [{ id: \"contact-hero\", type: \"hero\", headline: \"Hablemos\" }, { id: \"contact-form\", type: \"leadForm\", fields: [{ key: \"website\" }, { key: \"name\" }, { key: \"email\", required: true }], consentText: \"Acepto la política de privacidad y el tratamiento de mis datos.\", privacyPolicyPath: \"privacy\", privacyLinkText: \"política de privacidad\" }] }"},"theme":{"description":"Design tokens del proyecto (landing_theme.update, requiere aprobación). themeOverrides por página acepta los mismos campos.","colors":"primary, primaryContrast, background, surface, text, muted, accent (hex)","fonts":"heading/body: uno de [system, inter, georgia, mono, serif-display, geometric, humanist]","radius":"'none' | 'sm' | 'md' | 'full'","logoFileId":"CreativeFile.id opcional. Si está presente (en el tema del proyecto o en themeOverrides de la página), el renderer muestra un header ligero con el logo enlazado a la raíz (y el selector de idioma a la derecha si languageSelector: true) y repite el logo en el footer junto al copyright."}}}}}}}},"x-mcp":{"channel":"landing_pages","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"site_shared_section":{"operations":["create","update","archive"],"description":"Site-level reusable sections inherited by home and independent SitePages. Writes create a new immutable home draft version; publish landing_page to promote the change and invalidate all public site-page caches.","operationParams":{"create":{"landingPageId":{"type":"string","required":true},"key":{"type":"string","required":true},"section":{"type":"object","required":true}},"update":{"landingPageId":{"type":"string","required":true},"key":{"type":"string","required":true},"section":{"type":"object","required":true},"baseVersionNumber":{"type":"number","optional":true}},"archive":{"landingPageId":{"type":"string","required":true},"key":{"type":"string","required":true},"baseVersionNumber":{"type":"number","optional":true}}},"x-mcp":{"channel":"landing_pages","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"site_redirect":{"operations":["create","update","remove"],"description":"Explicit public redirects for removed URLs and migrations. Sources and targets accept normalized nested internal paths plus final .xml/.txt files. Schemes, hosts, query/fragment input, escapes, backslashes, traversal, controls, reserved-route collisions, chains and cycles are rejected. Destinations must resolve inside the same published site, including native blog routes. create is an idempotent 1-200 item manifest; validate_only is its dry run and multi-item manifests require permanent 308 redirects. Safe request queries are preserved at runtime. All writes require human approval. Creating from an issue accepts issueId and marks it redirected after approval.","operationParams":{"create":{"data":{"type":"array","required":true,"minItems":1,"maxItems":200,"description":"Idempotent redirect manifest. A repeated identical entry returns unchanged. Multi-item manifests must be permanent and are fully preflighted before any write.","items":{"type":"object","required":["pageId","fromPath","toPath"],"properties":{"pageId":{"type":"string","description":"LandingPage/Sites v2 id."},"fromPath":{"type":"string","description":"Internal source, including nested paths or final .xml/.txt files. Root, schemes, hosts, query, fragments, percent escapes, backslashes, traversal, controls and reserved routes are rejected."},"toPath":{"type":"string","description":"Published internal destination: /, a published SitePage, /blog, /blog/<slug>, /blog/tag/<tag>, /blog/feed.xml, /robots.txt or /sitemap.xml."},"permanent":{"type":"boolean","default":true,"description":"308 when true. Multi-item migration manifests require true."},"issueId":{"type":"string","description":"Optional matching 404 SiteIssue id."}}}},"validate_only":{"type":"boolean","default":false,"description":"Dry run. Returns normalized items and create/unchanged actions without persisting."}},"update":{"data":{"type":"array","required":true,"items":{"type":"object","required":["redirectId"],"properties":{"redirectId":{"type":"string"},"fromPath":{"type":"string","description":"Optional nested internal source."},"toPath":{"type":"string","description":"Optional published internal target."},"permanent":{"type":"boolean"}}}}},"remove":{"data":{"type":"array","required":true,"items":{"type":"object","properties":{"redirectId":{"type":"string"},"pageId":{"type":"string"},"fromPath":{"type":"string"}}}}}},"x-mcp":{"channel":"landing_pages","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},"site_issue":{"operations":["ignore","resolve","reopen"],"description":"Operational issue lifecycle. ignore and resolve require human approval; reopen is automatic. Keep isolated 404s and scanner noise under observation. Prioritize broken internal links, repeated human requests and search crawlers.","x-mcp":{"channel":"landing_pages","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}}},"x-examples":[{"description":"Dry-run an idempotent migration redirect manifest","body":{"resource":"site_redirect","operation":"create","validate_only":true,"data":[{"pageId":"PAGE_ID","fromPath":"/article-old/","toPath":"/blog/article-old"},{"pageId":"PAGE_ID","fromPath":"/category/white-label/","toPath":"/blog/tag/white-label"},{"pageId":"PAGE_ID","fromPath":"/feed/","toPath":"/blog/feed.xml"}]}},{"description":"Validate a new landing draft before creating it","body":{"resource":"landing_page","operation":"create","validate_only":true,"data":[{"name":"Oferta Verano","slug":"oferta-verano","content":{"schemaVersion":1,"meta":{"title":"Oferta de verano"},"blocks":[{"id":"hero","type":"hero","headline":"Ahorra un 20% este verano","ctas":[{"label":"Quiero mi descuento","href":"#form","style":"primary"}]},{"id":"form","type":"leadForm","fields":[{"key":"email","required":true}],"consentText":"Acepto la política de privacidad y el tratamiento de mis datos.","privacyPolicyPath":"privacy","privacyLinkText":"política de privacidad"},{"id":"footer","type":"footer","legalLinks":[{"label":"Privacidad","href":"/privacy"}]}],"auxPages":[{"path":"privacy","title":"Política de privacidad","sections":[{"text":"Contenido legal."}]}]}}]}},{"description":"Publish the latest draft (queues for human approval with preview)","body":{"resource":"landing_page","operation":"publish","data":[{"pageId":"PAGE_ID"}],"agent_note":"Landing revisada con preview_url; lista para publicar en su subdominio."}}]}},"/api/blog/agent-query":{"post":{"summary":"Native blog data","description":"Read the native multi-host blog: Markdown articles with immutable versions, optional visible FAQ with FAQPage JSON-LD, tags and signed previews. Each blog hangs off a landing page and is served at /blog on the landing's host.","tags":["Blog"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"list_posts","description":"List blog posts with status, hostname and version numbers. Title and tags come from the published version for published posts and from the latest version for drafts.","params":{"status":{"type":"string","enum":["draft","published","archived"],"optional":true},"tag":{"type":"string","optional":true},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"blog","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_post","description":"Full detail of one post: latest version (meta + bodyMarkdown), published version, public URL.","params":{"id":{"type":"string","optional":true},"slug":{"type":"string","optional":true}},"x-mcp":{"channel":"blog","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_versions","description":"Immutable version history of a post.","params":{"postId":{"type":"string","required":true},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"blog","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_meta_schema","description":"Article format guide: meta fields and limits, visible FAQ + FAQPage parity, Markdown rules (GFM, no embedded HTML, creative:<fileId> images, allowed link schemes), publishing flow and SEO output. Call this before writing.","params":{},"x-mcp":{"channel":"blog","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"preview_url","description":"Signed preview URL (7 days) of any version, including drafts. Review it before requesting publish.","params":{"postId":{"type":"string","required":true},"versionId":{"type":"string","optional":true}},"x-mcp":{"channel":"blog","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_tags","description":"Tags with published posts in a landing's blog, with counts.","params":{"pageId":{"type":"string","required":true}},"x-mcp":{"channel":"blog","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pending_mutations","description":"List blog mutations of this project.","params":{"status":{"type":"string","optional":true},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"blog","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_mutation_status","description":"Check one blog mutation by id.","params":{"mutationId":{"type":"string","required":true}},"x-mcp":{"channel":"blog","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}],"x-content-guide":{"schemaVersion":1,"document":"Cada artículo = { meta, bodyMarkdown }. meta: { title ≤180, slug ([a-z0-9-] ≤80; 'tag'/'feed'/'page' reservados), excerpt? ≤500 (recomendado: listados/SEO/feed), coverImageFileId? (opcional mientras sea borrador, obligatorio para publish/rollback; portada visible en detalle y listado), ogImageFileId? (default: cover), seo?: { title ≤70, description ≤180 }, locale (default 'es'), robots 'index'|'noindex', tags: [slug-case, ≤10], publishedAt? (ISO), authorName? ≤120, faq?: [{ question, answer }] }.","bodyMarkdown":{"format":"Markdown con GFM (tablas, listas de tareas, tachado). El HTML embebido NO se renderiza (queda inerte). No empieces con H1 (#): el título lo pone la plantilla desde meta.title; estructura con H2 (##) y H3 (###).","images":"Imágenes del proyecto con el esquema creative: ![texto alternativo](creative:<fileId>). Sube ficheros con POST /api/creatives/upload o genera con POST /api/creatives/generate (IA, gpt-image-2) y usa el fileId devuelto. Las URLs de imagen externas se eliminan en el render.","links":"Enlaces permitidos: https://, mailto:, tel:, anclas (#seccion) y rutas internas del blog (/blog/otro-slug). Todo lo demás se elimina.","maxBytes":204800},"faq":{"format":"meta.faq es opcional y admite de 1 a 20 elementos. Cada question es única, no vacía y tiene hasta 200 caracteres; cada answer es Markdown no vacío de hasta 4000 caracteres.","safety":"Las respuestas visibles solo admiten párrafos, énfasis, enlaces, listas y código. Se eliminan HTML, imágenes y URLs no permitidas; para enlaces aplica la misma lista segura que bodyMarkdown.","seo":"Si faq es válida, las mismas preguntas y respuestas se muestran al final del artículo y se emite JSON-LD FAQPage equivalente. Si falta o no es válida, no se emite FAQPage.","example":[{"question":"¿Cuánto tarda el servicio?","answer":"El plazo habitual es de **3 a 5 días laborables**. Consulta [el proceso](/blog/proceso)."},{"question":"¿Incluye soporte?","answer":"Sí, incluye soporte por correo durante 30 días."}]},"publishing":"El blog se sirve en el host de la landing del proyecto: /blog, /blog/<slug>, /blog/tag/<tag> y /blog/feed.xml. Solo hay blog si la landing está publicada. create/update_draft son inmediatos (borradores invisibles); publish/rollback/archive requieren aprobación humana. Adjunta agent_note con el motivo y revisa la preview con preview_url antes de pedir publish.","seo":"Cada artículo emite metadata completa (canonical en el dominio primario, OG type article) y JSON-LD Article + BreadcrumbList, más FAQPage cuando hay FAQ visible válida. Los tags generan páginas /blog/tag/<tag> y entran en el sitemap del host."}}},"/api/blog/agent-mutate":{"post":{"summary":"Native blog mutations","description":"Create and iterate blog articles as Markdown + validated meta JSON, including optional visible FAQ with FAQPage parity. Drafts are auto-executed; publish, rollback and archive queue for human approval with a rendered signed preview attached.","tags":["Blog"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["resource","operation","data"],"properties":{"resource":{"type":"string","enum":["blog_post"]},"operation":{"type":"string","description":"blog_post: create (post + version 1 on the landing's blog, stays draft), update_draft (new immutable version; optional baseVersionNumber for conflict detection), publish (versionId optional, defaults to latest; requires a valid meta.coverImageFileId and materializes the published snapshot/public URL), rollback (publishes an older versionId, also requiring a valid cover), archive (removes from listings/feed and frees the published slug)."},"data":{"type":"array","description":"Array of payloads. blog_post.create: { pageId, meta, bodyMarkdown }. update_draft: { postId, meta, bodyMarkdown, baseVersionNumber? }. publish/rollback: { postId, versionId? }. archive: { postId }. meta and bodyMarkdown must follow the guide from get_meta_schema (optional meta.faq included; images via creative:<fileId>; embedded HTML is inert)."},"agent_note":{"type":"string","description":"Recommended explanation for the human approver."},"validate_only":{"type":"boolean","default":false,"description":"Validate meta/bodyMarkdown (including image ownership) without persisting."}}}}}},"responses":{"200":{"description":"Executed immediately or queued for approval","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-resources":{"blog_post":{"operations":["create","update_draft","publish","rollback","archive"],"description":"Native blog article lifecycle. create/update_draft are auto (drafts are invisible to visitors); publish/rollback/archive are approval_required with a signed preview attached for the reviewer.","x-mcp":{"channel":"blog","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}}},"x-content-guide":{"schemaVersion":1,"document":"Cada artículo = { meta, bodyMarkdown }. meta: { title ≤180, slug ([a-z0-9-] ≤80; 'tag'/'feed'/'page' reservados), excerpt? ≤500 (recomendado: listados/SEO/feed), coverImageFileId? (opcional mientras sea borrador, obligatorio para publish/rollback; portada visible en detalle y listado), ogImageFileId? (default: cover), seo?: { title ≤70, description ≤180 }, locale (default 'es'), robots 'index'|'noindex', tags: [slug-case, ≤10], publishedAt? (ISO), authorName? ≤120, faq?: [{ question, answer }] }.","bodyMarkdown":{"format":"Markdown con GFM (tablas, listas de tareas, tachado). El HTML embebido NO se renderiza (queda inerte). No empieces con H1 (#): el título lo pone la plantilla desde meta.title; estructura con H2 (##) y H3 (###).","images":"Imágenes del proyecto con el esquema creative: ![texto alternativo](creative:<fileId>). Sube ficheros con POST /api/creatives/upload o genera con POST /api/creatives/generate (IA, gpt-image-2) y usa el fileId devuelto. Las URLs de imagen externas se eliminan en el render.","links":"Enlaces permitidos: https://, mailto:, tel:, anclas (#seccion) y rutas internas del blog (/blog/otro-slug). Todo lo demás se elimina.","maxBytes":204800},"faq":{"format":"meta.faq es opcional y admite de 1 a 20 elementos. Cada question es única, no vacía y tiene hasta 200 caracteres; cada answer es Markdown no vacío de hasta 4000 caracteres.","safety":"Las respuestas visibles solo admiten párrafos, énfasis, enlaces, listas y código. Se eliminan HTML, imágenes y URLs no permitidas; para enlaces aplica la misma lista segura que bodyMarkdown.","seo":"Si faq es válida, las mismas preguntas y respuestas se muestran al final del artículo y se emite JSON-LD FAQPage equivalente. Si falta o no es válida, no se emite FAQPage.","example":[{"question":"¿Cuánto tarda el servicio?","answer":"El plazo habitual es de **3 a 5 días laborables**. Consulta [el proceso](/blog/proceso)."},{"question":"¿Incluye soporte?","answer":"Sí, incluye soporte por correo durante 30 días."}]},"publishing":"El blog se sirve en el host de la landing del proyecto: /blog, /blog/<slug>, /blog/tag/<tag> y /blog/feed.xml. Solo hay blog si la landing está publicada. create/update_draft son inmediatos (borradores invisibles); publish/rollback/archive requieren aprobación humana. Adjunta agent_note con el motivo y revisa la preview con preview_url antes de pedir publish.","seo":"Cada artículo emite metadata completa (canonical en el dominio primario, OG type article) y JSON-LD Article + BreadcrumbList, más FAQPage cuando hay FAQ visible válida. Los tags generan páginas /blog/tag/<tag> y entran en el sitemap del host."},"x-examples":[{"description":"Validate a new article before creating it","body":{"resource":"blog_post","operation":"create","validate_only":true,"data":[{"pageId":"PAGE_ID","meta":{"title":"Domicilio fiscal y domicilio social: diferencias","slug":"domicilio-fiscal-y-social","excerpt":"Qué distingue el domicilio fiscal del social y por qué importa al constituir una empresa.","tags":["fiscalidad"],"publishedAt":"2026-07-21T09:00:00Z","authorName":"Equipo editorial","faq":[{"question":"¿Son siempre iguales?","answer":"No. Pueden coincidir, pero cumplen funciones distintas."}]},"bodyMarkdown":"## Qué es el domicilio fiscal\n\nEl domicilio fiscal es..."}]}},{"description":"Publish the latest draft (queues for human approval with preview)","body":{"resource":"blog_post","operation":"publish","data":[{"postId":"POST_ID"}],"agent_note":"Artículo revisado con preview_url; listo para publicar en /blog."}}]}},"/api/google-ads/agent-query":{"post":{"summary":"Google Ads data","description":"Query Google Ads metrics for the project's linked account.","tags":["Google Ads"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"get_account_summary","description":"Account-level metrics summary (impressions, clicks, cost, conversions, CTR, CPC, CPA) with comparable previousPeriod and delta (%) for executive reporting.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"],"description":"Named range; dateRange is accepted as an alias"},"from":{"type":"string","optional":true,"description":"Explicit start date YYYY-MM-DD (alias startDate); combine with to"},"to":{"type":"string","optional":true,"description":"Explicit end date YYYY-MM-DD (alias endDate)"},"daysBack":{"type":"number","optional":true,"description":"Last N complete days excluding today (1 = yesterday)"}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_campaigns","description":"List active campaigns with performance metrics.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"status":{"type":"string","default":"ENABLED"}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_keywords","description":"Keyword performance data.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_ads","description":"Ad performance data with headlines.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_ad_assets_performance","description":"Asset-level Display and Demand Gen creative performance with previews, policy/performance labels, technical conversions, and non-duplicating CRM lead attribution.","params":{"dateRange":{"type":"string","default":"LAST_30_DAYS"},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignNameContains":{"type":"string","optional":true,"description":"Campaign name substring filter."},"campaignIds":{"type":"array","optional":true,"items":{"type":"string"}},"campaignTypes":{"type":"array","default":["DISPLAY","DEMAND_GEN"],"items":{"type":"string","enum":["DISPLAY","DEMAND_GEN"]}},"includePreviews":{"type":"boolean","default":true},"includeImagePreviews":{"type":"boolean","default":true,"description":"Alias used by creative reporting clients."},"includeRemoved":{"type":"boolean","default":false},"includePolicyStatus":{"type":"boolean","default":true},"includeCreatedAt":{"type":"boolean","default":true},"includeLeadAttribution":{"type":"boolean","default":false},"groupBy":{"type":"array","default":["campaign","ad","asset"],"items":{"type":"string"}}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_creative_asset_performance","description":"Alias of get_ad_assets_performance for creative selection and CRM attribution workflows.","params":{"dateRange":{"type":"string","default":"LAST_30_DAYS"},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignNameContains":{"type":"string","optional":true},"campaignTypes":{"type":"array","default":["DISPLAY","DEMAND_GEN"]},"includeImagePreviews":{"type":"boolean","default":true},"includeRemoved":{"type":"boolean","default":false},"includeLeadAttribution":{"type":"boolean","default":false}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_daily_performance","description":"Daily metrics breakdown.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_tools","description":"List all Google Ads query tools available for the project.","params":{},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"diagnose_campaign_structure","description":"Diagnose active campaign types, ad groups, keywords, ads, and search-term availability.","params":{},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_campaign_chart","description":"Generate a visual chart URL or base64 image for impressions, clicks, conversions, or all metrics.","params":{"metric":{"type":"string","default":"all"},"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"format":{"type":"string","default":"url"}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_search_terms","description":"Search terms that triggered ads.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_display_ads","description":"Display creatives with type, image URLs, metrics, and view-through conversions.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_creative_performance","description":"Performance by creative across ad types.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_placements","description":"Managed placements with metrics for Display campaigns.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true},"limit":{"type":"number","default":50}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_placement_performance","description":"Placement performance filtered by minimum impressions.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true},"minImpressions":{"type":"number","default":100},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_view_through_conversions","description":"View-through conversion summary, trend, and campaign breakdown.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_brand_reach","description":"Brand reach, unique users, frequency, impressions, and cost per unique user.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_remarketing_lists","description":"Remarketing/user lists with size, type, membership duration, and performance.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_topic_targeting","description":"Display topic targeting with status and performance by topic.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_performance_max_assets","description":"Active or paused Performance Max asset_group_asset records grouped by type and asset group, with campaign-level brand guideline assets returned separately.","params":{"campaignId":{"type":"string","required":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_asset_groups","description":"Performance Max asset groups for a campaign.","params":{"campaignId":{"type":"string","required":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_campaign_inputs","description":"Active or paused Performance Max text inputs from asset groups, with campaign-level business names returned separately.","params":{"campaignId":{"type":"string","required":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_audience_signals","description":"Audience signals for a Performance Max campaign.","params":{"campaignId":{"type":"string","required":true},"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_custom_audiences","description":"Custom audiences assigned to a Performance Max campaign.","params":{"campaignId":{"type":"string","required":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_performance_max_diagnosis","description":"Health diagnosis for a Performance Max campaign, distinguishing asset-group creatives from campaign-level brand guidelines.","params":{"campaignId":{"type":"string","required":true},"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_asset_performance_breakdown","description":"Individual asset_group_asset performance breakdown for a Performance Max campaign.","params":{"campaignId":{"type":"string","required":true},"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_experiments","description":"List Google Ads experiments with type, status, and promote_status, including v24.2 campaign mix and PMax experiment types when returned by Google Ads.","params":{"limit":{"type":"number","default":50}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_experiment_arms","description":"List Google Ads experiment arms by resource_name.","params":{"limit":{"type":"number","default":50}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_local_services_leads","description":"List Local Services Ads leads using stable GAQL fields.","params":{"limit":{"type":"number","default":50}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_local_services_verifications","description":"List Local Services verification artifacts, statuses, and rejection reasons available through GAQL.","params":{"limit":{"type":"number","default":50}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_local_services_pmax_surfaces","description":"Inspect PMax campaigns, asset groups, and asset group signals relevant to Local Services/PMax v24.2 fields.","params":{"campaignId":{"type":"string","optional":true},"limit":{"type":"number","default":50}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_recommendations","description":"ALL active Google Ads recommendations with resource_name, optimizationScore, optimizationScoreDiagnostic, and a machine-readable completion gate. score_not_returned_by_google is a finite state; score_query_failed is retryable. Agents MUST NOT claim 100% unless completion.canClaim100Percent=true and MUST inform the user when completion.mustInformUser=true. Act via agent-mutate resource 'recommendations' (apply/dismiss).","params":{},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_ads_reports","description":"List generated Google Ads reports.","params":{"limit":{"type":"number","default":20}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"submit_ads_analysis","description":"Submit a briefing/analysis for an existing Google Ads report. Requires write scope.","params":{"reportId":{"type":"string","required":true},"text":{"type":"string","required":true}},"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"gaql_query","description":"Run a read-only GAQL SELECT query against Google Ads reporting.","params":{"gaql":{"type":"string","required":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_campaign_live","description":"Read a narrow, uncached structural campaign snapshot after mutations: status, serving status, bidding strategy, and budget.","params":{"campaignId":{"type":"string","optional":true},"resourceName":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_campaign_conversion_goals","description":"Audit campaign conversion goals, inherited customer goals, and active conversion actions for a campaign.","params":{"campaignId":{"type":"string","optional":true},"resourceName":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_business_profile_link_status","description":"Check Google Business Profile location asset link status for a campaign/account.","params":{"campaignId":{"type":"string","required":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_mutation_status","description":"Check a Google Ads mutation. After approval/execution, returns executionResult plus resource_name/id for a single created resource, and resource_names/createdResources for chaining dependent creates.","params":{"mutationId":{"type":"string","required":true}},"response_notes":{"pending":"status='pending' means a human still needs to approve/reject it.","executed":"status='executed' includes resource_name/id aliases when one resource was created and createdResources[] for one or many created resources.","error":"status='error' may include errorDetails.errors and top-level errors[] with GoogleAdsFailure details, including location.field_path_elements.","chaining":"Use createdResources[].resource_name as the real Google Ads resource reference for the next mutation, e.g. campaign_budget -> campaign -> ad_groups."},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pending_mutations","description":"List Google Ads mutations waiting for human approval.","params":{"limit":{"type":"number","default":20}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_mutation_history","description":"List Google Ads mutation history, including executed mutations with executionResult/resource_names/createdResources so agents can recover real IDs created in previous approved steps.","params":{"status":{"type":"string","default":"all","enum":["all","pending","executed","approved","rejected","cancelled","error"]},"limit":{"type":"number","default":20},"resource":{"type":"string","optional":true}},"example":{"request":{"tool":"list_mutation_history","params":{"status":"executed","resource":"campaign_budgets","limit":10}},"use":"Recover campaign budget resource_names before creating campaigns."},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"update_pending_mutation","description":"Update data or agent_note for a pending Google Ads mutation before human review.","params":{"mutationId":{"type":"string","required":true},"agent_note":{"type":"string","optional":true},"data":{"type":"array","optional":true}},"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"cancel_pending_mutation","description":"Cancel a pending Google Ads mutation before it is reviewed.","params":{"mutationId":{"type":"string","required":true},"reason":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"get_listing_groups","description":"Shopping listing group tree for an ad group.","params":{"adGroupId":{"type":"string","required":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_merchant_overview","description":"Merchant Center product status summary. Provider failures return provider='merchant_center', merchantAccount, phase, code, action, and retryable without Google Ads permission guidance.","params":{},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_merchant_products","description":"Merchant Center products with status/search/brand filters.","params":{"status":{"type":"string","optional":true},"search":{"type":"string","optional":true},"brand":{"type":"string","optional":true},"limit":{"type":"number","default":50}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_merchant_issues","description":"Merchant Center product diagnostics grouped by type and severity.","params":{"severity":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_merchant_product_detail","description":"Full Merchant Center product detail and issues.","params":{"productId":{"type":"string","required":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_merchant_feed_status","description":"Merchant Center feed status, including Content API / auto-sync accounts.","params":{},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"force_merchant_feed_refresh","description":"Force refresh of file-based Merchant Center feeds where supported.","params":{"datafeedId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"sync","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_merchant_promotions","description":"Merchant Center promotions.","params":{},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_merchant_shipping_settings","description":"Merchant Center shipping settings.","params":{},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_merchant_product_performance","description":"Merchant product click/impression performance.","params":{"days":{"type":"number","default":30},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_merchant_competitive_visibility","description":"Merchant competitive visibility benchmark data.","params":{"days":{"type":"number","default":30},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_negative_keywords","description":"Campaign, ad group, and shared-list negative keywords.","params":{"campaignId":{"type":"string","optional":true},"level":{"type":"string","default":"all"},"limit":{"type":"number","default":100}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_shared_negative_lists","description":"Shared negative keyword lists and optional keywords.","params":{"includeKeywords":{"type":"boolean","default":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_negative_exists","description":"Check whether a term is already negative at campaign, ad group, or shared-list level.","params":{"text":{"type":"string","required":true},"campaignId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_assets","description":"Campaign-linked assets such as sitelinks, callouts, snippets, calls, images, and promotions.","params":{"campaignId":{"type":"string","optional":true},"type":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_asset_performance","description":"Performance metrics by asset.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true},"limit":{"type":"number","default":50}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_asset_urls","description":"Check sitelink/asset URLs for reachable HTTP status.","params":{"campaignId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_audiences","description":"Audience performance metrics, optionally filtered by minimum conversions.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true},"minConversions":{"type":"number","default":0}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_customer_match_audiences","description":"List Customer Match/Data Manager audiences synchronized in DigitalPublic, optionally refreshing from Google Data Manager.","params":{"syncRemote":{"type":"boolean","default":false}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"search_audience_segments","description":"Search Google Ads audience segments and return IDs/resource names.","params":{"query":{"type":"string","optional":true},"types":{"type":"array","optional":true},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"preview_customer_match_upload","description":"Validate Customer Match rows, mapping, hashing eligibility, duplicates, and CRM opt-outs without sending anything to Google.","params":{"rows":{"type":"array","required":true},"mapping":{"type":"object","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_customer_match_upload_status","description":"Retrieve and refresh a Customer Match upload status by uploadId.","params":{"uploadId":{"type":"string","required":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_offline_conversion_upload_status","description":"Retrieve asynchronous Data Manager diagnostics for an offline conversion upload.","params":{"requestId":{"type":"string","required":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_segments","description":"Performance by device, geography, hour, day of week, or all segments.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"segment":{"type":"string","default":"all"},"campaignId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_audience_overlap","description":"Audience summary grouped by type with aggregate metrics.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_competitive_analysis","description":"Auction Insights competitive analysis for Search campaigns.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true},"competitorDepth":{"type":"number","default":10}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_quality_diagnosis","description":"Quality Score diagnosis by keyword and campaign/ad group aggregates.","params":{"period":{"type":"string","default":"LAST_30_DAYS","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"daysBack":{"type":"number","optional":true,"description":"Last N complete days, excluding today."},"campaignId":{"type":"string","optional":true},"minImpressions":{"type":"number","default":0},"limit":{"type":"number","default":50}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_seasonality_analysis","description":"Seasonality analysis with daily/weekly/monthly series, optional YoY, and anomaly detection.","params":{"dateFrom":{"type":"string","required":true},"dateTo":{"type":"string","required":true},"granularity":{"type":"string","default":"day"},"compareYear":{"type":"boolean","default":false},"campaignId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"download_report_pdf","description":"Get report data and PDF download URL for a previously generated report.","params":{"reportId":{"type":"string","required":true}},"x-mcp":{"channel":"google_ads","effect":"report_generation","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/google-ads/agent-mutate":{"post":{"summary":"Google Ads and Merchant Center mutations","description":"Create, update, remove, apply, dismiss, or validate allowlisted Google Ads and Merchant Center changes. Low-risk operations execute immediately; higher-risk operations queue for human approval unless project auto-approval is enabled. Requires write scope.","tags":["Google Ads"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"resource":{"type":"string","description":"Google Ads or Merchant resource name from x-resources."},"operation":{"type":"string","description":"Operation allowed for the resource."},"data":{"type":"array","description":"Array of resource payloads or operations."},"operations":{"type":"array","description":"Alternative batch operations payload for listing_group_operations."},"validate_only":{"type":"boolean","default":false},"agent_note":{"type":"string","description":"Recommended explanation for human approval."},"tool":{"type":"string","description":"Special tool name; supported values include link_business_profile_to_campaign, add_negative_keyword, create_youtube_video_asset, create_demand_gen_video_ad, launch_video_creative_test, and upload_offline_conversion_events."}}}}}},"responses":{"200":{"description":"Executed immediately, validated, or queued for approval","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-resources":[{"resource":"campaigns","operations":["create","update","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"campaign_budgets","operations":["create","update"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"ad_groups","operations":["create","update","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"ad_group_ads","operations":["create","update","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"ads","operations":["update"],"description":"Update an existing ad in place through AdService.MutateAds without recreating it (keeps history/learning): final_urls, tracking templates, and ad-type blocks such as responsive_display_ad.control_spec or responsive_search_ad texts. Identify the ad by resource_name customers/{customer_id}/ads/{ad_id} or adId (the Ad ID, not the AdGroupAd ID).","example":{"resource":"ads","operation":"update","data":[{"adId":814262197891,"responsive_display_ad":{"control_spec":{"enable_autogen_video":false}}}]},"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"ad_group_criteria","operations":["create","update","remove"],"description":"Create/update/remove ad group criteria. Supports direct user_list remarketing/RLSA attachment in Search and Display via AdGroupCriterion.user_list, and direct custom_audience/user_interest/detailed_demographic attachment in Display. For Demand Gen user_list, custom_audience, user_interest, and detailed_demographic shortcuts are routed through grouped Audience and linked as AdGroupCriterion.audience.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"listing_group_operations","operations":["mutate","rebuild_root","rebuild_tree"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"campaign_criteria","operations":["create","update","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"bidding_strategies","operations":["create","update","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"labels","operations":["create","update","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"campaign_labels","operations":["create","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"ad_group_labels","operations":["create","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"shared_sets","operations":["create","update","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"shared_criteria","operations":["create","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"assets","operations":["create","update","remove"],"description":"Create/update/remove Google Ads assets. For IMAGE assets, image_asset.data accepts raw base64 or a data URL and is decoded to bytes before Google Ads upload; mimeType/mime_type aliases such as image/jpeg are normalized. For YOUTUBE_VIDEO assets, pass youtube_video_asset.youtube_video_id, or the youtubeVideoId / youtubeUrl shortcut (watch/youtu.be/shorts URLs accepted) — type is set automatically. The video must already exist on YouTube (public or unlisted); to upload an MP4 first, use /api/creatives/agent-query youtube_upload_video with the project's connected YouTube channel.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"campaign_assets","operations":["create","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"customer_assets","operations":["create","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"audiences","operations":["create","update"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"custom_audiences","operations":["create","update","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"user_lists","operations":["create","update","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"asset_groups","operations":["create","update","remove"],"description":"Create/update/remove Performance Max asset groups. v24.2 Local Services field asset_group.google_local_services_info is accepted in payloads and requires agent_note plus human approval even when Google Ads auto-approval is enabled.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"asset_group_assets","operations":["create","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"asset_group_signals","operations":["create","remove"],"description":"Create/remove Performance Max asset group signals. Supports audience/user_list shortcuts plus v24.2 Local Services fields asset_group_signal.local_services_id and vertical_ads_item_group_rule_list; Local Services payloads require agent_note and human approval.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"experiments","operations":["create","update","remove"],"approval":"human_required","description":"Create/update/remove Google Ads experiments through ExperimentService, including v24.2 COMPARE_CAMPAIGNS and PMAX_TEXT_CUSTOMIZATION_FINAL_URL_EXPANSION experiment types when supported by the account/runtime. Requires agent_note and human approval.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"human","requestShape":"resource_operation"}},{"resource":"experiment_arms","operations":["create","update","remove"],"approval":"human_required","description":"Create/update/remove experiment arms through ExperimentArmService. Requires agent_note and human approval.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"human","requestShape":"resource_operation"}},{"resource":"conversion_actions","operations":["create","update","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"conversion_value_rules","operations":["create","update","remove"],"approval":"human_required","description":"Create, update, or remove advanced conversion value rules. Requires agent_note and human approval even when Google Ads auto-approval is enabled because value rules directly affect bidding signals.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"human","requestShape":"resource_operation"}},{"resource":"custom_conversion_goals","operations":["create","update","remove"],"approval":"human_required","description":"Create, update, or remove custom conversion goals that group conversion actions for campaign optimization. Requires agent_note and human approval.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"human","requestShape":"resource_operation"}},{"resource":"campaign_conversion_goals","operations":["update"],"approval":"human_required","description":"Set campaign-level conversion goal biddability without changing account-level conversion actions. Use validate_only first, include agent_note, and prefer disableOtherCampaignGoals=true when intentionally restricting a campaign to the listed goals.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"human","requestShape":"resource_operation"},"example":{"resource":"campaign_conversion_goals","operation":"update","validate_only":true,"agent_note":"Restrict this campaign to lead/contact website goals only.","data":[{"campaign":"customers/1234567890/campaigns/23961653698","goals":[{"category":"SUBMIT_LEAD_FORM","origin":"WEBSITE","biddable":true},{"category":"CONTACT","origin":"WEBSITE","biddable":true}],"disableOtherCampaignGoals":true}]}},{"resource":"conversion_goal_campaign_configs","operations":["update"],"approval":"human_required","description":"Set a campaign's conversion goal config: goal_config_level (CUSTOMER | CAMPAIGN) and custom_conversion_goal (numeric ID or resource name). Assigning a custom_conversion_goal without goal_config_level implies CAMPAIGN. Requires agent_note and human approval.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"human","requestShape":"resource_operation"},"example":{"resource":"conversion_goal_campaign_configs","operation":"update","validate_only":true,"agent_note":"Optimize this campaign against the 'Acme GEO-AEO Leads' custom goal instead of account defaults.","data":[{"campaign":"customers/1234567890/campaigns/23961653698","goal_config_level":"CAMPAIGN","custom_conversion_goal":"customers/1234567890/customConversionGoals/6458223419"}]}},{"resource":"customer_negative_criteria","operations":["create","remove"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"recommendations","operations":["apply","dismiss"],"description":"Apply or dismiss ANY Google Ads recommendation by resource_name (works for every type, including future/uncatalogued ones). Optional apply parameters can be passed alongside resource_name. If apply fails with RECOMMENDATION_NOT_APPLICABLE (type not applicable via API, already applied or invalidated), dismiss the same resource_name to remove it from the optimization score.","example":{"resource":"recommendations","operation":"apply","data":[{"resource_name":"customers/1234567890/recommendations/AbCdEf"}]},"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"recommendation_subscriptions","operations":["create","update"],"approval":"human_required","description":"Create or update recommendation subscriptions so Google can automatically apply selected recommendation types. Requires agent_note and human approval.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"human","requestShape":"resource_operation"}},{"resource":"merchant_products","operations":["create","update","review","delete"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"merchant_products_batch","operations":["update"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"merchant_promotions","operations":["create","update"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"merchant_local_inventory","operations":["update"],"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"tool":"add_negative_keyword","description":"Create campaign, ad group, or shared-list negative keywords from a compact agent payload. Returns a mutationId for audit; low-risk negatives are applied immediately unless validate_only=true.","params":{"campaignId":{"type":"string","optional":true},"adGroupId":{"type":"string","optional":true},"sharedSetId":{"type":"string","optional":true},"text":{"type":"string","optional":true},"matchType":{"type":"string","enum":["BROAD","PHRASE","EXACT"],"default":"PHRASE"},"reason":{"type":"string","optional":true},"keywords":{"type":"array","optional":true,"description":"Strings or objects with text/matchType/reason. A batch must target one level only."},"items":{"type":"array","optional":true,"description":"Alternative batch payload. Each item may include campaignId, adGroupId, or sharedSetId."},"data":{"type":"array","optional":true,"description":"Compatibility batch payload. Items accept text, keyword, term, or keyword:{text,match_type}, plus campaign/campaignId, adGroup/adGroupId, or sharedSet/sharedSetId."}},"example":{"tool":"add_negative_keyword","params":{"campaignId":"23961653698","text":"mi negocio","matchType":"PHRASE","reason":"Filtrar búsquedas de cliente final; objetivo prioritario agencias/distribuidores marca blanca"}},"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto","requestShape":"tool_params"}},{"tool":"link_business_profile_to_campaign","description":"Create/link Google Business Profile location assets for a campaign/account.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"tool":"create_youtube_video_asset","description":"Register a YouTube video as a Google Ads YOUTUBE_VIDEO asset (assets.create shortcut). Accepts a raw 11-char YouTube ID or any YouTube URL. The video must already exist on YouTube — upload it first with youtube_upload_video on /api/creatives/agent-query. Queued for human approval unless project auto-approval is enabled. Returns assetResourceName/assetId on execution.","params":{"youtubeVideoId":{"type":"string","optional":true,"description":"11-char YouTube video ID. Either this or youtubeUrl is required."},"youtubeUrl":{"type":"string","optional":true,"description":"YouTube watch/youtu.be/shorts URL."},"name":{"type":"string","optional":true,"description":"Asset display name."},"validate_only":{"type":"boolean","optional":true,"default":false},"agent_note":{"type":"string","optional":true,"description":"Auto-generated if omitted."}},"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"tool":"create_demand_gen_video_ad","description":"Create a DEMAND_GEN_VIDEO_RESPONSIVE_AD in a Demand Gen ad group (ad_group_ads.create shortcut). videoAssets must be existing YOUTUBE_VIDEO asset resource names or numeric IDs (create them first with create_youtube_video_asset). Defaults to status PAUSED for human review; long_headlines default to headlines when omitted; Google Ads requires logo_images for this ad type in most accounts. Queued for human approval unless project auto-approval is enabled.","params":{"adGroupResourceName":{"type":"string","optional":true,"description":"customers/{cid}/adGroups/{id}. Either this or adGroupId is required."},"adGroupId":{"type":"string","optional":true,"description":"Numeric Demand Gen ad group ID."},"videoAssets":{"type":"array","required":true,"description":"YOUTUBE_VIDEO asset resource names or numeric asset IDs (1-5)."},"businessName":{"type":"string","required":true},"headlines":{"type":"array","required":true,"description":"1-5 strings (max 40 chars each)."},"longHeadlines":{"type":"array","optional":true,"description":"Defaults to headlines when omitted."},"descriptions":{"type":"array","required":true,"description":"1-5 strings (max 90 chars each)."},"finalUrls":{"type":"array","required":true},"logoImages":{"type":"array","optional":true,"description":"IMAGE asset resource names or IDs for square logos (recommended 1200x1200)."},"status":{"type":"string","optional":true,"enum":["PAUSED","ENABLED"],"default":"PAUSED"},"validate_only":{"type":"boolean","optional":true,"default":false},"agent_note":{"type":"string","optional":true,"description":"Auto-generated if omitted."}},"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"tool":"launch_video_creative_test","description":"Launch a creative A/B test: create NEW Demand Gen video responsive ads across one or more ad groups while keeping the existing ads untouched (mode add_new_ads_keep_existing, the only supported mode). One ad per ad group in a single mutation; returns mutationId (pending approval) or the created adGroupAdResourceNames on execution. Compare performance afterwards with get_creative_performance and pause old ads explicitly with ad_group_ads.update if the test wins.","params":{"campaignId":{"type":"string","optional":true,"description":"Informative; used in the audit note."},"adGroupIds":{"type":"array","required":true,"description":"Demand Gen ad group IDs or resource names."},"youtubeVideoAssets":{"type":"array","required":true,"description":"YOUTUBE_VIDEO asset resource names or numeric asset IDs (alias: videoAssets)."},"mode":{"type":"string","optional":true,"enum":["add_new_ads_keep_existing"],"default":"add_new_ads_keep_existing"},"label":{"type":"string","optional":true,"description":"Test label recorded in the audit note (e.g. 'startup-video-v1')."},"businessName":{"type":"string","required":true},"headlines":{"type":"array","required":true},"longHeadlines":{"type":"array","optional":true},"descriptions":{"type":"array","required":true},"finalUrl":{"type":"string","optional":true,"description":"Single URL alternative to finalUrls."},"finalUrls":{"type":"array","optional":true},"logoImages":{"type":"array","optional":true},"status":{"type":"string","optional":true,"enum":["PAUSED","ENABLED"],"default":"PAUSED"},"validate_only":{"type":"boolean","optional":true,"default":false},"agent_note":{"type":"string","optional":true,"description":"Auto-generated if omitted."}},"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"resource":"audience_criteria_notes","description":"ad_group_criteria.create, campaign_criteria.create, and asset_group_signals.create accept custom_audience, user_interest, detailed_demographic, and user_list as numeric IDs or full resource names. user_list is attached directly as AdGroupCriterion.user_list for Search/RLSA and Display; custom_audience/user_interest/detailed_demographic are attached directly for Display. For user_list/custom_audience/user_interest/detailed_demographic in Demand Gen ad groups, the platform creates an Audience first and links AdGroupCriterion.audience, ensuring AdGroup.use_audience_grouped=true. For Demand Gen campaign_criteria.create with location or language on upgraded targeting campaigns, the platform routes criteria to active ad groups as AdGroupCriterion because Google Ads exposes Demand Gen geo/language at ad group level. For Performance Max campaigns/asset groups, it creates an Audience and links AssetGroupSignal.audience. campaign_conversion_goals.update changes campaign-level goal biddability only; it never mutates account-level conversion_action.primary_for_goal or include_in_conversions_metric. Empty Google Ads create results are treated as errors, not ok:true. For ad_groups/campaigns.update, incomplete targeting_setting.target_restrictions are completed from current Google Ads values for AGE_RANGE, GENDER, PARENT, INCOME_RANGE, and AUDIENCE before mutating.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"brand_asset_notes","description":"customer_assets.create routes LOGO, LANDSCAPE_LOGO, BUSINESS_LOGO, and BUSINESS_NAME through the supported brand asset link path. With campaign it creates CampaignAsset; with asset_group it creates AssetGroupAsset. If no target is sent and the account has exactly one active Performance Max asset group, the platform links there automatically. Direct CustomerAsset links are still used for field types Google Ads supports at customer level.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"responsive_display_ad_notes","description":"ad_group_ads.create strips responsive_display_ad image entries to the supported AdImageAsset shape { asset }. If Google Ads returns media_upload_error 11 and marketing_images/square_marketing_images are valid 1200x628 and 1200x1200 assets, inspect logo_images/square_logo_images next. Incident #285 was caused by a 512x512 logo asset in logo_images; although Google Ads documents square logo minimum 128x128 and recommends 1200x1200, the practical fix was to remove the small logo or upload/use a 1200x1200 logo asset. For exact-ratio replacement uploads, assets.create decodes base64 to bytes before Google Ads upload.","official_specs":"RDA recommended/minimum sizes: horizontal image 1200x628 / 600x314, square image 1200x1200 / 300x300, square logo 1200x1200 / 128x128, landscape logo 1200x300 / 512x128.","x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"tool":"submit_customer_match_upload","description":"Queue a Customer Match upload from structured rows. Rows are normalized, deduplicated, hashed, stripped from the mutation payload, and held for human approval before Google Data Manager ingest.","params":{"rows":{"type":"array","required":true},"mapping":{"type":"object","optional":true},"operation":{"type":"string","enum":["append","remove","replace"],"default":"append"},"audienceId":{"type":"string","optional":true},"audienceName":{"type":"string","optional":true},"membershipDurationDays":{"type":"number","optional":true,"default":540,"minimum":1,"maximum":540},"consentAccepted":{"type":"boolean","required":true},"legalBasis":{"type":"string","required":true},"agent_note":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"tool":"upload_offline_conversion_events","description":"Send idempotent Google Ads offline conversion events through Data Manager API v1. Click/session identifiers are sent directly to Google and excluded from DigitalPublic audit payloads. Use validate_only first and get_offline_conversion_upload_status for asynchronous diagnostics.","params":{"conversionActionId":{"type":"string","required":true,"description":"Numeric UPLOAD_CLICKS conversion action ID or full resource_name."},"events":{"type":"array","required":true,"maxItems":2000,"description":"Events with transactionId, eventTimestamp, at least one of gclid/gbraid/wbraid/sessionAttributes, and optional conversionValue/currency/eventSource."},"consentAccepted":{"type":"boolean","required":true},"legalBasis":{"type":"string","required":true},"validate_only":{"type":"boolean","optional":true,"default":false},"agent_note":{"type":"string","required":true}},"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"tool":"sync_crm_segment_to_google_ads_audience","description":"Queue a CRM segment synchronization into a Google Ads Customer Match audience. CRM opt-outs are excluded and execution requires human approval.","params":{"audienceId":{"type":"string","optional":true},"audienceName":{"type":"string","optional":true},"stage":{"type":"string","optional":true},"type":{"type":"string","optional":true},"tag":{"type":"string","optional":true},"source":{"type":"string","optional":true},"limit":{"type":"number","default":10000},"operation":{"type":"string","enum":["append","remove","replace"],"default":"append"},"membershipDurationDays":{"type":"number","optional":true,"default":540,"minimum":1,"maximum":540},"consentAccepted":{"type":"boolean","required":true},"legalBasis":{"type":"string","required":true},"agent_note":{"type":"string","optional":true}},"x-mcp":{"channel":"google_ads","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}}]}},"/api/meta-ads/agent-query":{"post":{"summary":"Meta Ads / Facebook Ads data","description":"Query Meta Ads connection status and campaigns for the project's linked ad account.","tags":["Meta Ads"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"list_tools","description":"List all Meta Ads query tools.","params":{},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_connection_status","description":"Return non-sensitive Meta Ads connection metadata for the project.","params":{},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_campaigns","description":"List Meta Ads campaigns with id, name, status, objective, and effectiveStatus.","params":{},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_campaign","description":"Get one Meta Ads campaign.","params":{"campaignId":{"type":"string","required":true}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_adsets","description":"List ad sets for the account or one campaign.","params":{"campaignId":{"type":"string","optional":true},"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_adset","description":"Get one Meta Ads ad set.","params":{"adsetId":{"type":"string","required":true}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_ads","description":"List ads for the account, one campaign, or one ad set.","params":{"campaignId":{"type":"string","optional":true},"adsetId":{"type":"string","optional":true},"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_ad","description":"Get one Meta ad.","params":{"adId":{"type":"string","required":true}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_creatives","description":"List account ad creatives.","params":{"limit":{"type":"number","default":50}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pages","description":"List accessible Facebook Pages and Instagram identities.","params":{"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_businesses","description":"List accessible Business Managers.","params":{"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_ad_images","description":"List reusable ad images and hashes.","params":{"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_ad_videos","description":"List reusable ad videos.","params":{"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"search_targeting","description":"Resolve targeting IDs for interests, locations, locales, and categories.","params":{"type":{"type":"string","required":true},"q":{"type":"string","required":true},"limit":{"type":"number","default":25}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pixels","description":"List account pixels/datasets.","params":{"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_custom_conversions","description":"List custom conversions.","params":{"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_custom_audiences","description":"List custom and lookalike audiences.","params":{"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_product_catalogs","description":"List product catalogs owned by the configured business.","params":{"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_automated_rules","description":"List account automated rules.","params":{"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_ad_studies","description":"List account experiments and A/B studies.","params":{"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_recommendations","description":"List operational recommendations from Meta.","params":{"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_lead_forms","description":"List instant lead forms.","params":{"pageId":{"type":"string","optional":true},"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_leads","description":"Retrieve leads from an instant form.","params":{"formId":{"type":"string","required":true},"limit":{"type":"number","default":100}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_ad_preview","description":"Render an ad preview.","params":{"adId":{"type":"string","required":true},"ad_format":{"type":"string","default":"DESKTOP_FEED_STANDARD"}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"preflight_campaign_bundle","description":"Run local and remote validation without publishing.","params":{"data":{"type":"array","required":true}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_insights","description":"Return Meta Ads insights by level with breakdowns and attribution controls.","params":{"level":{"type":"string","default":"campaign"},"id":{"type":"string","optional":true},"date_preset":{"type":"string","default":"last_30d"},"time_range":{"type":"object","optional":true},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Sent to Meta as time_range and applied exactly."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Sent to Meta as time_range and applied exactly."},"breakdowns":{"type":"array","optional":true},"time_increment":{"type":"string","optional":true}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"diagnose_account","description":"Account-level operational diagnosis.","params":{},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"diagnose_campaign","description":"Campaign-level operational diagnosis.","params":{"campaignId":{"type":"string","required":true}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_delivery_issues","description":"List active campaigns or ads with limited delivery / exhausted budget signals.","params":{},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_mutation_status","description":"Check one pending or executed Meta Ads mutation.","params":{"mutationId":{"type":"string","required":true}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pending_mutations","description":"List pending Meta Ads mutations.","params":{"limit":{"type":"number","default":20}},"x-mcp":{"channel":"meta_ads","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/meta-ads/agent-mutate":{"post":{"summary":"Meta Ads / Facebook Ads campaign actions","description":"Create and maintain Meta Ads campaigns through DigitalPublic. Requires write scope. New campaigns, ad sets and ads are always created PAUSED. Budget, targeting, schedule, special categories and creation operations require human approval unless meta_ads auto-approval is enabled.","tags":["Meta Ads"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Executed or validated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"pause_campaign","description":"Pause a Meta Ads campaign.","params":{"campaignId":{"type":"string","required":true},"agent_note":{"type":"string","optional":true},"validate_only":{"type":"boolean","optional":true}},"x-mcp":{"channel":"meta_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"enable_campaign","description":"Enable a Meta Ads campaign.","params":{"campaignId":{"type":"string","required":true},"agent_note":{"type":"string","optional":true},"validate_only":{"type":"boolean","optional":true}},"x-mcp":{"channel":"meta_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"tool_params"}},{"name":"resource_mutation","description":"Recommended structured mutation format.","params":{"resource":{"type":"string","required":true},"operation":{"type":"string","required":true},"data":{"type":"array","required":true},"validate_only":{"type":"boolean","optional":true},"remote_validate":{"type":"boolean","optional":true},"idempotency_key":{"type":"string","optional":true},"agent_note":{"type":"string","optional":true}},"x-mcp":{"channel":"meta_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}}],"x-resources":[{"resource":"meta_campaigns","operations":["create","update_status","update_name","update_budget","update_special_ad_categories","copy","delete"],"x-mcp":{"channel":"meta_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"meta_adsets","operations":["create","update_status","update_budget","update_schedule","update_targeting","update_bid","copy","delete"],"x-mcp":{"channel":"meta_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"meta_creatives","operations":["create","delete"],"x-mcp":{"channel":"meta_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"meta_ads","operations":["create","update_status","update_name","update_creative","update_tracking","copy","delete"],"x-mcp":{"channel":"meta_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"meta_campaign_bundle","operations":["create"],"description":"Create campaign + ad set + creative + ad, all PAUSED.","x-mcp":{"channel":"meta_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"meta_media","operations":["upload_image","upload_video"],"x-mcp":{"channel":"meta_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"meta_custom_audiences","operations":["create","update_name","add_users","remove_users","delete"],"x-mcp":{"channel":"meta_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"meta_lead_forms","operations":["create","delete"],"x-mcp":{"channel":"meta_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"meta_automated_rules","operations":["create","update_status","delete"],"x-mcp":{"channel":"meta_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"meta_ad_studies","operations":["create","delete"],"x-mcp":{"channel":"meta_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"meta_conversion_events","operations":["send"],"x-mcp":{"channel":"meta_ads","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}}]}},"/api/seo-tools/agent-query":{"post":{"summary":"SEO tools","description":"Query SEO metrics for the project's configured domain. DigitalPublic resolves the underlying SEO data source; agents never address it directly.","tags":["SEO"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"seo_domain_overview","description":"Domain overview with regional and worldwide metrics.","params":{"domain":{"type":"string","optional":true},"db":{"type":"string","default":"es"}},"x-mcp":{"channel":"seo_tools","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"seo_domain_keywords","description":"Organic keywords for the domain.","params":{"domain":{"type":"string","optional":true},"db":{"type":"string","default":"es"},"limit":{"type":"number","default":50}},"x-mcp":{"channel":"seo_tools","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"seo_backlinks_summary","description":"Backlink profile summary.","params":{"domain":{"type":"string","optional":true}},"x-mcp":{"channel":"seo_tools","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"seo_backlinks_changes","description":"Backlink history/changes.","params":{"domain":{"type":"string","optional":true}},"x-mcp":{"channel":"seo_tools","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"seo_backlinks_anchors","description":"Anchor text distribution.","params":{"domain":{"type":"string","optional":true}},"x-mcp":{"channel":"seo_tools","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"seo_competitors","description":"SEO competitors analysis.","params":{"domain":{"type":"string","optional":true},"source":{"type":"string","default":"es"},"type":{"type":"string","default":"organic"}},"x-mcp":{"channel":"seo_tools","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"seo_keyword_research","description":"Research keywords with volumes, CPC, difficulty and intents.","params":{"keywords":{"type":"string|array","required":true,"aliases":["keyword","query","term"]},"source":{"type":"string","default":"es"},"sort":{"type":"string","optional":true},"sort_order":{"type":"string","optional":true}},"x-mcp":{"channel":"seo_tools","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"seo_keyword_questions","description":"Related questions for a keyword.","params":{"keyword":{"type":"string","required":true,"aliases":["query","term"]},"source":{"type":"string","default":"es"},"limit":{"type":"number","default":100},"offset":{"type":"number","default":0}},"x-mcp":{"channel":"seo_tools","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"seo_serp_results","description":"SERP results for a keyword via an asynchronous SERP task. Every call without task_id creates a billable task, so the cycle is: call once with keyword, read taskId in the response, and if status is 'processing' call again with ONLY task_id (never resend the keyword). Two identical keyword calls within 15 minutes reuse the same task.","params":{"keyword":{"type":"string","required":"unless task_id is sent","aliases":["query","term"]},"task_id":{"type":"string|number","optional":true,"aliases":["taskId","serp_task_id"],"description":"Id returned by a previous call. When present the task is only read, never re-created, and keyword/location params are ignored."},"language_code":{"type":"string","default":"es"},"google_ads_location_id":{"type":"number","default":2724,"description":"Google Ads geo target id (2724 = Spain, 2276 = Germany, 2840 = United States), from the public Google Ads geo target constants table. Recommended way to target a country."},"location_id":{"type":"number","optional":true,"aliases":["region_id"],"description":"Id from the SEO data provider's OWN location catalog, a different catalog from Google Ads: the same number means a different place (or none at all) in each one. Never translate an id between catalogs. If you only know the Google Ads geo target id, send google_ads_location_id instead. When both are sent, location_id wins."},"device":{"type":"string","default":"desktop"},"limit":{"type":"number","default":10},"waitMs":{"type":"number","default":15000,"description":"How long the call waits for the task before returning status 'processing' with its taskId (max 25000)."}},"returns":{"taskId":"string","status":"completed | processing | submitted","reusedExistingTask":"boolean","result":"SERP payload when completed","retrieveWith":"exact follow-up call when the task is still processing"},"x-mcp":{"channel":"seo_tools","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"seo_domain_pages","description":"Top pages by organic traffic.","params":{"domain":{"type":"string","optional":true},"source":{"type":"string","default":"es"},"scope":{"type":"string","default":"base_domain"},"type":{"type":"string","default":"organic"},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"seo_tools","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"seo_ai_overview","description":"AI search visibility metrics.","params":{"domain":{"type":"string","optional":true},"source":{"type":"string","default":"es"},"engine":{"type":"string","default":"ai-overview"},"scope":{"type":"string","default":"base_domain"}},"x-mcp":{"channel":"seo_tools","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"download_seo_report_pdf","description":"Get report data and PDF download URL.","params":{"reportId":{"type":"string","required":true}},"x-mcp":{"channel":"seo_tools","effect":"report_generation","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_seo_reports","description":"List SEO reports saved for this project.","params":{"limit":{"type":"number","default":10}},"x-mcp":{"channel":"seo_tools","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"submit_seo_analysis","description":"Submit the analysis/briefing for a SEO report (requires write scope).","params":{"reportId":{"type":"string","required":true},"analysis":{"type":"object","description":"{ resumenEjecutivo, logros, alertas, propuestasMejora, proximosPasos }"}},"x-mcp":{"channel":"seo_tools","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}}]}},"/api/google-tag-manager/agent-query":{"post":{"summary":"Google Tag Manager query tools","description":"Query and audit the Google Tag Manager container assigned to the project.","tags":["Google Tag Manager"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"gtm_status","description":"Container assignment, public ID, account, and summary counts.","params":{},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_workspaces","description":"List GTM workspaces.","params":{},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_workspace_status","description":"Find modified/conflicting entities in a workspace.","params":{"workspaceId":{"type":"string","required":true}},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_tags","description":"List tags in a workspace.","params":{"workspaceId":{"type":"string","required":true}},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_tag","description":"Get one tag by tagId or path.","params":{"workspaceId":{"type":"string"},"tagId":{"type":"string"},"path":{"type":"string"}},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_triggers","description":"List triggers in a workspace.","params":{"workspaceId":{"type":"string","required":true}},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_trigger","description":"Get one trigger by triggerId or path.","params":{"workspaceId":{"type":"string"},"triggerId":{"type":"string"},"path":{"type":"string"}},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_variables","description":"List variables in a workspace.","params":{"workspaceId":{"type":"string","required":true}},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_variable","description":"Get one variable by variableId or path.","params":{"workspaceId":{"type":"string"},"variableId":{"type":"string"},"path":{"type":"string"}},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_folders","description":"List folders in a workspace.","params":{"workspaceId":{"type":"string","required":true}},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_templates","description":"List templates in a workspace.","params":{"workspaceId":{"type":"string","required":true}},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_environments","description":"List GTM environments.","params":{},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_versions","description":"List GTM container versions.","params":{},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"quick_preview","description":"Create a quick preview for a workspace.","params":{"workspaceId":{"type":"string","required":true}},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_mutation_status","description":"Check one pending GTM mutation.","params":{"mutationId":{"type":"string","required":true}},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pending_mutations","description":"List pending GTM mutations.","params":{"limit":{"type":"number","default":20}},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_mutation_history","description":"List GTM mutation history.","params":{"status":{"type":"string","default":"all"},"limit":{"type":"number","default":20},"resource":{"type":"string","optional":true}},"x-mcp":{"channel":"gtm","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"update_pending_mutation","description":"Update a pending GTM mutation.","params":{"mutationId":{"type":"string","required":true},"agent_note":{"type":"string","optional":true},"data":{"type":"array","optional":true}},"x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"cancel_pending_mutation","description":"Cancel a pending GTM mutation.","params":{"mutationId":{"type":"string","required":true},"reason":{"type":"string","optional":true}},"x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}}]}},"/api/google-tag-manager/agent-mutate":{"post":{"summary":"Google Tag Manager mutations","description":"Link an existing GTM container to a project or queue workspace, tag, trigger, variable, template, environment, and version changes for admin approval. Requires write scope.","tags":["Google Tag Manager"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"queue_gtm_mutation","description":"Link an existing GTM container or queue a GTM API mutation scoped to the project's assigned container.","params":{"resource":{"type":"string","required":true,"description":"gtm_container | gtm_workspaces | gtm_tags | gtm_triggers | gtm_variables | gtm_built_in_variables | gtm_folders | gtm_templates | gtm_clients | gtm_zones | gtm_transformations | gtm_environments | gtm_versions"},"operation":{"type":"string","required":true,"description":"link | create | update | delete | revert | sync | import_from_gallery | move_entities_to_folder | reauthorize | publish | set_latest | undelete"},"workspaceId":{"type":"string","optional":true},"data":{"type":"array","required":true},"validate_only":{"type":"boolean","default":false},"agent_note":{"type":"string","optional":true}},"x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}}],"x-resources":[{"resource":"gtm_container","operations":["link"],"description":"Validate an existing GTM container against the Google API and link it to the selected project. Shared containers are allowed; no GTM content is changed.","operationParams":{"link":{"data":{"type":"array","required":true,"minItems":1,"maxItems":1,"description":"One object with publicId, or containerPath, or accountId/accountPath plus containerId.","items":{"type":"object","properties":{"publicId":{"type":"string","description":"Public GTM ID, for example GTM-PLRNJP6R."},"containerPath":{"type":"string","description":"GTM API path, for example accounts/1/containers/2."},"accountId":{"type":"string"},"accountPath":{"type":"string"},"containerId":{"type":"string"},"accountName":{"type":"string"},"name":{"type":"string"},"domainName":{"type":"string"}}}},"agent_note":{"type":"string","required":true,"description":"Audit note explaining why this existing container is linked to the project."}}},"x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"gtm_workspaces","operations":["create","update","delete","sync"],"description":"Queue a GTM API mutation scoped to the project's assigned container.","x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"gtm_tags","operations":["create","update","delete","revert"],"description":"Queue a GTM API mutation scoped to the project's assigned container.","x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"gtm_triggers","operations":["create","update","delete","revert"],"description":"Queue a GTM API mutation scoped to the project's assigned container.","x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"gtm_variables","operations":["create","update","delete","revert"],"description":"Queue a GTM API mutation scoped to the project's assigned container.","x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"gtm_built_in_variables","operations":["create","delete","revert"],"description":"Queue a GTM API mutation scoped to the project's assigned container.","x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"gtm_folders","operations":["create","update","delete","move_entities_to_folder","revert"],"description":"Queue a GTM API mutation scoped to the project's assigned container.","x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"gtm_templates","operations":["create","update","delete","import_from_gallery","revert"],"description":"Queue a GTM API mutation scoped to the project's assigned container.","x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"gtm_clients","operations":["create","update","delete","revert"],"description":"Queue a GTM API mutation scoped to the project's assigned container.","x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"gtm_zones","operations":["create","update","delete","revert"],"description":"Queue a GTM API mutation scoped to the project's assigned container.","x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"gtm_transformations","operations":["create","update","delete","revert"],"description":"Queue a GTM API mutation scoped to the project's assigned container.","x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"gtm_environments","operations":["create","update","delete","reauthorize"],"description":"Queue a GTM API mutation scoped to the project's assigned container.","x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"gtm_versions","operations":["create","publish","set_latest","delete","undelete"],"description":"Queue a GTM API mutation scoped to the project's assigned container.","x-mcp":{"channel":"gtm","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}}]}},"/api/analytics/agent-query":{"post":{"summary":"Google Analytics (GA4) data","description":"Query GA4 metrics, audiences, and supported GA4 Admin API configuration for the project's linked property.","tags":["Analytics"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"acquisition_attribution","description":"Session-scoped GA4 acquisition attribution with source, medium, campaign, manual ad content (utm_content), landing page, sessions, users, Key Events, and a rate calculated only when its inputs are available. Empty or unavailable data is explicit and never coerced to zero.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD; requires to."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD; requires from."},"source":{"type":"string","optional":true,"description":"Exact, case-insensitive session source."},"medium":{"type":"string","optional":true,"description":"Exact, case-insensitive session medium."},"campaign":{"type":"string","optional":true,"description":"Exact, case-insensitive session campaign."},"landingPage":{"type":"string","optional":true,"description":"Substring of landing page plus query string."},"limit":{"type":"number","default":100,"min":1,"max":250}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"traffic_overview","description":"Total sessions, users, pageviews, bounce rate. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"traffic_by_channel","description":"Traffic breakdown by channel (organic, paid, social, etc.). Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"top_pages","description":"Most visited pages. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"device_breakdown","description":"Traffic by device type. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"top_countries","description":"Traffic by country. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"source_medium","description":"Traffic sources with medium. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"new_vs_returning","description":"New vs returning users. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"traffic_evolution","description":"Daily traffic evolution. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_events","description":"List measured GA4 events for the period. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"limit":{"type":"number","default":100}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"events_overview","description":"Return measured GA4 events with counts and event-level metrics. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."},"limit":{"type":"number","default":100}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_key_events","description":"List configured GA4 Key Events for the linked property. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"key_events_overview","description":"Key Events total, rate over sessions, top events, and configuration status. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"key_events_by_event","description":"Break down Key Events by GA4 event name. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"key_events_by_channel","description":"Attribute Key Events by traffic channel. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"key_events_by_source_medium","description":"Attribute Key Events by source/medium. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"key_events_evolution","description":"Daily Key Events and sessions trend. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"top_key_event_pages","description":"Landing pages that generate the most Key Events. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":30},"dateRange":{"type":"string","optional":true,"enum":["TODAY","YESTERDAY","LAST_7_DAYS","LAST_30_DAYS","LAST_90_DAYS","THIS_MONTH","LAST_MONTH"]},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"audit_hygiene","description":"Audit supported GA4 Admin API configuration, audiences and Google Ads link status.","params":{},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_audiences","description":"List GA4 audiences available for remarketing activation.","params":{},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_audience","description":"Get one GA4 audience by resource name.","params":{"audienceName":{"type":"string","required":true}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_google_ads_links","description":"List Google Ads links configured on the GA4 property.","params":{},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_google_ads_link","description":"Check whether the GA4 property is linked to a Google Ads customer.","params":{"customerId":{"type":"string","optional":true}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"recommend_country_exclusion","description":"Explain why country exclusion is not a native GA4 Admin API filter and suggest alternatives.","params":{"countries":{"type":"string|array","optional":true}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_mutation_status","description":"Check one pending Analytics mutation.","params":{"mutationId":{"type":"string","required":true}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pending_mutations","description":"List pending Analytics mutations.","params":{"limit":{"type":"number","default":20}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_mutation_history","description":"List Analytics mutation history.","params":{"status":{"type":"string","default":"all"},"limit":{"type":"number","default":20},"resource":{"type":"string","optional":true}},"x-mcp":{"channel":"analytics","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"update_pending_mutation","description":"Update a pending Analytics mutation.","params":{"mutationId":{"type":"string","required":true},"agent_note":{"type":"string","optional":true},"data":{"type":"array","optional":true}},"x-mcp":{"channel":"analytics","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"cancel_pending_mutation","description":"Cancel a pending Analytics mutation.","params":{"mutationId":{"type":"string","required":true},"reason":{"type":"string","optional":true}},"x-mcp":{"channel":"analytics","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}}]}},"/api/analytics/agent-mutate":{"post":{"summary":"Google Analytics (GA4) mutations","description":"Link the project's GA4 property or create supported GA4 Admin API changes for audiences, Key Events, and Google Ads links. Requires write scope and admin approval unless Analytics auto-approval is enabled for the project.","tags":["Analytics"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"link_property","description":"Link an existing GA4 property to the project. If measurementId is omitted, it is resolved from the property's web data stream.","params":{"resource":{"type":"string","enum":["analytics_property"]},"operation":{"type":"string","enum":["link"]},"data":{"type":"array","required":true,"description":"Exactly one payload: { propertyId, measurementId?, name?, websiteUrl? }."},"validate_only":{"type":"boolean","default":false},"agent_note":{"type":"string","optional":true}},"x-mcp":{"channel":"analytics","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"name":"create_audience","description":"Queue creation of a GA4 audience using a supported template.","params":{"resource":{"type":"string","enum":["analytics_audiences"]},"operation":{"type":"string","enum":["create"]},"data":{"type":"array","required":true,"description":"Array of audience template payloads"},"validate_only":{"type":"boolean","default":false},"agent_note":{"type":"string","optional":true}},"x-mcp":{"channel":"analytics","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"name":"create_key_event","description":"Queue creation of a GA4 Key Event for an existing or planned event name.","params":{"resource":{"type":"string","enum":["analytics_key_events"]},"operation":{"type":"string","enum":["create"]},"data":{"type":"array","required":true,"description":"Array of Key Event payloads: { eventName, countingMethod?, defaultValue? }. countingMethod defaults to ONCE_PER_EVENT."},"validate_only":{"type":"boolean","default":false},"agent_note":{"type":"string","optional":true}},"x-mcp":{"channel":"analytics","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"name":"create_google_ads_link","description":"Queue creation of the GA4 to Google Ads link for the project account.","params":{"resource":{"type":"string","enum":["analytics_google_ads_links"]},"operation":{"type":"string","enum":["create"]},"data":{"type":"array","required":true,"description":"Array with one or more link payloads"},"validate_only":{"type":"boolean","default":false},"agent_note":{"type":"string","optional":true}},"x-mcp":{"channel":"analytics","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}}]}},"/api/search-console/agent-query":{"post":{"summary":"Google Search Console data","description":"Query Search Console performance metrics and supported management state for the project's configured site.","tags":["Search Console"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"search_overview","description":"Search Console overview: clicks, impressions, CTR, average position. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":28},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"search_console","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"top_queries","description":"Top organic queries. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":28},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"search_console","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"top_pages","description":"Top pages from Search Console. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":28},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"search_console","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"device_breakdown","description":"Performance by device. Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":28},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"search_console","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"opportunities","description":"Queries with SEO opportunity (positions 4-15). Exact from/to ranges are applied without silent truncation.","params":{"days":{"type":"number","default":28},"from":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires to. Applied exactly, without silent truncation."},"to":{"type":"string","optional":true,"description":"YYYY-MM-DD, inclusive. Requires from. Applied exactly, without silent truncation."}},"x-mcp":{"channel":"search_console","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_sitemaps","description":"List registered sitemaps for the Search Console property.","params":{},"x-mcp":{"channel":"search_console","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"inspect_url","description":"Inspect one URL with the URL Inspection API.","params":{"url":{"type":"string","required":true}},"x-mcp":{"channel":"search_console","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"index_coverage_summary","description":"Return support status and alternatives because public API has no aggregate coverage inventory.","params":{"since":{"type":"string","optional":true},"until":{"type":"string","optional":true}},"x-mcp":{"channel":"search_console","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"removal_url","description":"Return support status because public API has no Removal Tool endpoint.","params":{"url":{"type":"string","optional":true},"type":{"type":"string","optional":true}},"x-mcp":{"channel":"search_console","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_mutation_status","description":"Check a Search Console mutation by mutationId, including execution result and actionable errors.","params":{"mutationId":{"type":"string","required":true}},"x-mcp":{"channel":"search_console","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pending_mutations","description":"List Search Console mutations pending human approval.","params":{"limit":{"type":"number","default":20}},"x-mcp":{"channel":"search_console","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_mutation_history","description":"List Search Console mutation history and execution results.","params":{"status":{"type":"string","default":"all"},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"search_console","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/search-console/agent-mutate":{"post":{"summary":"Google Search Console mutations","description":"Link the project's Search Console property or queue official sitemap mutations. Requires write scope and admin approval unless Search Console auto-approval is enabled for the project.","tags":["Search Console"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-resources":[{"resource":"sc_sitemap","operations":["submit","delete"],"x-mcp":{"channel":"search_console","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}},{"resource":"seo_config","operations":["update"],"description":"Link or update the project's Search Console site, SEO domain, target keywords, and competitors with { domain?, searchConsoleSiteUrl?, targetKeywords?, competitors? }.","x-mcp":{"channel":"search_console","effect":"write","requiredScope":"write","approval":"auto_approval_possible","requestShape":"resource_operation"}}]}},"/api/comments/agent-query":{"post":{"summary":"Project comments","description":"Read and write comments on the project. Agents can only edit/delete their own comments.","tags":["Comments"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"post_comment","description":"Create a new comment. Requires write scope. Incident #286/B2: if this returns COMMENT_WRITE_TRANSIENT or an upstream 'error code: 1010', first call list_comments to verify whether the comment was persisted; if it is missing, retry the same payload. The API retries transient database writes before returning an error.","params":{"text":{"type":"string","required":true},"area":{"type":"string","optional":true,"enum":["google-ads","seo","analytics"]},"author":{"type":"string","optional":true,"default":"Agente IA"}},"x-mcp":{"channel":"comments","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"edit_comment","description":"Edit an agent's own comment. Requires write scope. Incident #286/B2: transient write failures are retried by the API; on COMMENT_WRITE_TRANSIENT, call list_comments, confirm the current text, and retry the same edit only if the change is still missing.","params":{"commentId":{"type":"string","required":true},"text":{"type":"string","required":true}},"x-mcp":{"channel":"comments","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"delete_comment","description":"Delete an agent's own comment. Requires write scope.","params":{"commentId":{"type":"string","required":true}},"x-mcp":{"channel":"comments","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"list_comments","description":"List project comments. Requires read scope.","params":{"area":{"type":"string","optional":true,"enum":["google-ads","seo","analytics"]},"limit":{"type":"number","default":50,"max":100}},"x-mcp":{"channel":"comments","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/google-business/agent-query":{"post":{"summary":"Google Business Profile data","description":"Read Google Business Profile connection state, locations, posts, reviews, media and approved mutation results without exposing OAuth credentials.","tags":["Google Business Profile"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"get_business_profile_connection_status","description":"Check whether OAuth and a Business Profile location are configured for the project. Safe to call before configuration.","params":{},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_business_accounts","description":"List accessible Google Business accounts.","params":{},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_business_locations","description":"List only Business Profile locations assigned to the authenticated project.","params":{},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_business_location","description":"Get an assigned Business Profile location. locationId selects among multiple assignments.","params":{"locationId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_business_profile_summary","description":"Summary of the location: title, primary category, phone, website, store code, account name, and location name.","params":{},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_business_profile_location","description":"Full Google Business Profile location payload.","params":{},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_business_profile_attributes","description":"Current location attributes and available attribute definitions.","params":{},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_business_profile_performance","description":"Performance summary for website clicks, calls, direction requests, and views.","params":{"days":{"type":"number","default":28}},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_business_profile_posts","description":"List local posts for the assigned location.","params":{},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_business_posts","description":"List local posts for an assigned location.","params":{"locationId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_business_reviews","description":"List recent reviews for an assigned location without exposing OAuth credentials.","params":{"locationId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_business_media","description":"List media attached to an assigned Business Profile.","params":{"locationId":{"type":"string","optional":true}},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"check_mutation_status","description":"Check a Google Business mutation and its execution result.","params":{"mutationId":{"type":"string","required":true}},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_pending_mutations","description":"List Google Business changes pending human approval.","params":{"limit":{"type":"number","default":20}},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_mutation_history","description":"List Google Business mutation history.","params":{"status":{"type":"string","default":"all"},"limit":{"type":"number","default":20}},"x-mcp":{"channel":"google_business","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/google-business/agent-mutate":{"post":{"summary":"Google Business Profile mutations","description":"Prepare Google Business Profile changes for mandatory human approval. Requires write scope; this endpoint never executes provider writes directly.","tags":["Google Business Profile"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Pending human approval","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"create_business_post","description":"Prepare a local post for human approval.","params":{"locationId":{"type":"string","optional":true},"summary":{"type":"string","required":true},"callToAction":{"type":"object","optional":true},"agentNote":{"type":"string","optional":true}},"x-mcp":{"channel":"google_business","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"update_business_location","description":"Prepare an allowlisted location patch for human approval.","params":{"locationId":{"type":"string","optional":true},"payload":{"type":"object","required":true},"updateMask":{"type":"array","required":true},"agentNote":{"type":"string","optional":true}},"x-mcp":{"channel":"google_business","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"upload_business_media","description":"Prepare media creation from a public HTTPS source URL for human approval.","params":{"locationId":{"type":"string","optional":true},"sourceUrl":{"type":"string","required":true},"mediaFormat":{"type":"string","enum":["PHOTO","VIDEO"],"default":"PHOTO"},"category":{"type":"string","optional":true},"agentNote":{"type":"string","optional":true}},"x-mcp":{"channel":"google_business","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"update_business_profile_description","description":"Prepare a profile description change for human approval.","params":{"locationId":{"type":"string","optional":true},"description":{"type":"string","required":true}},"x-mcp":{"channel":"google_business","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"update_business_profile_basic_info","description":"Prepare a primaryPhone and/or websiteUri change for human approval.","params":{"locationId":{"type":"string","optional":true},"primaryPhone":{"type":"string","optional":true},"websiteUri":{"type":"string","optional":true}},"x-mcp":{"channel":"google_business","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"update_business_profile_hours","description":"Prepare regularHours and/or specialHours changes for human approval.","params":{"locationId":{"type":"string","optional":true},"regularHours":{"type":"object","optional":true},"specialHours":{"type":"object","optional":true}},"x-mcp":{"channel":"google_business","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"update_business_profile_attributes","description":"Prepare attribute changes for human approval.","params":{"locationId":{"type":"string","optional":true},"attributes":{"type":"array","required":true},"attributeMask":{"type":"array","required":true}},"x-mcp":{"channel":"google_business","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"create_business_profile_post","description":"Prepare a local post for human approval (legacy alias).","params":{"locationId":{"type":"string","optional":true},"summary":{"type":"string","required":true},"callToAction":{"type":"object","optional":true}},"x-mcp":{"channel":"google_business","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"update_business_profile_post","description":"Prepare an existing local post update for human approval.","params":{"locationId":{"type":"string","optional":true},"postName":{"type":"string","required":true},"summary":{"type":"string","required":true},"callToAction":{"type":"object","optional":true}},"x-mcp":{"channel":"google_business","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"delete_business_profile_post","description":"Prepare a local post deletion for human approval.","params":{"locationId":{"type":"string","optional":true},"postName":{"type":"string","required":true}},"x-mcp":{"channel":"google_business","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}}]}},"/api/reports/agent-query":{"post":{"summary":"Query structured reports and deterministic rendering capabilities","description":"Project-scoped read tools for report designs, blueprints, the ReportDocumentV1 schema, validation, report state and immutable artifacts.","tags":["Reports"],"security":[{"bearerAuth":[]}],"x-tools":[{"name":"get_report_capabilities","description":"Return supported blocks, chart types, limits, renderer version and effective presets. Agents provide structured content and data; DigitalPublic owns every visual decision.","params":{},"x-mcp":{"channel":"reports","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_report_designs","description":"List designs allowed by project, group or global inheritance. Optionally filter by reportType.","params":{"reportType":{"type":"string","optional":true,"enum":["SEO","GOOGLE_ADS","AEO","ANALYTICS","EXECUTIVE"]}},"x-mcp":{"channel":"reports","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_report_design","description":"Read metadata and published versions for an allowed design. Visual tokens remain controlled by DigitalPublic.","params":{"designId":{"type":"string","required":true}},"x-mcp":{"channel":"reports","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_report_blueprints","description":"List effective report blueprints, versions, minimum blocks and activation state.","params":{},"x-mcp":{"channel":"reports","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_report_document_schema","description":"Return ReportDocumentV1 JSON Schema and deterministic renderer limits.","params":{},"x-mcp":{"channel":"reports","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_report","description":"Read one structured report including contentHash, locked versions, authorization and artifact hashes.","params":{"reportId":{"type":"string","required":true}},"x-mcp":{"channel":"reports","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"validate_report_document","description":"Validate ReportDocumentV1 without saving. Errors include sectionId and blockId plus supported alternatives.","params":{"document":{"type":"object","required":true}},"x-mcp":{"channel":"reports","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/reports/agent-mutate":{"post":{"summary":"Create and update deterministic structured reports","description":"Project-scoped structured report mutations. HTML, CSS, JavaScript, SVG and external image URLs are rejected. Real email sending remains subject to human report and email authorization.","tags":["Reports"],"security":[{"bearerAuth":[]}],"x-tools":[{"name":"create_report_draft","description":"Create a draft from an allowed blueprint and optional design. Submit ReportDocumentV1 content and data, never free-form visual styling.","params":{"blueprintKey":{"type":"string","required":true},"designId":{"type":"string","optional":true},"title":{"type":"string","required":true},"period":{"type":"string","required":true},"description":{"type":"string","optional":true},"document":{"type":"object","required":true},"metricReferences":{"type":"object","optional":true}},"x-mcp":{"channel":"reports","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"update_report_draft","description":"Update an unlocked draft. expectedContentHash is mandatory to protect concurrent human or agent edits.","params":{"reportId":{"type":"string","required":true},"expectedContentHash":{"type":"string","required":true},"document":{"type":"object","optional":true},"title":{"type":"string","optional":true},"period":{"type":"string","optional":true},"description":{"type":"string","optional":true},"data":{"type":"object","optional":true}},"x-mcp":{"channel":"reports","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"set_report_design","description":"Switch an unlocked draft to another allowed design without changing its content.","params":{"reportId":{"type":"string","required":true},"expectedContentHash":{"type":"string","required":true},"designId":{"type":"string","required":true}},"x-mcp":{"channel":"reports","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"preview_report","description":"Render and cache a deterministic preview. The web preview and PDF use the same document and block registry.","params":{"reportId":{"type":"string","required":true}},"x-mcp":{"channel":"reports","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"request_report_authorization","description":"Validate and pre-render the current hash, then request human authorization. Do not consider it authorized until get_report returns authorizedAt and a definitive artifact.","params":{"reportId":{"type":"string","required":true},"expectedContentHash":{"type":"string","required":true}},"x-mcp":{"channel":"reports","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"propose_report_block","description":"Record a missing visual need for administrator review. Use figure immediately when the report cannot wait for development.","params":{"reportId":{"type":"string","optional":true},"title":{"type":"string","required":true},"description":{"type":"string","required":true},"exampleData":{"type":"object","optional":true}},"x-mcp":{"channel":"reports","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}}]}},"/api/reports/upload":{"post":{"summary":"Upload external report file","description":"Exceptional legacy upload for externally produced files. Monthly agent reports should use create_report_draft and ReportDocumentV1 instead.","tags":["Reports"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file","title","period"],"properties":{"file":{"type":"string","format":"binary","description":"Report file in any format (max 20 MB)"},"title":{"type":"string","description":"Report title, e.g. 'Informe Q1 2026 - Agencia X'"},"period":{"type":"string","description":"Reporting period, e.g. 'Enero 2026', 'Q1 2026', '01/01/2026 - 31/03/2026'"},"notes":{"type":"string","description":"Optional description or context. Shown as a snippet in the reports list."},"projectId":{"type":"string","description":"Project ID to associate the report with. Defaults to the user's active project."}}}}}},"responses":{"201":{"description":"Report created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"period":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Validation error (missing file, title, or period; file too large)"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden — CLIENT role cannot upload reports"}},"x-tools":[{"name":"upload_report","description":"Exceptional legacy upload for a report produced outside DigitalPublic. Do not use for recurring monthly agent reports; use create_report_draft.","params":{"filename":{"type":"string","required":true},"contentType":{"type":"string","optional":true,"default":"application/octet-stream"},"title":{"type":"string","required":true},"period":{"type":"string","required":true},"notes":{"type":"string","optional":true},"fileBase64":{"type":"string","required":true}},"x-mcp":{"channel":"reports","effect":"write","requiredScope":"write","approval":"none","requestShape":"multipart_upload"}}]}},"/api/reports/omit-send/{reportId}":{"post":{"summary":"Omit report email sending","description":"Marks a generated or uploaded report as no longer pending email sending while preserving it in the report history. Requires write scope.","tags":["Reports"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"reportId","required":true,"schema":{"type":"string"},"description":"Report ID"}],"responses":{"200":{"description":"Report send omitted","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"report":{"type":"object","properties":{"id":{"type":"string"},"sendOmittedAt":{"type":"string","format":"date-time","nullable":true}}}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Report not found"}},"x-tools":[{"name":"omit_report_send","description":"Mark a report as no longer pending email sending without deleting it from report history.","params":{"reportId":{"type":"string","required":true}},"x-mcp":{"channel":"reports","effect":"write","requiredScope":"write","approval":"none","requestShape":"direct_body"}}]}},"/api/reports/file/{reportId}":{"get":{"summary":"Download external report file","description":"Returns the binary file for an uploaded report.","tags":["Reports"],"parameters":[{"in":"path","name":"reportId","required":true,"schema":{"type":"string"},"description":"Report ID returned by /api/reports/upload"}],"responses":{"200":{"description":"Report file","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Report not found or not an uploaded file"}},"x-tools":[{"name":"get_report_file","description":"Download an uploaded report file. The MCP returns filename, contentType, and base64 content.","params":{"reportId":{"type":"string","required":true}},"x-mcp":{"channel":"reports","effect":"read","requiredScope":"read","approval":"none","requestShape":"file_download"}}]}},"/api/creatives":{"get":{"summary":"List project creative files","description":"List stored project creative files with session or bearer authentication. Session callers select an authorized project with projectId or the active-project header.","tags":["Creatives"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"projectId","schema":{"type":"string"},"description":"Required with global dpa_ tokens and when the session has no active-project header."},{"in":"query","name":"kind","schema":{"type":"string","enum":["image","video","document"]}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Creative files ordered from newest to oldest."},"403":{"description":"Project access denied."}}}},"/api/creatives/upload":{"post":{"summary":"Upload creative file (video/image)","description":"Upload a campaign creative (MP4/MOV/WebM video or JPG/PNG/GIF/WebP image) as multipart/form-data. Max 200 MB by default. Video metadata (duration, dimensions, codec, audio) is parsed automatically. Requires write scope.","tags":["Creatives"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"Creative file (max 200 MB)"},"name":{"type":"string","description":"Display name for the creative. Defaults to the filename."},"projectId":{"type":"string","description":"Required with global dpa_ tokens; dpk_ keys infer the project."}}}}}},"responses":{"201":{"description":"Creative stored; returns fileId, url, mimeType, sizeBytes, sha256, and parsed video metadata."},"400":{"description":"Validation error (missing file, unsupported type)"},"413":{"description":"File exceeds the size limit"}},"x-tools":[{"name":"upload_creative_file","description":"Upload a local creative file (video/image) from base64 content. The MCP converts fileBase64 into multipart/form-data for /api/creatives/upload. Returns fileId, url, sha256 and parsed video metadata. For large files prefer import_creative_file with a remote URL.","params":{"filename":{"type":"string","required":true},"contentType":{"type":"string","optional":true,"default":"application/octet-stream"},"name":{"type":"string","optional":true,"description":"Display name; defaults to filename."},"fileBase64":{"type":"string","required":true}},"x-mcp":{"channel":"creatives","effect":"write","requiredScope":"write","approval":"none","requestShape":"multipart_upload"}}]}},"/api/creatives/generate":{"post":{"summary":"Queue AI image generation","description":"Persist an asynchronous image-generation job and return 202 immediately. Poll the returned statusUrl until completed or failed. A completed job includes the CreativeFile usable in landing pages and blog Markdown. Requests are idempotent by explicit key, or by name when no key is supplied.","tags":["Creatives"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["prompt"],"properties":{"prompt":{"type":"string","description":"Image description (max 4000 chars). Be specific: subject, style, lighting, composition."},"size":{"type":"string","enum":["1024x1024","1536x1024","1024x1536","auto"],"default":"auto"},"quality":{"type":"string","enum":["low","medium","high"],"default":"high"},"name":{"type":"string","description":"Display name for the creative. Defaults to the prompt."},"idempotencyKey":{"type":"string","maxLength":200,"description":"Optional caller-stable retry key. The same key must keep the same payload."},"projectId":{"type":"string","description":"Required with global dpa_ tokens; dpk_ keys infer the project."}}}}}},"responses":{"202":{"description":"Job accepted or idempotently reused; returns jobId, status, statusUrl, reused, and Retry-After."},"409":{"description":"Idempotency key was already used with a different payload."},"503":{"description":"OPENAI_API_KEY not configured in this environment"}},"x-tools":[{"name":"generate_creative_image","description":"Queue AI image generation and return immediately with jobId and statusUrl. Poll get_creative_generation_status until completed; the completed payload includes the CreativeFile fileId.","params":{"prompt":{"type":"string","required":true},"size":{"type":"string","optional":true,"default":"auto","description":"1024x1024 | 1536x1024 | 1024x1536 | auto"},"quality":{"type":"string","optional":true,"default":"high"},"name":{"type":"string","optional":true},"idempotencyKey":{"type":"string","optional":true,"description":"Stable retry key, max 200 characters."}},"x-mcp":{"channel":"creatives","effect":"write","requiredScope":"write","approval":"none","requestShape":"direct_body"}}]}},"/api/creatives/generate/{jobId}":{"get":{"summary":"Get creative generation status","description":"Read one project-scoped generation job. Running responses include Retry-After; completed responses include the stored CreativeFile.","tags":["Creatives"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"jobId","required":true,"schema":{"type":"string"}},{"in":"query","name":"projectId","schema":{"type":"string"},"description":"Required with global dpa_ tokens."}],"responses":{"200":{"description":"Job status: queued, running, completed, or failed."},"404":{"description":"Job not found in the selected project."}},"x-tools":[{"name":"get_creative_generation_status","description":"Poll an asynchronous creative generation job. When status is completed, creative.fileId is ready for landing blocks or blog Markdown.","params":{"jobId":{"type":"string","required":true}},"x-mcp":{"channel":"creatives","effect":"read","requiredScope":"read","approval":"none","requestShape":"json_get"}}]}},"/api/creatives/file/{fileId}":{"get":{"summary":"Download creative file","description":"Returns the binary of a stored creative for the project.","tags":["Creatives"],"parameters":[{"in":"path","name":"fileId","required":true,"schema":{"type":"string"},"description":"Creative fileId returned by upload_creative_file/import_creative_file"}],"responses":{"200":{"description":"Creative file","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Creative not found"},"410":{"description":"Binary no longer available in storage"}},"x-tools":[{"name":"download_creative_file","description":"Download a stored creative file. The MCP returns filename, contentType, and base64 content.","params":{"fileId":{"type":"string","required":true}},"x-mcp":{"channel":"creatives","effect":"read","requiredScope":"read","approval":"none","requestShape":"file_download"}}]}},"/api/creatives/agent-query":{"post":{"summary":"Creative asset management and YouTube upload","description":"Manage campaign creatives (videos/images): list, import from URL or base64, validate videos per Google Ads channel, and upload videos to the project's connected YouTube channel as unlisted. Agents use this before creating YOUTUBE_VIDEO assets and Demand Gen video ads via /api/google-ads/agent-mutate.","tags":["Creatives"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}}},"x-tools":[{"name":"list_creative_files","description":"List the project's creative files (videos/images) with safe metadata, parsed video info, sha256 and youtubeVideoId when already uploaded to YouTube. Read-only.","params":{"kind":{"type":"string","optional":true,"enum":["video","image"]},"limit":{"type":"number","optional":true,"default":50,"description":"Clamped between 1 and 100."}},"x-mcp":{"channel":"creatives","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_creative_file","description":"Get one creative file with metadata and availability on disk. Read-only.","params":{"fileId":{"type":"string","required":true}},"x-mcp":{"channel":"creatives","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"import_creative_file","description":"Import a creative from a public remote URL (streamed with SSRF protections and a 200 MB cap) or from base64 content. For local files use the multipart tool upload_creative_file instead. Requires write scope. Video metadata is parsed automatically.","params":{"source":{"type":"object","required":true,"description":"{ type: 'remote_url' | 'base64', value: string }"},"name":{"type":"string","optional":true},"mimeType":{"type":"string","optional":true,"description":"Required with base64 (e.g. video/mp4); with remote_url it defaults to the response content-type."}},"x-mcp":{"channel":"creatives","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"validate_video_creative","description":"Validate a stored video against a Google Ads channel target. Returns metadata (width, height, durationSeconds, aspectRatio, codec, hasAudio, bitrateKbps), blocking errors and actionable warnings. Read-only.","params":{"fileId":{"type":"string","required":true},"target":{"type":"string","optional":true,"enum":["DEMAND_GEN_VIDEO","YOUTUBE_AD","PERFORMANCE_MAX_VIDEO"],"default":"DEMAND_GEN_VIDEO"}},"x-mcp":{"channel":"creatives","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"delete_creative_file","description":"Soft-delete a creative file and remove its binary from storage. Requires write scope.","params":{"fileId":{"type":"string","required":true}},"x-mcp":{"channel":"creatives","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"get_youtube_connection_status","description":"Check whether the project has a YouTube channel connected via OAuth (channelId, channelTitle, oauthConnectedAt). Read-only. If not connected, returns instructions: an ADMIN must visit /api/youtube/oauth/start?projectId=...","params":{},"x-mcp":{"channel":"creatives","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"youtube_upload_video","description":"Upload a stored video creative to the project's connected YouTube channel using the resumable upload protocol. Defaults to privacyStatus 'unlisted'. Returns youtubeVideoId, youtubeUrl, privacyStatus and processingStatus, and stores youtubeVideoId on the creative. Requires write scope. Fails with an actionable YOUTUBE_NOT_CONNECTED error when no channel is connected, and with a reconnect message when the OAuth token expired.","params":{"fileId":{"type":"string","required":true},"title":{"type":"string","required":true},"description":{"type":"string","optional":true},"privacyStatus":{"type":"string","optional":true,"enum":["unlisted","private","public"],"default":"unlisted"},"madeForKids":{"type":"boolean","optional":true,"default":false},"tags":{"type":"array","optional":true},"language":{"type":"string","optional":true,"description":"BCP-47 code, e.g. 'es'."}},"x-mcp":{"channel":"creatives","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"get_youtube_video_status","description":"Check YouTube processing status for an uploaded video (by youtubeVideoId or by the creative fileId). Returns uploadStatus, processingStatus, progress and failure/rejection reasons. Read-only.","params":{"youtubeVideoId":{"type":"string","optional":true},"fileId":{"type":"string","optional":true,"description":"Creative already uploaded with youtube_upload_video."}},"x-mcp":{"channel":"creatives","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}}]}},"/api/agent/processes":{"post":{"summary":"Verifiable process work queue","description":"Poll, start, claim and submit nodes in project-scoped versioned workflows. Agents complete nodes, but only DigitalPublic advances or finishes the process after deterministic verification.","tags":["Processes"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["tool"],"properties":{"tool":{"type":"string","enum":["list_process_work","start_process_run","get_process_run","claim_process_node","heartbeat_process_node","submit_process_node_result"]},"params":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"Process operation succeeded."},"409":{"description":"Claim conflict, expired lease, invalid state, or workflow-managed operation."}},"x-tools":[{"name":"list_process_work","description":"List due process triggers and prepared agent nodes for this project. The call also safely reconciles expired reservations and human waits.","params":{},"x-mcp":{"channel":"processes","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"start_process_run","description":"Atomically start a due process task. Repeating the same scheduled trigger returns the same run. Manual processes require a stable idempotencyKey.","params":{"taskId":{"type":"string","required":true},"idempotencyKey":{"type":"string","optional":true}},"x-mcp":{"channel":"processes","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"get_process_run","description":"Read the pinned graph version, current state, node attempts, real verification evidence, events and blockers.","params":{"processRunId":{"type":"string","required":true}},"x-mcp":{"channel":"processes","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"claim_process_node","description":"Atomically reserve one prepared node for 30 minutes. Returns a one-time opaque claimToken required for heartbeat and submission.","params":{"nodeRunId":{"type":"string","required":true}},"x-mcp":{"channel":"processes","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"heartbeat_process_node","description":"Extend an active reservation by another 30 minutes without exceeding the node timeout.","params":{"nodeRunId":{"type":"string","required":true},"claimToken":{"type":"string","required":true}},"x-mcp":{"channel":"processes","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"submit_process_node_result","description":"Submit structured node success or failure with evidence. This completes only the claimed node. DigitalPublic performs verification and decides the process transition.","params":{"nodeRunId":{"type":"string","required":true},"claimToken":{"type":"string","required":true},"idempotencyKey":{"type":"string","required":true},"result":{"type":"string","required":true,"enum":["success","failure"]},"output":{"type":"object","optional":true},"evidence":{"type":"object","optional":true},"errorMessage":{"type":"string","optional":true}},"x-mcp":{"channel":"processes","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}}]}},"/api/agent/schedule":{"post":{"summary":"External and embedded agent task scheduling","description":"List and manage project tasks/subtasks. EXTERNAL tasks are executed by the connected agent runtime. EMBEDDED task drafts may be proposed through this API, but require human activation before DigitalPublic's internal scheduler can run them. complete_execution rejects ambiguous completions from external agents.","tags":["Scheduling"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["tool"],"properties":{"tool":{"type":"string","enum":["list_tasks","list_due_tasks","get_task","get_task_by_url","list_embedded_runs","create_task","create_embedded_task_draft","update_task","delete_task","postpone_task","start_execution","append_task_message","append_execution_message","update_task_message","delete_task_message","complete_execution"]},"params":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"Success"}},"x-tools":[{"name":"list_tasks","description":"List project tasks and subtasks.","params":{},"x-mcp":{"channel":"schedule","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_due_tasks","description":"List active tasks that are due or require a new execution date. Every handled task must finish with complete_execution or postpone_task.","params":{},"x-mcp":{"channel":"schedule","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_task","description":"Get task detail with recent executions, task messages, and the canonical taskUrl.","params":{"taskId":{"type":"string","required":true}},"x-mcp":{"channel":"schedule","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"get_task_by_url","description":"Resolve a copied DigitalPublic task URL and return the task detail with messages, instructions, executions, and canonical taskUrl. Use this when the user says only 'Ejecuta esta tarea' and provides the URL.","params":{"taskUrl":{"type":"string","required":true}},"x-mcp":{"channel":"schedule","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"list_embedded_runs","description":"List recent executions performed by DigitalPublic's embedded agent runtime for this project.","params":{"status":{"type":"string","optional":true,"enum":["QUEUED","RUNNING","WAITING_APPROVAL","WAITING_PROVIDER","BLOCKED_QUOTA","SUCCEEDED","FAILED","CANCELLED"]},"limit":{"type":"number","optional":true}},"x-mcp":{"channel":"schedule","effect":"read","requiredScope":"read","approval":"none","requestShape":"tool_params"}},{"name":"create_task","description":"Create a task for the external agent runtime. Requires write scope.","params":{"title":{"type":"string","required":true},"description":{"type":"string","optional":true},"instructions":{"type":"string","optional":true},"parentId":{"type":"string","optional":true},"status":{"type":"string","optional":true,"enum":["active","paused","completed"]},"frequency":{"type":"string","optional":true,"enum":["manual","daily","weekly","every_two_weeks","monthly","every_two_months","quarterly","semiannual","annual","custom"]},"nextRunAt":{"type":"string","optional":true,"description":"Authoritative ISO8601 execution date."},"reason":{"type":"string","optional":true,"description":"Reason recorded in the scheduling audit."},"sortOrder":{"type":"number","optional":true},"serviceArea":{"type":"string","optional":true},"clientVisible":{"type":"boolean","optional":true,"default":false},"clientTitle":{"type":"string","optional":true},"clientSummary":{"type":"string","optional":true}},"x-mcp":{"channel":"schedule","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"create_embedded_task_draft","description":"Propose a scheduled task for DigitalPublic's embedded agent. It is always paused and in DRAFT state until a human activates it. Requires write scope.","params":{"title":{"type":"string","required":true},"description":{"type":"string","optional":true},"instructions":{"type":"string","required":true},"frequency":{"type":"string","optional":true,"enum":["manual","daily","weekly","every_two_weeks","monthly","every_two_months","quarterly","semiannual","annual","custom"]},"nextRunAt":{"type":"string","optional":true,"description":"Proposed first execution date. A human may change it while activating the draft."},"timezone":{"type":"string","optional":true,"description":"IANA timezone."},"scheduleRule":{"type":"object","optional":true},"serviceArea":{"type":"string","optional":true},"aiProfile":{"type":"string","optional":true,"enum":["ECONOMY","STANDARD","DEEP"],"description":"Model and cost profile. Defaults to STANDARD."},"reason":{"type":"string","optional":true}},"x-mcp":{"channel":"schedule","effect":"write","requiredScope":"write","approval":"human","requestShape":"tool_params"}},{"name":"update_task","description":"Update project task scheduling, content, status, order, or parentId to move it in the task tree. Requires write scope.","params":{"taskId":{"type":"string","required":true},"parentId":{"type":"string","optional":true,"description":"New parent task id. Send null or empty string to move the task to the root."},"title":{"type":"string","optional":true},"description":{"type":"string","optional":true},"instructions":{"type":"string","optional":true},"status":{"type":"string","optional":true,"enum":["active","paused","completed"]},"frequency":{"type":"string","optional":true,"enum":["manual","daily","weekly","every_two_weeks","monthly","every_two_months","quarterly","semiannual","annual","custom"]},"nextRunAt":{"type":"string","optional":true,"description":"Authoritative ISO8601 date selected by the agent or human."},"reason":{"type":"string","optional":true,"description":"Reason recorded with the previous and new schedule state."},"sortOrder":{"type":"number","optional":true},"serviceArea":{"type":"string","optional":true},"clientVisible":{"type":"boolean","optional":true},"clientTitle":{"type":"string","optional":true},"clientSummary":{"type":"string","optional":true}},"x-mcp":{"channel":"schedule","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"delete_task","description":"Delete a project task and its subtasks/executions. Requires write scope.","params":{"taskId":{"type":"string","required":true}},"x-mcp":{"channel":"schedule","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"postpone_task","description":"Postpone a task that cannot be completed yet. Records a deferred execution and updates nextRunAt without changing frequency. Requires write scope.","params":{"taskId":{"type":"string","required":true},"nextRunAt":{"type":"string","required":true,"description":"Future ISO8601 date for the next check."},"reason":{"type":"string","required":true}},"x-mcp":{"channel":"schedule","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"start_execution","description":"Start a task execution. Requires write scope.","params":{"taskId":{"type":"string","required":true},"scheduledFor":{"type":"string","optional":true},"clientVisible":{"type":"boolean","optional":true},"clientSummary":{"type":"string","optional":true},"evidence":{"type":"object","optional":true}},"x-mcp":{"channel":"schedule","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"append_task_message","description":"Append an agent message to a task without requiring an execution. Content supports Markdown/GFM. Messages default to internal; set visibility=client only for content approved for the partner portal. Requires write scope.","params":{"taskId":{"type":"string","required":true},"content":{"type":"string","required":true,"description":"Markdown/GFM text to render in the task message timeline."},"messageKind":{"type":"string","optional":true,"enum":["client","blobic","note"]},"visibility":{"type":"string","optional":true,"enum":["internal","client"],"default":"internal"}},"x-mcp":{"channel":"schedule","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"append_execution_message","description":"Append an agent message to an execution. Messages default to internal. Requires write scope.","params":{"executionId":{"type":"string","required":true},"content":{"type":"string","required":true,"description":"Markdown/GFM text to render in the task message timeline."},"messageKind":{"type":"string","optional":true,"enum":["client","blobic","note"]},"visibility":{"type":"string","optional":true,"enum":["internal","client"],"default":"internal"}},"x-mcp":{"channel":"schedule","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"update_task_message","description":"Update content, category, or internal/client visibility. Requires write scope. Author fields are immutable.","params":{"messageId":{"type":"string","required":true},"content":{"type":"string","optional":true},"messageKind":{"type":"string","optional":true,"enum":["client","blobic","note"]},"visibility":{"type":"string","optional":true,"enum":["internal","client"]}},"x-mcp":{"channel":"schedule","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"delete_task_message","description":"Delete a task or execution message. Requires write scope.","params":{"messageId":{"type":"string","required":true}},"x-mcp":{"channel":"schedule","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}},{"name":"complete_execution","description":"Complete, fail, or skip an execution. A next-run decision is mandatory; ambiguous completions return NEXT_RUN_DECISION_REQUIRED. Internal summary/error stay private; clientSummary/evidence are published only when clientVisible=true. Requires write scope.","params":{"executionId":{"type":"string","required":true},"status":{"type":"string","required":true,"enum":["completed","failed","skipped"]},"summary":{"type":"string","optional":true},"errorMessage":{"type":"string","optional":true},"clientVisible":{"type":"boolean","optional":true},"clientSummary":{"type":"string","optional":true},"evidence":{"type":"object","optional":true},"nextRunAt":{"type":"string","optional":true,"description":"Future ISO8601 date selected by the agent. Mutually exclusive with nextRunDecision."},"nextRunDecision":{"type":"string","optional":true,"enum":["use_frequency","close"],"description":"Required when nextRunAt is omitted. use_frequency explicitly applies a predefined cadence; close archives the task."},"nextRunReason":{"type":"string","optional":true,"description":"Required when nextRunDecision='close' to record why no future execution is needed."}},"x-mcp":{"channel":"schedule","effect":"write","requiredScope":"write","approval":"none","requestShape":"tool_params"}}]}}}}