{"openapi":"3.1.0","info":{"title":"Privatus Analytics API","version":"1.0.0","description":"Every page in Privatus Analytics is also an API endpoint: add .json to the URL and send an API token as a Bearer token. Most of them are MCP tools too."},"servers":[{"url":"https://privatusanalytics.com"}],"security":[{"bearer":[]}],"tags":[{"name":"API tokens"},{"name":"Account"},{"name":"Ad creatives"},{"name":"Ad placements"},{"name":"Affiliate program"},{"name":"Alerts"},{"name":"Analytics"},{"name":"Assistant"},{"name":"Audit log"},{"name":"Billing"},{"name":"Bot detection"},{"name":"Campaigns"},{"name":"Channel rules"},{"name":"Collection"},{"name":"Crawlers"},{"name":"Dashboards"},{"name":"Documentation"},{"name":"Domain Rating"},{"name":"Email reports"},{"name":"Email settings"},{"name":"Events"},{"name":"Experiments"},{"name":"Exports"},{"name":"Forms"},{"name":"Funnels"},{"name":"Goals"},{"name":"Help and feedback"},{"name":"Imports"},{"name":"Live"},{"name":"Members"},{"name":"Mobile app"},{"name":"Notes"},{"name":"Notification channels"},{"name":"Performance"},{"name":"Plans"},{"name":"Private feedback"},{"name":"Removal requests"},{"name":"Rewards"},{"name":"Roles"},{"name":"SCIM"},{"name":"SSO"},{"name":"Search"},{"name":"Segments"},{"name":"Sharing"},{"name":"Site audit"},{"name":"Sites"},{"name":"Sponsor report"},{"name":"Sponsor reports"},{"name":"Status pages"},{"name":"Subscriptions"},{"name":"Surveys"},{"name":"Testimonial analytics"},{"name":"Testimonial brand kit"},{"name":"Testimonial collections"},{"name":"Testimonial companies"},{"name":"Testimonial custom domain requests"},{"name":"Testimonial custom properties"},{"name":"Testimonial duplicates"},{"name":"Testimonial images"},{"name":"Testimonial import runs"},{"name":"Testimonial import sources"},{"name":"Testimonial languages"},{"name":"Testimonial media"},{"name":"Testimonial mentions"},{"name":"Testimonial migrations"},{"name":"Testimonial people"},{"name":"Testimonial purchase connections"},{"name":"Testimonial request recipients"},{"name":"Testimonial requests"},{"name":"Testimonial saved views"},{"name":"Testimonial spreadsheet imports"},{"name":"Testimonial tags"},{"name":"Testimonial translations"},{"name":"Testimonial trash"},{"name":"Testimonial undo list"},{"name":"Testimonials"},{"name":"Tracking"},{"name":"Traffic rules"},{"name":"Uptime"},{"name":"Walls of Love"},{"name":"Warehouse sync"},{"name":"Webhooks"},{"name":"Website"},{"name":"Widgets"},{"name":"Workspaces"}],"paths":{"/workspaces/{workspace_id}/api_tokens.json":{"post":{"operationId":"api_tokens_create","summary":"Create an API token (the token is returned once)","description":"Creates an API token for the calling member in a workspace and returns the secret exactly once in the token field. Copy it immediately, it cannot be read again and a lost token must be revoked and recreated. A token can only narrow what its member may do. permissions defaults to all of the member's own permissions when omitted (an explicit empty list is refused, and asking for a permission you lack is an error). site_ids takes public site ids (pa_...) and restricts the token to those sites, and when empty the token works for every site its member can access (or keeps the site list of the token making this call). expires_at is optional ISO 8601 and must be in the future and at most 3 years away, omit it for a token that never expires. allowed_ips limits the token to those IPs or CIDR ranges. A token making this call needs tokens.manage. A workspace that requires two-factor authentication refuses tokens for members without a second factor of their own. Returns the same fields as api_tokens_list plus token.","tags":["API tokens"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"token":{"anyOf":[{"type":"string","description":"The token itself: only returned when created"},{"type":"null"}]},"token_prefix":{"type":"string","description":"First characters, to recognize the token"},"owner":{"type":"string","description":"Email of the member who owns it"},"permissions":{"type":"array","items":{"type":"string"}},"site_ids":{"type":"array","items":{"type":"string"},"description":"Restricted to these sites (empty = all)"},"allowed_ips":{"type":"array","items":{"type":"string"}},"oauth_client":{"anyOf":[{"type":"string","description":"MCP client that received it"},{"type":"null"}]},"status":{"type":"string","description":"active, expired or revoked"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-token-permission":"tokens.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"A label to recognize the token by, for example CI deploys. Required.","examples":["CI deploys"]},"permissions":{"type":"array","items":{"type":"string","enum":["analytics.read","analytics.export","content.write","sites.manage","uptime.manage","members.manage","tokens.manage","billing.manage","workspace.manage"]},"description":"Permission names to grant, from analytics.read, analytics.export, content.write, sites.manage, uptime.manage, members.manage, tokens.manage, billing.manage and workspace.manage. Must be a subset of your own. Omit to grant all of yours. An empty list is refused."},"site_ids":{"type":"array","items":{"type":"string"},"description":"Public site ids (pa_..., from sites_list) the token may access. Empty means every site its member can access.","default":[]},"expires_at":{"type":"string","format":"date-time","description":"Expiry as an ISO 8601 timestamp, for example 2027-01-31T00:00:00Z. Must be in the future and at most 3 years away. Omit for a token that never expires."},"allowed_ips":{"type":"array","items":{"type":"string"},"description":"IP addresses or CIDR ranges (for example 203.0.113.7 or 198.51.100.0/24) the token accepts requests from. Empty means any address.","default":[]}},"required":["name"]}}}}},"get":{"operationId":"api_tokens_list","summary":"List API tokens","description":"Lists the API tokens of a workspace, newest first and paginated. Without the tokens.manage permission you only see your own tokens, with it you see every member's. Revoked and expired tokens are hidden unless include_revoked is true. Each item has id (uuid, used by api_tokens_delete), name, token_prefix (the first characters, for recognizing a token), owner (the member's email), permissions (names such as analytics.read), site_ids (public site ids pa_..., an empty array means every site the owner can access), allowed_ips, oauth_client (the connected app's name when the token was issued through OAuth, otherwise null), status (active, expired or revoked), expires_at, last_used_at, revoked_at and created_at. The secret itself is never returned here, token is always null in a list. It is only shown once by api_tokens_create.","tags":["API tokens"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"include_revoked","in":"query","required":false,"schema":{"type":"boolean","description":"Set true to also list revoked and expired tokens. Default false.","default":false}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"token":{"anyOf":[{"type":"string","description":"The token itself: only returned when created"},{"type":"null"}]},"token_prefix":{"type":"string","description":"First characters, to recognize the token"},"owner":{"type":"string","description":"Email of the member who owns it"},"permissions":{"type":"array","items":{"type":"string"}},"site_ids":{"type":"array","items":{"type":"string"},"description":"Restricted to these sites (empty = all)"},"allowed_ips":{"type":"array","items":{"type":"string"}},"oauth_client":{"anyOf":[{"type":"string","description":"MCP client that received it"},{"type":"null"}]},"status":{"type":"string","description":"active, expired or revoked"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"api_tokens_list"}},"/workspaces/{workspace_id}/api_tokens/{id}.json":{"delete":{"operationId":"api_tokens_delete","summary":"Revoke an API token","description":"Revokes an API token immediately and permanently. Requests that use it fail from then on, and a revoked token cannot be restored, create a new one instead. The token record stays in the list with status revoked (use api_tokens_list with include_revoked to see it), and revoking an already revoked token changes nothing. Take the id (a uuid) from api_tokens_list. You can revoke your own tokens, revoking someone else's needs tokens.manage and reach over every site the token covers. A token calling this needs tokens.manage. Returns the revoked token without its secret.","tags":["API tokens"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by api_tokens_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"token":{"anyOf":[{"type":"string","description":"The token itself: only returned when created"},{"type":"null"}]},"token_prefix":{"type":"string","description":"First characters, to recognize the token"},"owner":{"type":"string","description":"Email of the member who owns it"},"permissions":{"type":"array","items":{"type":"string"}},"site_ids":{"type":"array","items":{"type":"string"},"description":"Restricted to these sites (empty = all)"},"allowed_ips":{"type":"array","items":{"type":"string"}},"oauth_client":{"anyOf":[{"type":"string","description":"MCP client that received it"},{"type":"null"}]},"status":{"type":"string","description":"active, expired or revoked"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-token-permission":"tokens.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/account.json":{"get":{"operationId":"account_get","summary":"Get your profile and preferences","description":"Returns the signed-in member's own profile and preferences. Use it to read settings before changing them with account_update. This is about the person, not a workspace. Workspace plan and invoices are under billing_get. Fields are email, unconfirmed_email (set while an email change awaits confirmation, otherwise null), name (nullable), theme (system, light or dark), default_landing (sites or last_site), locale (language code for the signed-in app), timezone (IANA name, nullable), shortcuts_enabled, reduce_motion, product_emails, site_audit_emails, marketing_emails, newsletter (all booleans where true means subscribed), two_factor (boolean), passkeys (count of registered passkeys) and created_at (ISO 8601). A session opened only through a workspace identity provider sees just email and the display settings.","tags":["Account"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"email":{"type":"string"},"email_verified":{"type":"boolean","description":"Whether the person has proven the email address is theirs. A client that logs people in with this account relies on it"},"unconfirmed_email":{"anyOf":[{"type":"string","description":"New email awaiting confirmation"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"theme":{"type":"string"},"default_landing":{"type":"string"},"locale":{"type":"string","description":"Language code of the app for this account (en by default)"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}]},"shortcuts_enabled":{"type":"boolean"},"reduce_motion":{"type":"boolean"},"menu_stars":{"type":"array","items":{"type":"string"},"description":"The sidebar items this account starred, as keys such as site.experiments or workspace.billing"},"holiday_looks":{"type":"array","items":{"type":"string"},"description":"The holiday looks this account sees in the app, as keys such as halloween or christmas"},"product_emails":{"type":"boolean"},"site_audit_emails":{"type":"boolean","description":"Whether site audit summary emails may be sent. Off here turns them off for every site"},"marketing_emails":{"type":"boolean","description":"Whether marketing emails (drip campaigns) may be sent. false after an unsubscribe"},"newsletter":{"type":"boolean"},"two_factor":{"type":"boolean"},"passkeys":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"account_get"},"patch":{"operationId":"account_update","summary":"Update your profile and preferences","description":"Updates the signed-in member's own profile, display preferences and email subscriptions. Only the inputs you send change, everything else stays as it is. Changing email does not take effect at once. A confirmation email is sent to the new address (rate limited) and unconfirmed_email shows the pending address until it is confirmed. API tokens cannot change the email address and cannot turn marketing_emails back on after an unsubscribe, both need a signed-in browser. Turning marketing_emails off is allowed. Sessions opened by a workspace identity provider may only change the display settings (theme, default_landing, locale, timezone, shortcuts_enabled, reduce_motion). Returns the updated account in the same shape as account_get. This does not delete the account and cannot change workspace settings.","tags":["Account"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"email":{"type":"string"},"email_verified":{"type":"boolean","description":"Whether the person has proven the email address is theirs. A client that logs people in with this account relies on it"},"unconfirmed_email":{"anyOf":[{"type":"string","description":"New email awaiting confirmation"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"theme":{"type":"string"},"default_landing":{"type":"string"},"locale":{"type":"string","description":"Language code of the app for this account (en by default)"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}]},"shortcuts_enabled":{"type":"boolean"},"reduce_motion":{"type":"boolean"},"menu_stars":{"type":"array","items":{"type":"string"},"description":"The sidebar items this account starred, as keys such as site.experiments or workspace.billing"},"holiday_looks":{"type":"array","items":{"type":"string"},"description":"The holiday looks this account sees in the app, as keys such as halloween or christmas"},"product_emails":{"type":"boolean"},"site_audit_emails":{"type":"boolean","description":"Whether site audit summary emails may be sent. Off here turns them off for every site"},"marketing_emails":{"type":"boolean","description":"Whether marketing emails (drip campaigns) may be sent. false after an unsubscribe"},"newsletter":{"type":"boolean"},"two_factor":{"type":"boolean"},"passkeys":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"account_update","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Your name"},"email":{"type":"string","description":"New login email address. Not applied until the confirmation email sent to it is confirmed, and not allowed with an API token."},"theme":{"type":"string","description":"Color theme of the signed-in app.","enum":["system","light","dark"]},"default_landing":{"type":"string","description":"Page shown after signing in. sites is the site list, last_site reopens the last site you viewed.","enum":["sites","last_site"]},"locale":{"type":"string","description":"Language of the signed-in app, as a language code such as en, de or fr. Public pages, emails and the API stay as they are.","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]},"timezone":{"type":"string","description":"IANA timezone name, for example Europe/Berlin or America/New_York. Unknown names are rejected."},"shortcuts_enabled":{"type":"boolean","description":"Keyboard shortcuts"},"reduce_motion":{"type":"boolean","description":"Reduce animations"},"product_emails":{"type":"boolean","description":"Product update and tips emails"},"site_audit_emails":{"type":"boolean","description":"Site audit summary emails, for every site"},"marketing_emails":{"type":"boolean","description":"true or false. false unsubscribes from marketing emails such as onboarding tips. Turning them back on after an unsubscribe is refused for API tokens and needs a signed-in browser."},"newsletter":{"type":"boolean","description":"Monthly newsletter"},"menu_stars":{"type":"array","items":{"type":"string"},"description":"The sidebar items starred for this account, shown first in the menu. A list of keys such as site.experiments or workspace.billing: site. or workspace. followed by the item (site.overview, site.goals, workspace.members). The list replaces the current one, and an empty list removes every star."},"holiday_looks":{"type":"array","items":{"type":"string"},"description":"The holiday looks to show in the app, as a list of keys: valentines, halloween, christmas, new_year. The list replaces the current one, and an empty list keeps the normal look all year."}}}}}}}},"/sites/{site_id}/experiments/ads/{ad_placement_id}/creatives.json":{"post":{"operationId":"ad_creatives_create","summary":"Add a creative to an ad placement","description":"Adds an image of the placement's shape (at least its size, twice the size looks sharpest) and the address a click goes to. Send the image as a multipart file, or image_url to have it downloaded. It is processed in the background, so poll ad_creatives_get until state is ready. A schedule, devices and paths are Pro and up. Requires content.write.","tags":["Ad creatives"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"ad_placement_id","in":"path","required":true,"description":"Ad placement id (adp_...), from ad_placements_list","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Creative id, e.g. adc_7Q2K9XH3AB"},"placement_id":{"type":"string","description":"Its placement (adp_...)"},"name":{"type":"string","description":"Internal name"},"alt_text":{"type":"string","description":"What the image says, for screen readers"},"destination_url":{"type":"string","description":"Where a click goes, as set"},"link":{"type":"string","description":"Where a click goes, with the campaign parameters when utm is on"},"utm":{"type":"boolean","description":"Whether campaign parameters are added to the link"},"weight":{"type":"integer","description":"Share of the views in the rotation"},"active":{"type":"boolean","description":"Whether it is in the rotation"},"starts_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it starts to show, or null"},{"type":"null"}]},"ends_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it stops showing, or null"},{"type":"null"}]},"devices":{"type":"array","items":{"type":"string"},"description":"Only on these devices. Empty means all"},"paths":{"type":"array","items":{"type":"string"},"description":"Only on these pages. Empty means all"},"state":{"type":"string","description":"processing, ready or failed"},"error":{"anyOf":[{"type":"string","description":"Why the image could not be used, or null: image_size, image_type, image_too_large or processing_failed"},{"type":"null"}]},"image_url":{"anyOf":[{"type":"string","description":"The image at the placement's size, or null before it is ready"},{"type":"null"}]},"image_2x_url":{"anyOf":[{"type":"string","description":"The image at twice the size, or null"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width of the image in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height of the image in pixels"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"impressions":{"type":"integer","description":"Times a creative was shown in a slot the page displayed"},"viewable":{"type":"integer","description":"Impressions seen: half of the creative on screen for one second (30% for a big one)"},"clicks":{"type":"integer","description":"Clicks, one per creative and visitor address in ten minutes"},"ctr":{"type":"number","description":"Clicks per viewable impression, as a percent"}},"description":"The period's numbers, on ad_placements_get"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was added"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"ad_creatives_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Internal name, such as Spring sale, max 120 characters"},"destination_url":{"type":"string","description":"Where a click goes: an https address, or a page of the site that starts with a slash"},"alt_text":{"type":"string","description":"What the image says, for screen readers, max 250 characters","default":""},"utm":{"type":"boolean","description":"Add utm_source (the site's domain), utm_medium (house_ad), utm_campaign (the placement's key) and utm_content (the name) to the link. Default true","default":true},"weight":{"type":"integer","description":"Its share of the views in the rotation, from 0 to 100, against the other creatives' weights. Default 100","default":100},"active":{"type":"boolean","description":"Whether it is in the rotation. Default true","default":true},"starts_at":{"type":"string","format":"date-time","description":"When it starts to show, ISO 8601. Pro and up"},"ends_at":{"type":"string","format":"date-time","description":"When it stops showing, ISO 8601. Pro and up"},"devices":{"type":"array","items":{"type":"string","enum":["desktop","mobile","tablet"]},"description":"Only on these devices: desktop, mobile, tablet. Empty means all. Pro and up","default":[]},"paths":{"type":"array","items":{"type":"string"},"description":"Only on these pages of the site, such as [\"/tools/*\"]. Empty means all. Pro and up","default":[]},"image":{"type":"string","format":"binary","description":"The image, as a multipart file: JPEG, PNG, WebP or GIF (animated stays animated), up to 2 MB, of the placement's shape and at least its size"},"image_url":{"type":"string","description":"A public http or https address to download the image from, in place of a file"}},"required":["name","destination_url"]}}}}}},"/sites/{site_id}/experiments/ads/{ad_placement_id}/creatives/{id}.json":{"delete":{"operationId":"ad_creatives_delete","summary":"Delete a creative and its image","description":"Permanently deletes a creative and its image. One that an experiment compares can't be deleted: switch it off instead. The MCP tool does not run it and responds with human_only and the page where a person deletes it. Requires content.write.","tags":["Ad creatives"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"ad_placement_id","in":"path","required":true,"description":"Ad placement id (adp_...), from ad_placements_list","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by the tools that list or create it","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Creative id, e.g. adc_7Q2K9XH3AB"},"placement_id":{"type":"string","description":"Its placement (adp_...)"},"name":{"type":"string","description":"Internal name"},"alt_text":{"type":"string","description":"What the image says, for screen readers"},"destination_url":{"type":"string","description":"Where a click goes, as set"},"link":{"type":"string","description":"Where a click goes, with the campaign parameters when utm is on"},"utm":{"type":"boolean","description":"Whether campaign parameters are added to the link"},"weight":{"type":"integer","description":"Share of the views in the rotation"},"active":{"type":"boolean","description":"Whether it is in the rotation"},"starts_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it starts to show, or null"},{"type":"null"}]},"ends_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it stops showing, or null"},{"type":"null"}]},"devices":{"type":"array","items":{"type":"string"},"description":"Only on these devices. Empty means all"},"paths":{"type":"array","items":{"type":"string"},"description":"Only on these pages. Empty means all"},"state":{"type":"string","description":"processing, ready or failed"},"error":{"anyOf":[{"type":"string","description":"Why the image could not be used, or null: image_size, image_type, image_too_large or processing_failed"},{"type":"null"}]},"image_url":{"anyOf":[{"type":"string","description":"The image at the placement's size, or null before it is ready"},{"type":"null"}]},"image_2x_url":{"anyOf":[{"type":"string","description":"The image at twice the size, or null"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width of the image in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height of the image in pixels"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"impressions":{"type":"integer","description":"Times a creative was shown in a slot the page displayed"},"viewable":{"type":"integer","description":"Impressions seen: half of the creative on screen for one second (30% for a big one)"},"clicks":{"type":"integer","description":"Clicks, one per creative and visitor address in ten minutes"},"ctr":{"type":"number","description":"Clicks per viewable impression, as a percent"}},"description":"The period's numbers, on ad_placements_get"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was added"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"ad_creatives_get","summary":"Get one creative with its state","description":"A creative is processing until its image is made, then ready (or failed, with the reason in error). Requires analytics.read.","tags":["Ad creatives"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"ad_placement_id","in":"path","required":true,"description":"Ad placement id (adp_...), from ad_placements_list","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by the tools that list or create it","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Creative id, e.g. adc_7Q2K9XH3AB"},"placement_id":{"type":"string","description":"Its placement (adp_...)"},"name":{"type":"string","description":"Internal name"},"alt_text":{"type":"string","description":"What the image says, for screen readers"},"destination_url":{"type":"string","description":"Where a click goes, as set"},"link":{"type":"string","description":"Where a click goes, with the campaign parameters when utm is on"},"utm":{"type":"boolean","description":"Whether campaign parameters are added to the link"},"weight":{"type":"integer","description":"Share of the views in the rotation"},"active":{"type":"boolean","description":"Whether it is in the rotation"},"starts_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it starts to show, or null"},{"type":"null"}]},"ends_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it stops showing, or null"},{"type":"null"}]},"devices":{"type":"array","items":{"type":"string"},"description":"Only on these devices. Empty means all"},"paths":{"type":"array","items":{"type":"string"},"description":"Only on these pages. Empty means all"},"state":{"type":"string","description":"processing, ready or failed"},"error":{"anyOf":[{"type":"string","description":"Why the image could not be used, or null: image_size, image_type, image_too_large or processing_failed"},{"type":"null"}]},"image_url":{"anyOf":[{"type":"string","description":"The image at the placement's size, or null before it is ready"},{"type":"null"}]},"image_2x_url":{"anyOf":[{"type":"string","description":"The image at twice the size, or null"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width of the image in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height of the image in pixels"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"impressions":{"type":"integer","description":"Times a creative was shown in a slot the page displayed"},"viewable":{"type":"integer","description":"Impressions seen: half of the creative on screen for one second (30% for a big one)"},"clicks":{"type":"integer","description":"Clicks, one per creative and visitor address in ten minutes"},"ctr":{"type":"number","description":"Clicks per viewable impression, as a percent"}},"description":"The period's numbers, on ad_placements_get"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was added"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"ad_creatives_get","x-permission":"analytics.read"},"patch":{"operationId":"ad_creatives_update","summary":"Change a creative","description":"Changes the link, weight, schedule or targeting, switches it off (active false) or replaces the image. Only given inputs change. A new image replaces the old one when it is ready. Requires content.write.","tags":["Ad creatives"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"ad_placement_id","in":"path","required":true,"description":"Ad placement id (adp_...), from ad_placements_list","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by the tools that list or create it","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Creative id, e.g. adc_7Q2K9XH3AB"},"placement_id":{"type":"string","description":"Its placement (adp_...)"},"name":{"type":"string","description":"Internal name"},"alt_text":{"type":"string","description":"What the image says, for screen readers"},"destination_url":{"type":"string","description":"Where a click goes, as set"},"link":{"type":"string","description":"Where a click goes, with the campaign parameters when utm is on"},"utm":{"type":"boolean","description":"Whether campaign parameters are added to the link"},"weight":{"type":"integer","description":"Share of the views in the rotation"},"active":{"type":"boolean","description":"Whether it is in the rotation"},"starts_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it starts to show, or null"},{"type":"null"}]},"ends_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it stops showing, or null"},{"type":"null"}]},"devices":{"type":"array","items":{"type":"string"},"description":"Only on these devices. Empty means all"},"paths":{"type":"array","items":{"type":"string"},"description":"Only on these pages. Empty means all"},"state":{"type":"string","description":"processing, ready or failed"},"error":{"anyOf":[{"type":"string","description":"Why the image could not be used, or null: image_size, image_type, image_too_large or processing_failed"},{"type":"null"}]},"image_url":{"anyOf":[{"type":"string","description":"The image at the placement's size, or null before it is ready"},{"type":"null"}]},"image_2x_url":{"anyOf":[{"type":"string","description":"The image at twice the size, or null"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width of the image in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height of the image in pixels"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"impressions":{"type":"integer","description":"Times a creative was shown in a slot the page displayed"},"viewable":{"type":"integer","description":"Impressions seen: half of the creative on screen for one second (30% for a big one)"},"clicks":{"type":"integer","description":"Clicks, one per creative and visitor address in ten minutes"},"ctr":{"type":"number","description":"Clicks per viewable impression, as a percent"}},"description":"The period's numbers, on ad_placements_get"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was added"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"ad_creatives_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New internal name"},"destination_url":{"type":"string","description":"Where a click goes"},"alt_text":{"type":"string","description":"What the image says"},"utm":{"type":"boolean","description":"Whether campaign parameters are added to the link"},"weight":{"type":"integer","description":"Share of the views in the rotation, from 0 to 100"},"active":{"type":"boolean","description":"Whether it is in the rotation"},"starts_at":{"type":"string","format":"date-time","description":"When it starts to show. Pro and up"},"ends_at":{"type":"string","format":"date-time","description":"When it stops showing. Pro and up"},"devices":{"type":"array","items":{"type":"string","enum":["desktop","mobile","tablet"]},"description":"Only on these devices. Pro and up"},"paths":{"type":"array","items":{"type":"string"},"description":"Only on these pages. Pro and up"},"image":{"type":"string","format":"binary","description":"A new image, as a multipart file"},"image_url":{"type":"string","description":"A public address to download a new image from"}}}}}}}},"/sites/{site_id}/experiments/ads.json":{"post":{"operationId":"ad_placements_create","summary":"Create an ad placement","description":"Creates a slot of one size on the site. Send size (a common size such as medium_rectangle or leaderboard) or width and height in pixels. key is what the tag on the site names it by, and is made from the name when left out. Then add creatives with ad_creatives_create and put the tag from ad_placements_embed on the site. Requires content.write.","tags":["Ad placements"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Placement id, e.g. adp_7Q2K9XH3AB"},"name":{"type":"string","description":"Internal name"},"key":{"type":"string","description":"What the tag on the site names it by"},"width":{"type":"integer","description":"Width in pixels"},"height":{"type":"integer","description":"Height in pixels"},"size":{"anyOf":[{"type":"string","description":"The common size it is, such as medium_rectangle, or null"},{"type":"null"}]},"label":{"anyOf":[{"type":"string","description":"Text shown above the ad, or null"},{"type":"null"}]},"creatives_count":{"type":"integer","description":"How many creatives it has"},"stats":{"anyOf":[{"type":"object","properties":{"impressions":{"type":"integer","description":"Times a creative was shown in a slot the page displayed"},"viewable":{"type":"integer","description":"Impressions seen: half of the creative on screen for one second (30% for a big one)"},"clicks":{"type":"integer","description":"Clicks, one per creative and visitor address in ten minutes"},"ctr":{"type":"number","description":"Clicks per viewable impression, as a percent"}},"description":"The last 30 days, or null outside a list"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"ad_placements_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Internal name, such as Profile sidebar, max 120 characters"},"key":{"type":"string","description":"What the tag on the site names it by, such as profile-sidebar: lowercase letters, numbers and single dashes. Made from the name when left out"},"size":{"type":"string","description":"A common size: medium_rectangle (300x250), leaderboard (728x90), billboard (970x250), half_page (300x600), wide_skyscraper (160x600), large_rectangle (336x280), mobile_banner (320x50), large_mobile_banner (320x100) or square (250x250). Wins over width and height","enum":["medium_rectangle","leaderboard","billboard","half_page","wide_skyscraper","large_rectangle","mobile_banner","large_mobile_banner","square","custom"]},"width":{"type":"integer","description":"Width in pixels, from 10 to 2000, when no size is given"},"height":{"type":"integer","description":"Height in pixels, from 10 to 2000, when no size is given"},"label":{"type":"string","description":"Text shown above the ad, such as Sponsored, max 40 characters. Empty for none"}},"required":["name"]}}}}},"get":{"operationId":"ad_placements_list","summary":"List a site's ad placements with their last 30 days","description":"Each placement with its key, size, how many creatives it has and stats (impressions, viewable impressions, clicks and ctr, the click rate per viewable impression) over the last 30 days. Requires analytics.read.","tags":["Ad placements"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","description":"Page number, from 1","default":1}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","description":"Placements a page, up to 100","default":25}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Placement id, e.g. adp_7Q2K9XH3AB"},"name":{"type":"string","description":"Internal name"},"key":{"type":"string","description":"What the tag on the site names it by"},"width":{"type":"integer","description":"Width in pixels"},"height":{"type":"integer","description":"Height in pixels"},"size":{"anyOf":[{"type":"string","description":"The common size it is, such as medium_rectangle, or null"},{"type":"null"}]},"label":{"anyOf":[{"type":"string","description":"Text shown above the ad, or null"},{"type":"null"}]},"creatives_count":{"type":"integer","description":"How many creatives it has"},"stats":{"anyOf":[{"type":"object","properties":{"impressions":{"type":"integer","description":"Times a creative was shown in a slot the page displayed"},"viewable":{"type":"integer","description":"Impressions seen: half of the creative on screen for one second (30% for a big one)"},"clicks":{"type":"integer","description":"Clicks, one per creative and visitor address in ten minutes"},"ctr":{"type":"number","description":"Clicks per viewable impression, as a percent"}},"description":"The last 30 days, or null outside a list"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"ad_placements_list","x-permission":"analytics.read"}},"/sites/{site_id}/experiments/ads/{id}.json":{"delete":{"operationId":"ad_placements_delete","summary":"Delete an ad placement with its creatives","description":"Permanently deletes a placement with its creatives and their images, its ad experiments and their results, and its sponsor links. The tag on the site then draws nothing. The MCP tool does not run it and responds with human_only and the page where a person deletes it. Requires content.write.","tags":["Ad placements"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by ad_placements_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Placement id, e.g. adp_7Q2K9XH3AB"},"name":{"type":"string","description":"Internal name"},"key":{"type":"string","description":"What the tag on the site names it by"},"width":{"type":"integer","description":"Width in pixels"},"height":{"type":"integer","description":"Height in pixels"},"size":{"anyOf":[{"type":"string","description":"The common size it is, such as medium_rectangle, or null"},{"type":"null"}]},"label":{"anyOf":[{"type":"string","description":"Text shown above the ad, or null"},{"type":"null"}]},"creatives_count":{"type":"integer","description":"How many creatives it has"},"stats":{"anyOf":[{"type":"object","properties":{"impressions":{"type":"integer","description":"Times a creative was shown in a slot the page displayed"},"viewable":{"type":"integer","description":"Impressions seen: half of the creative on screen for one second (30% for a big one)"},"clicks":{"type":"integer","description":"Clicks, one per creative and visitor address in ten minutes"},"ctr":{"type":"number","description":"Clicks per viewable impression, as a percent"}},"description":"The last 30 days, or null outside a list"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"ad_placements_get","summary":"Get a placement with each creative's numbers","description":"The placement, its creatives with their stats over the period (7d, 30d or 90d) and the placement's numbers day by day. humans_only keeps what the bot score calls likely human (Pro and up). Requires analytics.read.","tags":["Ad placements"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by ad_placements_list","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"7d, 30d (default) or 90d","enum":["7d","30d","90d"],"default":"30d"}},{"name":"humans_only","in":"query","required":false,"schema":{"type":"boolean","description":"Count only what the bot score calls likely human. Pro and up","default":false}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"placement":{"type":"object","properties":{"id":{"type":"string","description":"Placement id, e.g. adp_7Q2K9XH3AB"},"name":{"type":"string","description":"Internal name"},"key":{"type":"string","description":"What the tag on the site names it by"},"width":{"type":"integer","description":"Width in pixels"},"height":{"type":"integer","description":"Height in pixels"},"size":{"anyOf":[{"type":"string","description":"The common size it is, such as medium_rectangle, or null"},{"type":"null"}]},"label":{"anyOf":[{"type":"string","description":"Text shown above the ad, or null"},{"type":"null"}]},"creatives_count":{"type":"integer","description":"How many creatives it has"},"stats":{"anyOf":[{"type":"object","properties":{"impressions":{"type":"integer","description":"Times a creative was shown in a slot the page displayed"},"viewable":{"type":"integer","description":"Impressions seen: half of the creative on screen for one second (30% for a big one)"},"clicks":{"type":"integer","description":"Clicks, one per creative and visitor address in ten minutes"},"ctr":{"type":"number","description":"Clicks per viewable impression, as a percent"}},"description":"The last 30 days, or null outside a list"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}},"description":"The placement"},"period":{"type":"string","description":"7d, 30d or 90d"},"humans_only":{"type":"boolean","description":"Whether only likely humans are counted"},"creatives":{"type":"array","items":{"type":"object"},"description":"Its creatives, each with stats for the period"},"daily":{"type":"array","items":{"type":"object"},"description":"Each day: date, impressions, viewable, clicks"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"ad_placements_get","x-permission":"analytics.read"},"patch":{"operationId":"ad_placements_update","summary":"Change an ad placement","description":"Changes the name, key, size or label. Only given inputs change. A new key needs the new tag on the site. Requires content.write.","tags":["Ad placements"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by ad_placements_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Placement id, e.g. adp_7Q2K9XH3AB"},"name":{"type":"string","description":"Internal name"},"key":{"type":"string","description":"What the tag on the site names it by"},"width":{"type":"integer","description":"Width in pixels"},"height":{"type":"integer","description":"Height in pixels"},"size":{"anyOf":[{"type":"string","description":"The common size it is, such as medium_rectangle, or null"},{"type":"null"}]},"label":{"anyOf":[{"type":"string","description":"Text shown above the ad, or null"},{"type":"null"}]},"creatives_count":{"type":"integer","description":"How many creatives it has"},"stats":{"anyOf":[{"type":"object","properties":{"impressions":{"type":"integer","description":"Times a creative was shown in a slot the page displayed"},"viewable":{"type":"integer","description":"Impressions seen: half of the creative on screen for one second (30% for a big one)"},"clicks":{"type":"integer","description":"Clicks, one per creative and visitor address in ten minutes"},"ctr":{"type":"number","description":"Clicks per viewable impression, as a percent"}},"description":"The last 30 days, or null outside a list"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"ad_placements_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New internal name"},"key":{"type":"string","description":"New key. The tag on the site must carry it"},"size":{"type":"string","description":"A common size, as for ad_placements_create","enum":["medium_rectangle","leaderboard","billboard","half_page","wide_skyscraper","large_rectangle","mobile_banner","large_mobile_banner","square","custom"]},"width":{"type":"integer","description":"Width in pixels"},"height":{"type":"integer","description":"Height in pixels"},"label":{"type":"string","description":"Text shown above the ad. Empty for none"}}}}}}}},"/sites/{site_id}/experiments/ads/{id}/embed.json":{"get":{"operationId":"ad_placements_embed","summary":"Get the tag that shows a placement on the site","description":"The loader script (once a page) and the slot for this placement, as html to paste. The slot keeps its size before the loader runs. Requires analytics.read.","tags":["Ad placements"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by ad_placements_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"placement_id":{"type":"string","description":"The placement (adp_...)"},"key":{"type":"string","description":"The key the slot carries"},"script":{"type":"string","description":"The loader, once a page"},"slot":{"type":"string","description":"The slot, where the ad goes"},"html":{"type":"string","description":"Both, ready to paste"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"ad_placements_embed","x-permission":"analytics.read"}},"/account/affiliate/commissions.json":{"get":{"operationId":"affiliate_commissions_list","summary":"List your affiliate commissions","description":"Commissions, refund and chargeback clawbacks and reversals, newest first. Amounts are in cents.","tags":["Affiliate program"],"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Only commissions with this status","enum":["pending","approved","paid","void"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Commission id"},"kind":{"type":"string","description":"commission, clawback (refund or chargeback) or reversal"},"status":{"type":"string","description":"pending (on hold), approved (payable), paid or void"},"amount_cents":{"type":"integer","description":"Your share in cents (negative for a clawback)"},"basis_cents":{"type":"integer","description":"The net payment (excluding tax) it was calculated from, in cents"},"currency":{"type":"string","description":"ISO currency code"},"earned_at":{"type":"string","format":"date-time","description":"When the payment (or refund) happened"},"approved_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it became payable"},{"type":"null"}]},"paid_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was paid out"},{"type":"null"}]}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"affiliate_commissions_list"}},"/account/affiliate/signup-box.json":{"get":{"operationId":"affiliate_signup_box_get","summary":"Get your affiliate signup box code and results","description":"The embed code for your signup box (a script and a plain iframe) for the chosen theme, the attributes that prefill the form, the events the script fires on your page, and the box’s numbers: signups waiting to confirm, confirmed signups and paying customers. available is false until your affiliate application is approved.","tags":["Affiliate program"],"parameters":[{"name":"theme","in":"query","required":false,"schema":{"type":"string","description":"Theme of the box: auto (match the visitor’s device), light or dark","enum":["auto","light","dark"],"examples":["auto"],"default":"auto"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"available":{"type":"boolean","description":"Whether you have a signup box (approved affiliates only)"},"theme":{"type":"string","description":"The theme the code was built for"},"frame_url":{"anyOf":[{"type":"string","description":"The address of the box, for a plain iframe"},{"type":"null"}]},"script":{"anyOf":[{"type":"string","description":"The script embed code: an element and the loader script"},{"type":"null"}]},"iframe":{"anyOf":[{"type":"string","description":"The plain iframe embed code"},{"type":"null"}]},"prefill_attributes":{"type":"array","description":"Attributes on the element that prefill the form for signed-in visitors"},"events":{"type":"array","description":"DOM events the script fires on the element"},"waiting":{"type":"integer","description":"Signups who have an account and have not signed in yet"},"signups":{"type":"integer","description":"Confirmed signups that came through the box"},"customers":{"type":"integer","description":"Those that became paying customers"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"affiliate_signup_box_get"}},"/account/affiliate.json":{"get":{"operationId":"affiliate_get","summary":"Get your affiliate status, referral link and stats","description":"Your affiliate application status, referral link, signups and paying customers you referred, and balances per currency (on hold, payable, paid). status is none when you have not applied.","tags":["Affiliate program"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string","description":"none (not applied), pending, approved, rejected or suspended"},"code":{"anyOf":[{"type":"string","description":"Your referral code"},{"type":"null"}]},"referral_url":{"anyOf":[{"type":"string","description":"The link to share (approved affiliates only)"},{"type":"null"}]},"payout_method":{"anyOf":[{"type":"string","description":"wise or credit"},{"type":"null"}]},"rejection_reason":{"anyOf":[{"type":"string","description":"Why the last application was rejected"},{"type":"null"}]},"applied_at":{"anyOf":[{"type":"string","format":"date-time","description":"When you applied"},{"type":"null"}]},"approved_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the application was approved"},{"type":"null"}]},"credit_blocked":{"anyOf":[{"type":"string","description":"Why account credit is waiting: program (the workspace is in a discount program), no_subscription or no_workspace. null when nothing blocks it"},{"type":"null"}]},"signups":{"type":"integer","description":"Accounts created through your link or code"},"customers":{"type":"integer","description":"Referred workspaces that have paid"},"balances":{"type":"array","description":"Per currency: pending_cents (on hold), approved_cents (payable) and paid_cents"},"payouts":{"type":"array","description":"Recent payouts with amount_cents, currency, payout_method, status (applied: account credit waiting for your next renewal, or paid), applied_at and paid_at"},"terms":{"type":"object","description":"Commission percent, months, hold days and the Wise payout threshold in cents"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"affiliate_get"}},"/alerts/{id}/acknowledge.json":{"post":{"operationId":"alerts_acknowledge","summary":"Acknowledge the latest incident","description":"Marks the latest unacknowledged incident of an alert as seen by the calling user. It does not resolve the incident or mute the alert, the alert resolves by itself when the condition clears. If the alert has no unacknowledged incident the call fails with a validation error. Returns the alert. Use alerts_history to see incidents with their acknowledged_at and acknowledged_by. Only needs analytics read access, so viewers can acknowledge.","tags":["Alerts"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by alerts_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Alert id, e.g. alr_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site id (null for usage alerts and for a testimonials alert about the allowance)"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"threshold, anomaly, goal, new_referrer, no_data, usage, uptime, ssl, vitals or testimonials"},"metric":{"anyOf":[{"type":"string","description":"The metric a threshold, anomaly or vitals alert measures. For a testimonials alert, what it watches: new, low_rating, approved, allowance, sync_found, import_failed, removal_requested or request_bounced"},{"type":"null"}]},"operator":{"anyOf":[{"type":"string","description":"gt, gte, lt or lte"},{"type":"null"}]},"threshold":{"anyOf":[{"type":"number"},{"type":"null"}]},"window_minutes":{"type":"integer"},"sensitivity":{"type":"string","description":"anomaly sensitivity"},"goal_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of the goal of the alert. Null without one"},{"type":"null"}]},"filters":{"type":"array","description":"Stats filters the alert counts by (empty for all visits)"},"segment_id":{"anyOf":[{"type":"string","description":"Shared segment the alert counts by"},{"type":"null"}]},"segment_name":{"anyOf":[{"type":"string","description":"The name of that segment. Null without one"},{"type":"null"}]},"filters_summary":{"anyOf":[{"type":"string","description":"What the alert counts, in words (its filters and its segment together). Null when it counts every visit"},{"type":"null"}]},"comparison":{"anyOf":[{"type":"string","description":"previous_period or previous_week when the threshold is a percent change"},{"type":"null"}]},"min_rating":{"anyOf":[{"type":"integer","description":"Lowest Domain Rating a new referrer needs"},{"type":"null"}]},"frequency":{"type":"string","description":"How often a testimonials alert notifies: immediate, hourly or daily. Always immediate for every other kind"},"channel_ids":{"type":"array","items":{"type":"string"},"description":"Notification channel ids"},"channel_names":{"type":"array","items":{"type":"string"},"description":"The names of those channels, in the order of channel_ids"},"state":{"type":"string","description":"ok or triggered"},"enabled":{"type":"boolean"},"muted_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_triggered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_evaluated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"alerts_acknowledge","x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/workspaces/{workspace_id}/alerts.json":{"post":{"operationId":"alerts_create","summary":"Create an alert","description":"Creates an alert rule that watches a site (or the whole workspace for kind usage) and notifies the chosen channels when it triggers. Path takes workspace_id. name and kind are required. kind decides what else is needed. threshold needs site_id, metric (visitors, visits, pageviews, bounce_rate or conversion), operator (gt, gte, lt or lte) and threshold, and conversion also needs goal_id. anomaly needs site_id and metric (visitors, visits or pageviews), compares the last window with the same window in each of the previous 4 weeks and uses sensitivity (low, medium or high). operator lt only alerts on drops, gt only on spikes and empty on both. goal needs site_id, goal_id and threshold (completions in the window). no_data needs site_id and threshold in hours without events (default 24). usage needs no site and threshold as percent of the monthly event allowance (default 80). uptime needs site_id and optionally uptime_check_id (default all checks of the site). ssl needs site_id and threshold in days before a certificate or domain expires (default 14). vitals needs site_id, metric (lcp, inp, cls, fcp or ttfb) and threshold in milliseconds (a score for cls). subscriptions needs site_id, metric (mrr_drop: MRR fell by more than threshold percent in the last 30 days, churn_rate or mrr_churn_rate: churn over the last 30 days is above threshold percent) and threshold (default 10), and skips while the site has no payment provider connected or nothing to measure. window_minutes (default 60, 5 to 10080) is how far back each evaluation looks. channel_ids come from notification_channels_list and sensitivity defaults to medium. Alerts are evaluated automatically every 5 minutes. bounce_rate and conversion thresholds are percents from 0 to 100. testimonials needs site_id and metric, which says what it watches: new (a new testimonial arrives), low_rating (a rating of 3 or lower arrives), approved (a testimonial is approved), allowance (the month's allowance of new testimonials is 80% used, used up, or holding a testimonial as waiting), sync_found (a sync finds new reviews), import_failed (an import fails, or a source fails three syncs in a row), removal_requested (someone asks for their testimonial to be removed) or request_bounced (a request email bounces). A testimonials alert is not evaluated every 5 minutes: it triggers at once each time the thing happens, records an incident that is already resolved, and its state stays ok. With metric allowance it watches the whole workspace and keeps no site. Returns the created alert with state ok.","tags":["Alerts"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Alert id, e.g. alr_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site id (null for usage alerts and for a testimonials alert about the allowance)"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"threshold, anomaly, goal, new_referrer, no_data, usage, uptime, ssl, vitals or testimonials"},"metric":{"anyOf":[{"type":"string","description":"The metric a threshold, anomaly or vitals alert measures. For a testimonials alert, what it watches: new, low_rating, approved, allowance, sync_found, import_failed, removal_requested or request_bounced"},{"type":"null"}]},"operator":{"anyOf":[{"type":"string","description":"gt, gte, lt or lte"},{"type":"null"}]},"threshold":{"anyOf":[{"type":"number"},{"type":"null"}]},"window_minutes":{"type":"integer"},"sensitivity":{"type":"string","description":"anomaly sensitivity"},"goal_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of the goal of the alert. Null without one"},{"type":"null"}]},"filters":{"type":"array","description":"Stats filters the alert counts by (empty for all visits)"},"segment_id":{"anyOf":[{"type":"string","description":"Shared segment the alert counts by"},{"type":"null"}]},"segment_name":{"anyOf":[{"type":"string","description":"The name of that segment. Null without one"},{"type":"null"}]},"filters_summary":{"anyOf":[{"type":"string","description":"What the alert counts, in words (its filters and its segment together). Null when it counts every visit"},{"type":"null"}]},"comparison":{"anyOf":[{"type":"string","description":"previous_period or previous_week when the threshold is a percent change"},{"type":"null"}]},"min_rating":{"anyOf":[{"type":"integer","description":"Lowest Domain Rating a new referrer needs"},{"type":"null"}]},"frequency":{"type":"string","description":"How often a testimonials alert notifies: immediate, hourly or daily. Always immediate for every other kind"},"channel_ids":{"type":"array","items":{"type":"string"},"description":"Notification channel ids"},"channel_names":{"type":"array","items":{"type":"string"},"description":"The names of those channels, in the order of channel_ids"},"state":{"type":"string","description":"ok or triggered"},"enabled":{"type":"boolean"},"muted_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_triggered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_evaluated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"alerts_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"site_id":{"type":"string","description":"Site id (pa_..., from sites_list). Required for every kind except usage, which watches the whole workspace and ignores it. A testimonials alert with metric allowance is about the whole workspace too and keeps no site"},"metric":{"type":"string","description":"threshold: visitors, visits, pageviews, bounce_rate or conversion. anomaly: visitors, visits or pageviews. vitals: lcp, inp, cls, fcp or ttfb. subscriptions: mrr_drop, churn_rate or mrr_churn_rate. testimonials: what the alert watches, one of new (a new testimonial arrives), low_rating (a rating of 3 or lower arrives), approved (a testimonial is approved), allowance (the month's allowance of new testimonials is 80% used, used up, or holding a testimonial as waiting), sync_found (a sync finds new reviews), import_failed (an import fails, or a source fails three syncs in a row), removal_requested (someone asks for their testimonial to be removed) or request_bounced (a request email bounces). The default is new. Not used by the other kinds"},"operator":{"type":"string","description":"Comparison against the threshold: gt (greater), gte, lt (less) or lte. Required for threshold. For anomaly lt alerts only on drops, gt only on spikes and empty on both. vitals defaults to gt","enum":["gt","gte","lt","lte"]},"threshold":{"type":"number","description":"Number whose unit depends on kind. threshold: the metric value (bounce_rate and conversion in percent 0 to 100). With a comparison it is a percent change. goal: completions in the window. new_referrer: visitors the new site sent in the window (default 10). no_data: hours without events (default 24). usage: percent of the allowance (default 80). ssl: days left (default 14). vitals: milliseconds (a score for cls). subscriptions: a percent (default 10). Not used by anomaly and uptime"},"window_minutes":{"type":"integer","description":"How far back each evaluation looks, in minutes, from 5 to 10080 (default 60). For anomaly it is also the length of the windows compared with the previous 4 weeks"},"sensitivity":{"type":"string","description":"anomaly only: low, medium (default) or high. Higher is more sensitive and triggers on smaller deviations","enum":["low","medium","high"]},"goal_id":{"type":"string","description":"Goal id (goal_..., from goals_list) of the same site. Required for goal alerts and for threshold alerts with metric conversion"},"filters":{"type":"array","items":{},"description":"threshold, anomaly, goal and new_referrer: count only the visits these filters match, as a list of [dimension, operator, value] in the same format as the stats tools, for example [[\"page\",\"starts_with\",\"/blog\"]]. Empty or left out counts all visits. Ignored by the other kinds","examples":[[["page","starts_with","/blog"],["country","is","US"]]]},"segment_id":{"type":"string","description":"threshold, anomaly, goal and new_referrer: a shared segment (seg_..., from segments_list) of the same site whose filters are applied as well. A private segment is refused"},"comparison":{"type":"string","description":"threshold only: previous_period (the window just before) or previous_week (the same window a week earlier). The threshold is then a percent change and must be above 0: operator lt or lte triggers on a drop of at least that percent, gt or gte on a rise. Leave out to compare with a fixed value","enum":["previous_period","previous_week"]},"min_rating":{"type":"integer","description":"new_referrer only: the lowest Domain Rating (0 to 100) the referring domain needs to trigger the alert. Leave out for any referrer","examples":[50]},"frequency":{"type":"string","description":"testimonials alerts only: how often the alert notifies its channels. immediate (default) sends each time it happens, hourly sends one summary at the top of the next hour and daily one summary a day at 9:00 in the workspace's time zone. Every incident is in the history at once either way. Ignored for every other kind, which always notifies at once","enum":["immediate","hourly","daily"]},"uptime_check_id":{"type":"string","description":"uptime and ssl alerts: the uptime check id to watch, from uptime_checks_list. Leave out to watch all of the site's checks"},"channel_ids":{"type":"array","items":{"type":"string"},"description":"Notification channel ids (nch_..., from notification_channels_list) to notify. Empty means the alert only records incidents"},"enabled":{"type":"boolean","description":"Evaluate this alert (default true). Evaluation runs every 5 minutes. A testimonials alert is not evaluated: it triggers when the thing happens"},"name":{"type":"string","description":"Alert name, up to 120 characters","examples":["Traffic dropped"]},"kind":{"type":"string","description":"What to watch: threshold (a metric against a fixed value, or its change against an earlier window with comparison), anomaly (unusual compared with the last 4 weeks), goal (completions of a goal), new_referrer (a site that sent nothing in the 30 days before now sends visitors), no_data (no events for some hours), usage (share of the monthly event allowance), uptime (an uptime check is down), ssl (certificate or domain expires soon), vitals (a Web Vital is too slow), subscriptions (MRR falls or churn rises, from the Subscriptions page) or testimonials (something happens in the Testimonials of the site: metric says what)","enum":["threshold","anomaly","goal","new_referrer","no_data","usage","uptime","ssl","vitals","subscriptions","testimonials"]}},"required":["name","kind"]}}}}},"get":{"operationId":"alerts_list","summary":"List alerts","description":"Lists the alert rules of a workspace (path takes workspace_id), sorted by name and paginated. Returns a data array of alerts with meta pagination. Each alert has id (alr_...), site_id (pa_..., null for usage alerts which watch the whole workspace), name, kind, metric, operator, threshold, window_minutes, sensitivity, goal_id and goal_name, segment_name, filters_summary, channel_ids (nch_... ids) and channel_names, state (ok or triggered), enabled, muted_until, last_triggered_at, last_evaluated_at and created_at. Narrow it with site_id, state (ok or triggered) or kind. Use site_alerts_list to list the alerts of one site from a site path, alerts_get for a single alert and alerts_history for its incidents. A caller limited to some sites never sees usage alerts.","tags":["Alerts"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"site_id","in":"query","required":false,"schema":{"type":"string","description":"Only alerts for this site (pa_..., from sites_list)"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","description":"Only alerts in this state: ok or triggered (an incident is open)","enum":["ok","triggered"]}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","description":"Only this kind: threshold, anomaly, goal, new_referrer, no_data, usage, uptime, ssl, vitals, subscriptions or testimonials","enum":["threshold","anomaly","goal","new_referrer","no_data","usage","uptime","ssl","vitals","subscriptions","testimonials"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Alert id, e.g. alr_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site id (null for usage alerts and for a testimonials alert about the allowance)"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"threshold, anomaly, goal, new_referrer, no_data, usage, uptime, ssl, vitals or testimonials"},"metric":{"anyOf":[{"type":"string","description":"The metric a threshold, anomaly or vitals alert measures. For a testimonials alert, what it watches: new, low_rating, approved, allowance, sync_found, import_failed, removal_requested or request_bounced"},{"type":"null"}]},"operator":{"anyOf":[{"type":"string","description":"gt, gte, lt or lte"},{"type":"null"}]},"threshold":{"anyOf":[{"type":"number"},{"type":"null"}]},"window_minutes":{"type":"integer"},"sensitivity":{"type":"string","description":"anomaly sensitivity"},"goal_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of the goal of the alert. Null without one"},{"type":"null"}]},"filters":{"type":"array","description":"Stats filters the alert counts by (empty for all visits)"},"segment_id":{"anyOf":[{"type":"string","description":"Shared segment the alert counts by"},{"type":"null"}]},"segment_name":{"anyOf":[{"type":"string","description":"The name of that segment. Null without one"},{"type":"null"}]},"filters_summary":{"anyOf":[{"type":"string","description":"What the alert counts, in words (its filters and its segment together). Null when it counts every visit"},{"type":"null"}]},"comparison":{"anyOf":[{"type":"string","description":"previous_period or previous_week when the threshold is a percent change"},{"type":"null"}]},"min_rating":{"anyOf":[{"type":"integer","description":"Lowest Domain Rating a new referrer needs"},{"type":"null"}]},"frequency":{"type":"string","description":"How often a testimonials alert notifies: immediate, hourly or daily. Always immediate for every other kind"},"channel_ids":{"type":"array","items":{"type":"string"},"description":"Notification channel ids"},"channel_names":{"type":"array","items":{"type":"string"},"description":"The names of those channels, in the order of channel_ids"},"state":{"type":"string","description":"ok or triggered"},"enabled":{"type":"boolean"},"muted_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_triggered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_evaluated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"alerts_list","x-permission":"analytics.read"}},"/alerts/{id}.json":{"delete":{"operationId":"alerts_delete","summary":"Delete an alert","description":"Permanently deletes an alert rule and its whole incident history. This cannot be undone and notifications stop at once. To pause an alert without losing history use alerts_update with enabled false or alerts_mute. The id (alr_...) comes from alerts_list. Returns the deleted alert as it was. Requires content write permission.","tags":["Alerts"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by alerts_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Alert id, e.g. alr_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site id (null for usage alerts and for a testimonials alert about the allowance)"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"threshold, anomaly, goal, new_referrer, no_data, usage, uptime, ssl, vitals or testimonials"},"metric":{"anyOf":[{"type":"string","description":"The metric a threshold, anomaly or vitals alert measures. For a testimonials alert, what it watches: new, low_rating, approved, allowance, sync_found, import_failed, removal_requested or request_bounced"},{"type":"null"}]},"operator":{"anyOf":[{"type":"string","description":"gt, gte, lt or lte"},{"type":"null"}]},"threshold":{"anyOf":[{"type":"number"},{"type":"null"}]},"window_minutes":{"type":"integer"},"sensitivity":{"type":"string","description":"anomaly sensitivity"},"goal_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of the goal of the alert. Null without one"},{"type":"null"}]},"filters":{"type":"array","description":"Stats filters the alert counts by (empty for all visits)"},"segment_id":{"anyOf":[{"type":"string","description":"Shared segment the alert counts by"},{"type":"null"}]},"segment_name":{"anyOf":[{"type":"string","description":"The name of that segment. Null without one"},{"type":"null"}]},"filters_summary":{"anyOf":[{"type":"string","description":"What the alert counts, in words (its filters and its segment together). Null when it counts every visit"},{"type":"null"}]},"comparison":{"anyOf":[{"type":"string","description":"previous_period or previous_week when the threshold is a percent change"},{"type":"null"}]},"min_rating":{"anyOf":[{"type":"integer","description":"Lowest Domain Rating a new referrer needs"},{"type":"null"}]},"frequency":{"type":"string","description":"How often a testimonials alert notifies: immediate, hourly or daily. Always immediate for every other kind"},"channel_ids":{"type":"array","items":{"type":"string"},"description":"Notification channel ids"},"channel_names":{"type":"array","items":{"type":"string"},"description":"The names of those channels, in the order of channel_ids"},"state":{"type":"string","description":"ok or triggered"},"enabled":{"type":"boolean"},"muted_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_triggered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_evaluated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"alerts_delete","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"alerts_get","summary":"Get an alert","description":"Returns one alert rule by id (alr_..., from alerts_list or site_alerts_list). The response is the alert object with id, site_id (null for usage alerts), name, kind, metric, operator, threshold, window_minutes, sensitivity, goal_id and goal_name, filters, segment_id and segment_name, filters_summary (what the alert counts in words, null when it counts every visit), channel_ids and channel_names (in the same order), state (ok or triggered), enabled, muted_until, last_triggered_at, last_evaluated_at and created_at. It does not include incidents, use alerts_history for those. threshold is a number whose unit depends on the kind (see alerts_create). Requires analytics read access.","tags":["Alerts"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by alerts_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Alert id, e.g. alr_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site id (null for usage alerts and for a testimonials alert about the allowance)"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"threshold, anomaly, goal, new_referrer, no_data, usage, uptime, ssl, vitals or testimonials"},"metric":{"anyOf":[{"type":"string","description":"The metric a threshold, anomaly or vitals alert measures. For a testimonials alert, what it watches: new, low_rating, approved, allowance, sync_found, import_failed, removal_requested or request_bounced"},{"type":"null"}]},"operator":{"anyOf":[{"type":"string","description":"gt, gte, lt or lte"},{"type":"null"}]},"threshold":{"anyOf":[{"type":"number"},{"type":"null"}]},"window_minutes":{"type":"integer"},"sensitivity":{"type":"string","description":"anomaly sensitivity"},"goal_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of the goal of the alert. Null without one"},{"type":"null"}]},"filters":{"type":"array","description":"Stats filters the alert counts by (empty for all visits)"},"segment_id":{"anyOf":[{"type":"string","description":"Shared segment the alert counts by"},{"type":"null"}]},"segment_name":{"anyOf":[{"type":"string","description":"The name of that segment. Null without one"},{"type":"null"}]},"filters_summary":{"anyOf":[{"type":"string","description":"What the alert counts, in words (its filters and its segment together). Null when it counts every visit"},{"type":"null"}]},"comparison":{"anyOf":[{"type":"string","description":"previous_period or previous_week when the threshold is a percent change"},{"type":"null"}]},"min_rating":{"anyOf":[{"type":"integer","description":"Lowest Domain Rating a new referrer needs"},{"type":"null"}]},"frequency":{"type":"string","description":"How often a testimonials alert notifies: immediate, hourly or daily. Always immediate for every other kind"},"channel_ids":{"type":"array","items":{"type":"string"},"description":"Notification channel ids"},"channel_names":{"type":"array","items":{"type":"string"},"description":"The names of those channels, in the order of channel_ids"},"state":{"type":"string","description":"ok or triggered"},"enabled":{"type":"boolean"},"muted_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_triggered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_evaluated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"alerts_get","x-permission":"analytics.read"},"patch":{"operationId":"alerts_update","summary":"Update an alert","description":"Changes an existing alert rule (id from alerts_list). Only the inputs you send change, everything else keeps its value. The same per kind rules as alerts_create apply to the result, so changing kind or metric may require the matching site_id, goal_id, operator or threshold. Send channel_ids to replace the whole list of notification channels, and enabled false to stop evaluating without deleting. To silence notifications for a while but keep recording incidents use alerts_mute instead. Returns the updated alert.","tags":["Alerts"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by alerts_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Alert id, e.g. alr_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site id (null for usage alerts and for a testimonials alert about the allowance)"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"threshold, anomaly, goal, new_referrer, no_data, usage, uptime, ssl, vitals or testimonials"},"metric":{"anyOf":[{"type":"string","description":"The metric a threshold, anomaly or vitals alert measures. For a testimonials alert, what it watches: new, low_rating, approved, allowance, sync_found, import_failed, removal_requested or request_bounced"},{"type":"null"}]},"operator":{"anyOf":[{"type":"string","description":"gt, gte, lt or lte"},{"type":"null"}]},"threshold":{"anyOf":[{"type":"number"},{"type":"null"}]},"window_minutes":{"type":"integer"},"sensitivity":{"type":"string","description":"anomaly sensitivity"},"goal_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of the goal of the alert. Null without one"},{"type":"null"}]},"filters":{"type":"array","description":"Stats filters the alert counts by (empty for all visits)"},"segment_id":{"anyOf":[{"type":"string","description":"Shared segment the alert counts by"},{"type":"null"}]},"segment_name":{"anyOf":[{"type":"string","description":"The name of that segment. Null without one"},{"type":"null"}]},"filters_summary":{"anyOf":[{"type":"string","description":"What the alert counts, in words (its filters and its segment together). Null when it counts every visit"},{"type":"null"}]},"comparison":{"anyOf":[{"type":"string","description":"previous_period or previous_week when the threshold is a percent change"},{"type":"null"}]},"min_rating":{"anyOf":[{"type":"integer","description":"Lowest Domain Rating a new referrer needs"},{"type":"null"}]},"frequency":{"type":"string","description":"How often a testimonials alert notifies: immediate, hourly or daily. Always immediate for every other kind"},"channel_ids":{"type":"array","items":{"type":"string"},"description":"Notification channel ids"},"channel_names":{"type":"array","items":{"type":"string"},"description":"The names of those channels, in the order of channel_ids"},"state":{"type":"string","description":"ok or triggered"},"enabled":{"type":"boolean"},"muted_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_triggered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_evaluated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"alerts_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"site_id":{"type":"string","description":"Site id (pa_..., from sites_list). Required for every kind except usage and a testimonials alert with metric allowance"},"metric":{"type":"string","description":"threshold: visitors, visits, pageviews, bounce_rate or conversion. anomaly: visitors, visits or pageviews. vitals: lcp, inp, cls, fcp or ttfb. subscriptions: mrr_drop, churn_rate or mrr_churn_rate. testimonials: new, low_rating, approved, allowance, sync_found, import_failed, removal_requested or request_bounced, see alerts_create"},"operator":{"type":"string","description":"Comparison against the threshold: gt, gte, lt or lte. For anomaly lt alerts only on drops, gt only on spikes and empty on both","enum":["gt","gte","lt","lte"]},"threshold":{"type":"number","description":"Number whose unit depends on kind. threshold: the metric value (bounce_rate and conversion in percent). goal: completions. no_data: hours. usage: percent of the allowance. ssl: days. vitals: milliseconds (a score for cls). subscriptions: a percent"},"window_minutes":{"type":"integer","description":"How far back each evaluation looks, in minutes, from 5 to 10080"},"sensitivity":{"type":"string","description":"anomaly only: low, medium or high","enum":["low","medium","high"]},"goal_id":{"type":"string","description":"Goal id (goal_..., from goals_list) of the same site, for goal alerts and conversion thresholds"},"filters":{"type":"array","items":{},"description":"Replaces the filters the alert counts by, as a list of [dimension, operator, value]. Send an empty list to count all visits","examples":[[["page","starts_with","/blog"],["country","is","US"]]]},"segment_id":{"type":"string","description":"A shared segment (seg_..., from segments_list) of the same site to count by. Send an empty string to remove it"},"comparison":{"type":"string","description":"threshold only: previous_period or previous_week, which makes the threshold a percent change. Send an empty string to compare with a fixed value again","enum":["previous_period","previous_week"]},"min_rating":{"type":"integer","description":"new_referrer only: the lowest Domain Rating (0 to 100) a new referrer needs. Send null for any referrer","examples":[50]},"frequency":{"type":"string","description":"testimonials alerts only: immediate, hourly or daily. Incidents already waiting for a summary still go out at the time they were due. Ignored for every other kind","enum":["immediate","hourly","daily"]},"uptime_check_id":{"type":"string","description":"uptime and ssl alerts: the uptime check id to watch, from uptime_checks_list. Empty watches all of the site's checks"},"channel_ids":{"type":"array","items":{"type":"string"},"description":"Replaces the whole list of notification channel ids (nch_..., from notification_channels_list). Send an empty list to notify nowhere"},"enabled":{"type":"boolean","description":"Set false to stop evaluating without deleting the alert"},"name":{"type":"string","description":"New alert name, up to 120 characters"},"kind":{"type":"string","description":"Change what is watched. The required inputs of the new kind must then be present, see alerts_create","enum":["threshold","anomaly","goal","new_referrer","no_data","usage","uptime","ssl","vitals","subscriptions","testimonials"]}}}}}}}},"/alerts/{id}/history.json":{"get":{"operationId":"alerts_history","summary":"Incident history of an alert","description":"Lists the incidents of one alert, newest first and paginated. Each incident has triggered_at, resolved_at (null while still open), value (the measured number when it triggered, same unit as the alert threshold), message (a readable description), acknowledged_at and acknowledged_by (display name of the member, or null). Set open to true to see only unresolved incidents. Use alerts_acknowledge to mark the latest one as seen and alerts_get for the current state of the rule.","tags":["Alerts"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by alerts_list","schema":{"type":"string"}},{"name":"open","in":"query","required":false,"schema":{"type":"boolean","description":"true returns only incidents that have not resolved yet (default false returns all)","default":false}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"triggered_at":{"type":"string","format":"date-time"},"resolved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"value":{"anyOf":[{"type":"number","description":"Measured value when triggered"},{"type":"null"}]},"message":{"anyOf":[{"type":"string"},{"type":"null"}]},"digest_due_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the hourly or daily summary that holds this incident goes out. Null once it was sent, and for an incident that was notified at once"},{"type":"null"}]},"acknowledged_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"acknowledged_by":{"anyOf":[{"type":"string","description":"Name of the member who acknowledged"},{"type":"null"}]}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"alerts_history","x-permission":"analytics.read"}},"/alerts/{id}/mute.json":{"post":{"operationId":"alerts_mute","summary":"Mute (or unmute) an alert’s notifications","description":"Silences the notifications of one alert for a number of minutes while it keeps evaluating and recording incidents in its history. minutes defaults to 60, the maximum is 43200 (30 days) and 0 unmutes it right away. The response is the alert with muted_until set to the end of the mute (null when unmuted). Use alerts_update with enabled false to stop evaluating completely and alerts_acknowledge to mark an incident as seen without muting.","tags":["Alerts"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by alerts_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Alert id, e.g. alr_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site id (null for usage alerts and for a testimonials alert about the allowance)"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"threshold, anomaly, goal, new_referrer, no_data, usage, uptime, ssl, vitals or testimonials"},"metric":{"anyOf":[{"type":"string","description":"The metric a threshold, anomaly or vitals alert measures. For a testimonials alert, what it watches: new, low_rating, approved, allowance, sync_found, import_failed, removal_requested or request_bounced"},{"type":"null"}]},"operator":{"anyOf":[{"type":"string","description":"gt, gte, lt or lte"},{"type":"null"}]},"threshold":{"anyOf":[{"type":"number"},{"type":"null"}]},"window_minutes":{"type":"integer"},"sensitivity":{"type":"string","description":"anomaly sensitivity"},"goal_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of the goal of the alert. Null without one"},{"type":"null"}]},"filters":{"type":"array","description":"Stats filters the alert counts by (empty for all visits)"},"segment_id":{"anyOf":[{"type":"string","description":"Shared segment the alert counts by"},{"type":"null"}]},"segment_name":{"anyOf":[{"type":"string","description":"The name of that segment. Null without one"},{"type":"null"}]},"filters_summary":{"anyOf":[{"type":"string","description":"What the alert counts, in words (its filters and its segment together). Null when it counts every visit"},{"type":"null"}]},"comparison":{"anyOf":[{"type":"string","description":"previous_period or previous_week when the threshold is a percent change"},{"type":"null"}]},"min_rating":{"anyOf":[{"type":"integer","description":"Lowest Domain Rating a new referrer needs"},{"type":"null"}]},"frequency":{"type":"string","description":"How often a testimonials alert notifies: immediate, hourly or daily. Always immediate for every other kind"},"channel_ids":{"type":"array","items":{"type":"string"},"description":"Notification channel ids"},"channel_names":{"type":"array","items":{"type":"string"},"description":"The names of those channels, in the order of channel_ids"},"state":{"type":"string","description":"ok or triggered"},"enabled":{"type":"boolean"},"muted_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_triggered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_evaluated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"alerts_mute","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"minutes":{"type":"integer","description":"Mute for this many minutes (default 60, maximum 43200 which is 30 days). 0 unmutes right away","default":60}}}}}}}},"/sites/{site_id}/alerts.json":{"get":{"operationId":"site_alerts_list","summary":"List alerts for a site","description":"Lists the alert rules of one site (path takes site_id), sorted by name and paginated. It returns the same alert objects and accepts the same state and kind filters as alerts_list, but only for this site, so usage alerts (which have no site) are not included. Choose this when you already have a site id and alerts_list when you want every alert in the workspace. Each alert has id (alr_...), site_id, name, kind, metric, operator, threshold, window_minutes, sensitivity, goal_id, channel_ids, state (ok or triggered), enabled, muted_until, last_triggered_at, last_evaluated_at and created_at.","tags":["Alerts"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","description":"Only alerts in this state: ok or triggered (an incident is open)","enum":["ok","triggered"]}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","description":"Only this kind: threshold, anomaly, goal, new_referrer, no_data, usage, uptime, ssl, vitals, subscriptions or testimonials","enum":["threshold","anomaly","goal","new_referrer","no_data","usage","uptime","ssl","vitals","subscriptions","testimonials"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Alert id, e.g. alr_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site id (null for usage alerts and for a testimonials alert about the allowance)"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"threshold, anomaly, goal, new_referrer, no_data, usage, uptime, ssl, vitals or testimonials"},"metric":{"anyOf":[{"type":"string","description":"The metric a threshold, anomaly or vitals alert measures. For a testimonials alert, what it watches: new, low_rating, approved, allowance, sync_found, import_failed, removal_requested or request_bounced"},{"type":"null"}]},"operator":{"anyOf":[{"type":"string","description":"gt, gte, lt or lte"},{"type":"null"}]},"threshold":{"anyOf":[{"type":"number"},{"type":"null"}]},"window_minutes":{"type":"integer"},"sensitivity":{"type":"string","description":"anomaly sensitivity"},"goal_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of the goal of the alert. Null without one"},{"type":"null"}]},"filters":{"type":"array","description":"Stats filters the alert counts by (empty for all visits)"},"segment_id":{"anyOf":[{"type":"string","description":"Shared segment the alert counts by"},{"type":"null"}]},"segment_name":{"anyOf":[{"type":"string","description":"The name of that segment. Null without one"},{"type":"null"}]},"filters_summary":{"anyOf":[{"type":"string","description":"What the alert counts, in words (its filters and its segment together). Null when it counts every visit"},{"type":"null"}]},"comparison":{"anyOf":[{"type":"string","description":"previous_period or previous_week when the threshold is a percent change"},{"type":"null"}]},"min_rating":{"anyOf":[{"type":"integer","description":"Lowest Domain Rating a new referrer needs"},{"type":"null"}]},"frequency":{"type":"string","description":"How often a testimonials alert notifies: immediate, hourly or daily. Always immediate for every other kind"},"channel_ids":{"type":"array","items":{"type":"string"},"description":"Notification channel ids"},"channel_names":{"type":"array","items":{"type":"string"},"description":"The names of those channels, in the order of channel_ids"},"state":{"type":"string","description":"ok or triggered"},"enabled":{"type":"boolean"},"muted_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_triggered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_evaluated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_alerts_list","x-permission":"analytics.read"}},"/sites/{site_id}/clicks.json":{"get":{"operationId":"clicks_list","summary":"Click map: the most clicked elements of the site, or of one page with the share of its visits that clicked each","description":"Clicks per element from the clicks tracker module. An element is a short CSS selector (tag, id and up to two classes, at most four levels), or [data-privatus-click=\"name\"] when the site named it. Pass path (starting with a slash, as stored) for one page: then elements are {selector, clicks, visits, visit_share} and page_visits is the number of visits that viewed the page, with visit_share the percent of them (0 to 100) that clicked the element. Without path, elements are {path, selector, clicks, visits} across the site. visits counts visits that clicked at least once. Returns period, path, page_visits and elements, most clicked first. No element text, coordinates or mouse movement is ever collected. Use pages_detail for the rest of a page.","tags":["Analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"path","in":"query","required":false,"schema":{"type":"string","description":"Page path starting with a slash, exactly as stored (no host and no query string), for example /pricing. Leave it out for the most clicked elements of the whole site","examples":["/pricing"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"How many elements to return, 1 to 500. Default 100","default":100}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"clicks_list","x-permission":"analytics.read"}},"/sites/{site_id}/overview.json":{"get":{"operationId":"stats_overview","summary":"Site overview: metrics, chart series, top panels, live visitors and notes","description":"One call that returns everything the site overview page shows: use it to answer a broad question such as how a site is doing, instead of calling several tools. Returns period, metrics (visitors, visits, pageviews, views_per_visit, bounce_rate, visit_duration, revenue), interval, series (one entry per time bucket), panels, notes and live_visitors. With compare it adds comparison_period, comparison, change and comparison_series, as in stats_aggregate and stats_timeseries. Units match those tools: bounce_rate is a percent from 0 to 100, visit_duration is median engaged milliseconds, revenue is an integer in minor units (cents). panels is an object keyed by dimension name, each holding the top 10 rows with their share, in the same row shape as stats_breakdown for that dimension. By default it returns channel, referrer, page, entry_page, country, device, browser, os, utm_campaign, event and goal. Send panels to choose other dimensions (any dimension name except prop keys). notes lists annotations in the range as {id, date, end_date, title, url, color}. live_visitors counts visitors in the last 5 minutes. For more than 10 rows of a dimension use stats_breakdown, and for one number use stats_aggregate. Takes the shared period, compare, filters and segment inputs.","tags":["Analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Chart bucket size. auto picks minute, hour, day, week or month to suit the range","enum":["auto","minute","hour","day","week","month","quarter","year"],"default":"auto"}},{"name":"panels","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["channel","referrer","referrer_url","utm_source","utm_medium","utm_campaign","utm_content","utm_term","ref","hostname","country","language","device","browser","browser_version","os","os_version","screen","entry_page","exit_page","interaction","bot_score","page","event","goal"]},"description":"Dimensions to return top 10 rows for, as exact dimension names. Defaults to channel, referrer, page, entry_page, country, device, browser, os, utm_campaign, event and goal. prop:<key> dimensions are not available here, use stats_breakdown for those","default":["channel","referrer","page","entry_page","country","device","browser","os","utm_campaign","event","goal"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"stats_overview","x-permission":"analytics.read"}},"/sites/{site_id}/experiments/external.json":{"get":{"operationId":"experiments_report","summary":"Report for an A/B test run with another tool: conversion rate per variant from an event property, uplift vs control and significance (two-proportion z-test)","description":"Reports an A/B test using event data. Visits are assigned to the variant found in an event property (the first value seen in the visit, for example property variant with values control and b), and a conversion is a visit that completed a goal. Required inputs are property (lowercase key, up to 64 characters) and goal_id (an active goal, from goals_list). Returns period, property, goal {id, name}, control, confidence (0.95) and variants. Each variant has visits, conversions, conversion_rate (percent, 0 to 100), control (true for the baseline), uplift (percent change of the conversion rate against the control, null for the control or when the control rate is 0), z, p_value and significant (true when p_value is below 0.05, using a two-proportion z-test). The control is the variant you pass in control, else one named control, else the variant with most visits. At most 20 variants, busiest first. Make sure the site sends the variant as an event property first. Takes the shared period and filters inputs. For a plain goal conversion rate use goals_get. Needs the Business or Enterprise plan (402 plan_limit otherwise).","tags":["Analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"property","in":"query","required":false,"schema":{"type":"string","description":"Event property that holds the variant name. Lowercase letters, digits and underscores, up to 64 characters, for example variant","examples":["variant"]}},{"name":"goal_id","in":"query","required":false,"schema":{"type":"string","description":"Active goal (goal_..., from goals_list) that counts as a conversion. Required"}},{"name":"control","in":"query","required":false,"schema":{"type":"string","description":"Variant name to use as the baseline. Defaults to a variant named control if present, otherwise the variant with the most visits"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"experiments_report","x-permission":"analytics.read"}},"/sites/{site_id}/insights.json":{"get":{"operationId":"insights_get","summary":"Notable changes vs the previous period, in plain English (biggest movers, goal conversion changes)","description":"Plain-English notable changes for a site, compared with the previous period of the same length. Returns period, comparison_period, insights and benchmarks. The period covers whole days up to yesterday, chosen with period (7d, 14d, 28d or 30d, default 7d). Each insight has dimension (total, channel, page, country or goal), metric, value, previous, current, change and sentence. change is a percent for counts and percentage points for goal conversion rate, and sentence is a ready-to-read English line. It includes total visitors and pageviews, the two biggest movers per dimension (changes of 20 percent or more with at least 10 visits or views) and goals whose conversion rate moved by half a point or more. Most important first, limited by limit (default 8, max 20). Results are kept for the day. For exact figures use stats_aggregate and stats_breakdown, and use this to find what changed. benchmarks compares the site with all sites on Privatus Analytics over the last 28 days, whatever the period: enabled (false when the workspace switched benchmarks off), days, computed_at and rows. Each row has metric (bounce_rate, homepage_bounce_rate, visit_duration, views_per_visit, LCP, INP, CLS, FCP or TTFB), unit (percent, ms or number), better (lower or higher), value (this site), low, median and high (the 25th, 50th and 75th percentile of all sites), percentile (the share of sites this site is higher than, from 5 to 95), standing (better, typical or worse) and sites (how many sites the benchmark comes from). A metric appears only when the site has enough data and enough sites are behind the benchmark, so rows can be empty.","tags":["Analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Length of the period in whole days ending yesterday, one of 7d (default), 14d, 28d or 30d. It is compared with the same number of days before it","enum":["7d","14d","28d","30d"],"default":"7d"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Maximum number of insights to return, 1 to 20. Default 8","default":8}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"insights_get","x-permission":"analytics.read"}},"/sites/{site_id}/journeys.json":{"get":{"operationId":"journeys_explore","summary":"Journeys: top 3-step paths after a page (or any entrance), or before a page or goal","description":"Explores the most common three-step page paths inside visits. In forward mode (default) it shows the paths after a start page given in path, or after any entrance when path is blank. In reverse mode it shows the paths leading to an end page (path) or to a goal (goal_id, which switches to reverse automatically). reverse needs path or goal_id. path must start with a slash. Returns period, mode, path, goal, sampled, sample_rate (percent), total_visits and the path graph with nodes and links per step, limited to limit pages per step (2 to 12, default 6). Above 100,000 visits the data is sampled. Page filters are ignored because they would cut paths short. Paths are built per visit, since no visitor id is stored. Takes the shared period, filters and segment inputs. For one page's neighbors use pages_detail, and for step conversion use funnels_get.","tags":["Analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"mode","in":"query","required":false,"schema":{"type":"string","description":"forward (default) shows the pages after the start page. reverse shows the pages leading to the end page or goal and needs path or goal_id","enum":["forward","reverse"],"default":"forward"}},{"name":"path","in":"query","required":false,"schema":{"type":"string","description":"Page path starting with a slash, for example /pricing. The start page in forward mode (blank means any entrance) or the end page in reverse mode"}},{"name":"goal_id","in":"query","required":false,"schema":{"type":"string","description":"Goal id (goal_..., from goals_list). Ends the journeys at this goal and switches to reverse mode"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Pages shown per step, 2 to 12. Default 6","default":6}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"journeys_explore","x-permission":"analytics.read"}},"/sites/{site_id}/pages/detail.json":{"get":{"operationId":"pages_detail","summary":"Page detail: metrics, previous and next pages, sources, Web Vitals, events and click map for one path","description":"One page in depth. Pass path (it must start with a slash, for example /pricing), exactly as stored (without query string or host). Returns period, path, url, metrics, previous_pages, next_pages, sources, vitals, events, clicks, goals, notes and audited_page_id (the id of this page in the latest finished site audit for site_audit_pages_get, null when that audit did not crawl the path). metrics has visitors, visits, pageviews, entrances, exits, entry_rate, exit_rate and bounce_rate (percents, 0 to 100), time_on_page (median milliseconds) and scroll_depth (median percent), the last two null with no engagement data. previous_pages and next_pages are the pages seen before and after in the same visit, as {value, count, share}, with (entrance) and (exit) as special values. sources has the top channels and referrers of visits that entered on this page. vitals has p75 values per Web Vital with ratings. events are custom events fired on the page, clicks are the most clicked element selectors, goals are goals completed on it and notes are annotations that mention it. Use stats_breakdown with dimension page to rank pages and referrers_detail for a referring site.","tags":["Analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"path","in":"query","required":false,"schema":{"type":"string","description":"Page path starting with a slash, exactly as stored (no host and no query string), for example /pricing. Required","examples":["/pricing"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"pages_detail","x-permission":"analytics.read"}},"/sites/{site_id}/referrers.json":{"get":{"operationId":"referrers_list","summary":"Referrers: the sites that link to this site, with visitors, engagement, kind of traffic and number of linking pages","description":"Ranks the external sites that sent visitors, with what each one sent. Direct visits (no referrer) are left out. Returns period, summary, channels, page, limit, has_more and rows. summary has visitors, visits, pageviews, bounce_rate (percent), visit_duration (median engaged milliseconds), revenue (minor units, cents), sites (number of referring sites) and share (percent of all visits that came from referrers). channels shows the kinds of traffic as {value, visitors, visits}. Each row has value (the referrer host), visitors, visits, pageviews, bounce_rate, visit_duration, revenue, channel (its usual channel), linking_pages (how many different pages of that site link here) and share (percent of referred visitors). Sort with sort (visitors, visits, pageviews or revenue, default visitors), narrow with search (text contained in the host), and page through with page and limit (max 100) while has_more is true. Use referrers_detail for one site. Takes the shared period, compare, filters and segment inputs.","tags":["Analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Referring sites per page, 1 to 100. Default 25","default":25}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","description":"Page number, starting at 1. Keep asking for the next page while has_more is true","default":1}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"Order by this metric. Default visitors","enum":["visitors","visits","pageviews","revenue"]}},{"name":"search","in":"query","required":false,"schema":{"type":"string","description":"Only referring sites whose host contains this text, case-insensitive","examples":["ycombinator"]}},{"name":"min_rating","in":"query","required":false,"schema":{"type":"integer","description":"Only referring sites whose domain has a Domain Rating of at least this, 0 to 100. Each row has its rating in domain_rating, null until the domain is rated. A site that is not rated yet is left out","examples":[50]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"referrers_list","x-permission":"analytics.read"}},"/sites/{site_id}/referrers/detail.json":{"get":{"operationId":"referrers_detail","summary":"Referrer detail: metrics and trend of one referring site, its linking pages, landing pages, countries, devices, campaigns and conversions","description":"One referring site in depth. Pass referrer as the host without www and without a path (for example news.ycombinator.com), the same value as in referrers_list. Returns period, referrer, url, channel (its most common channel), metrics, share (percent of all visits), interval, series (the traffic over time), linking_pages, landing_pages, channels, countries, devices, campaigns, goals and, with compare, comparison, change and comparison_series. metrics and series use the same fields and units as stats_aggregate and stats_timeseries. linking_pages are the referrer's pages that sent visitors, as rows with path, url, visitors and share (query strings are never stored). landing_pages are where those visitors entered. channels, countries, devices and campaigns are top values with metrics, and goals lists goals they completed with conversions and conversion_rate. Use referrers_list to rank referring sites and stats_breakdown with dimension referrer for a simple list.","tags":["Analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"referrer","in":"query","required":false,"schema":{"type":"string","description":"Referring site as a host without www and without a path, for example news.ycombinator.com. Take it from the value of a referrers_list row. Required","examples":["news.ycombinator.com"]}},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Chart bucket size. auto picks one to suit the range","enum":["auto","minute","hour","day","week","month","quarter","year"],"default":"auto"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"referrers_detail","x-permission":"analytics.read"}},"/sites/{site_id}/stats/aggregate.json":{"get":{"operationId":"stats_aggregate","summary":"Headline metrics for a period (with comparison)","description":"Headline numbers for one period, as one object. Returns period {from, to} and metrics {visitors, visits, pageviews, views_per_visit, bounce_rate, visit_duration, revenue}. With compare it also returns comparison_period, comparison (the same metrics for the other range) and change (percent change per metric, null when the earlier value was 0). Units: bounce_rate is a percent from 0 to 100 (10.9 means 10.9%). visit_duration is the median engaged time of a visit in milliseconds. revenue is an integer in minor units (cents) of the site currency. views_per_visit is a decimal. Visitors are counted per day because no persistent visitor id is stored, so someone who comes back on another day counts again. Use this for totals and period-over-period change. Use stats_timeseries for a chart over time, stats_breakdown for top values of a dimension, and stats_overview for all of it in one call. Narrow any of them with filters (see filters for the dimension names and operators).","tags":["Analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"stats_aggregate","x-permission":"analytics.read"}},"/sites/{site_id}/breakdown/{dimension}.json":{"get":{"operationId":"stats_breakdown","summary":"Top values of a dimension (pages, sources, countries…)","description":"Top values of one dimension with their metrics, most important first, paginated. The dimension is the last part of the path and must be an exact name from its description (for example country, page, channel, utm_campaign, prop:plan). Returns period, dimension, label, page, limit, has_more and rows. Ask for the next page while has_more is true. Every row has value and share (percent of the period total). The other fields of a row depend on the dimension. Visit dimensions (channel, referrer, referrer_url, utm_*, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score) give visitors, visits, pageviews, views_per_visit, bounce_rate, visit_duration and revenue. page gives pageviews, visits, time_on_page (milliseconds) and scroll_depth (percent), with no visitors. event and prop:<key> give completions, visits, revenue and conversion_rate. goal gives goal_id, completions, conversions, conversion_rate and revenue. Units: bounce_rate and conversion_rate are percents (0 to 100), durations are milliseconds, revenue is in minor units (cents). A wrong dimension returns a 422 that lists the valid names. Use search to look for a value across all rows, and filters to narrow the data first (for example pages visited by one country). For one page or one referrer in depth use pages_detail or referrers_detail. The interaction and bot_score dimensions need the Business or Enterprise plan: as a breakdown they respond with 402 plan_limit on other plans, and a filter on one is left out.","tags":["Analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"dimension","in":"path","required":true,"description":"What to group by: channel (traffic channel: paid_search, paid_social, paid_other, email, ai_assistants, organic_search, organic_social, internal, referral, direct, or a custom channel name), referrer (referring hostname such as news.ycombinator.com), referrer_url (referrer hostname plus path), utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref (the ref, via or source query parameter), hostname (the site hostname the visit was on), country (two-letter ISO code such as US), language (browser language such as en-US), device (desktop, mobile or tablet), browser (family such as Chrome), browser_version (family and major version such as Chrome 126), os (such as Windows, Mac, iOS or Android), os_version (such as iOS 18), screen (width bucket: xs under 414px, sm under 768, md under 1024, lg under 1440, xl above), page (a page path such as /pricing, no domain or query string), entry_page (first page of a visit), exit_page (last page of a visit), event (custom event name such as Signup), goal (one row per goal), prop:<key> (a custom event property such as prop:plan, keys come from event_properties_list), interaction (seen, none or unknown: whether a real user input was seen during the visit), bot_score (likely_human, unsure, likely_bot or not_scored: how likely the visit came from a bot. Visits are scored on plans with Advanced Bot Detection, from the day the plan starts). Each is also a valid filter dimension. Use the exact singular name (country, not countries)","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Rows per page, 1 to 1000 (default 10)","default":10}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","description":"Page number, from 1. has_more in the result says whether another page exists","default":1}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"Metric to sort by, highest first. Default is the main count of the dimension: visitors for visit dimensions, pageviews for page, completions for event, goal and prop:<key>","enum":["visitors","visits","pageviews","revenue"]}},{"name":"search","in":"query","required":false,"schema":{"type":"string","description":"Only rows whose value contains this text, in any letter case. It searches every value, not just the top rows. Not for goal","examples":["pricing"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"stats_breakdown","x-permission":"analytics.read"}},"/sites/{site_id}/stats/timeseries.json":{"get":{"operationId":"stats_timeseries","summary":"Metrics per time bucket for charts","description":"Metrics per time bucket, for charts and trends. Returns period, interval (the bucket actually used) and series, a list of {date, visitors, visits, pageviews, views_per_visit, bounce_rate, visit_duration, revenue}, one entry per bucket with date as the ISO 8601 start of the bucket. With compare it also returns comparison_series for the other range, bucket by bucket. Units are the same as stats_aggregate: bounce_rate is a percent (0 to 100), visit_duration is median engaged milliseconds, revenue is in minor units (cents). interval defaults to auto, which picks minute, hour, day, week or month to suit the range. Set it to force a bucket size. Use stats_aggregate for a single total and stats_breakdown to split by a dimension such as country or page.","tags":["Analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Bucket size: minute, hour, day, week, month, quarter or year. auto picks one that suits the range","enum":["auto","minute","hour","day","week","month","quarter","year"],"default":"auto"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"stats_timeseries","x-permission":"analytics.read"}},"/sites/{site_id}/ask.json":{"post":{"operationId":"assistant_ask","summary":"Ask a question in a new conversation (counts toward the monthly AI questions limit)","description":"Starts a new Ask conversation on one site and answers its first question using that site's analytics. Use it for a plain-English question about a site. Use assistant_ask_followup to continue an existing conversation and the stats tools when you already know the exact query. The answer is produced by an AI model that runs read-only analytics queries on its own, so the call can take many seconds. It counts as one AI question against the workspace's monthly allowance (5 on Free, 20 on Pro, 100 on Business) and fails with a limit error when the allowance is used up. The question can be at most 2,000 characters. Conversations are private to the member who started them and are deleted 30 days after their last message. Returns the conversation (id, site_id, title taken from the question, created_at, updated_at, expires_at) with a messages array. Each message has role (user or assistant), content (the answer text), queries (the exact analytics queries the assistant ran), chart (nullable chart definition), goal_draft (nullable suggested goal), token counts and created_at. If the answer fails the conversation is removed and no question is counted. Requires analytics.read.","tags":["Assistant"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Conversation id, e.g. ask_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site id"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"The first question, shortened"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time","description":"Time of the last message"},"expires_at":{"type":"string","format":"date-time","description":"Deleted automatically after this time (30 days after the last message)"},"messages":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Message id within the conversation"},"role":{"type":"string","description":"user (the question) or assistant (the answer)"},"content":{"type":"string","description":"Question, or the answer in Markdown"},"queries":{"type":"array","items":{"type":"object"},"description":"How I got this: the exact API queries behind the answer, as [{tool, input, status, error}]"},"chart":{"anyOf":[{"type":"object","description":"Chart of the answer: {type: line, labels, series, comparison, metric, format} or {type: table, columns, rows}"},{"type":"null"}]},"goal_draft":{"anyOf":[{"type":"object","description":"A goal proposed by the assistant, to confirm with goals_create"},{"type":"null"}]},"input_tokens":{"anyOf":[{"type":"integer","description":"Model input tokens used"},{"type":"null"}]},"output_tokens":{"anyOf":[{"type":"integer","description":"Model output tokens used"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}},"description":"Questions and answers, oldest first"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"assistant_ask","x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"question":{"type":"string","description":"Your first question in plain English about this site's analytics, at most 2,000 characters. Counts as one AI question against the monthly allowance.","examples":["How many visitors did we have last week?"]}},"required":["question"]}}}}},"get":{"operationId":"assistant_conversations_list","summary":"List your Ask conversations for a site","description":"Lists the signed-in member's Ask conversations on one site, most recently updated first. Conversations of other members are never shown. Use it to find a conversation id for assistant_conversations_get, assistant_ask_followup or assistant_conversations_delete. Each item has id, site_id, title (the first question, truncated to 80 characters), created_at, updated_at and expires_at but no messages. Paginated with page and per_page (maximum 100). Requires analytics.read.","tags":["Assistant"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Conversation id, e.g. ask_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site id"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"The first question, shortened"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time","description":"Time of the last message"},"expires_at":{"type":"string","format":"date-time","description":"Deleted automatically after this time (30 days after the last message)"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"assistant_conversations_list","x-permission":"analytics.read"}},"/sites/{site_id}/ask/{id}.json":{"delete":{"operationId":"assistant_conversations_delete","summary":"Delete an Ask conversation and its messages","description":"Permanently deletes one Ask conversation and all its messages right away. This cannot be undone. Get the conversation id from assistant_conversations_list. Only the member who started a conversation can see and delete it. Requires analytics.read and a site_id. Returns the deleted conversation summary (id, site_id, title, timestamps). It does not refund the AI questions already counted for the month.","tags":["Assistant"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by assistant_conversations_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Conversation id, e.g. ask_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site id"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"The first question, shortened"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time","description":"Time of the last message"},"expires_at":{"type":"string","format":"date-time","description":"Deleted automatically after this time (30 days after the last message)"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"assistant_conversations_delete","x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"assistant_conversations_get","summary":"An Ask conversation: questions, answers, the queries behind them and charts","description":"Returns one Ask conversation with its full message history. Get the conversation id from assistant_conversations_list or from the result of assistant_ask. Fields are id, site_id, title, created_at, updated_at, expires_at (30 days after the last message, then the conversation is deleted) and messages. Each message has role (user or assistant), content, queries (the analytics queries the assistant ran), chart (nullable), goal_draft (nullable) and input_tokens and output_tokens (nullable integers). Only the member who started the conversation can read it. Requires analytics.read.","tags":["Assistant"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by assistant_conversations_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Conversation id, e.g. ask_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site id"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"The first question, shortened"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time","description":"Time of the last message"},"expires_at":{"type":"string","format":"date-time","description":"Deleted automatically after this time (30 days after the last message)"},"messages":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Message id within the conversation"},"role":{"type":"string","description":"user (the question) or assistant (the answer)"},"content":{"type":"string","description":"Question, or the answer in Markdown"},"queries":{"type":"array","items":{"type":"object"},"description":"How I got this: the exact API queries behind the answer, as [{tool, input, status, error}]"},"chart":{"anyOf":[{"type":"object","description":"Chart of the answer: {type: line, labels, series, comparison, metric, format} or {type: table, columns, rows}"},{"type":"null"}]},"goal_draft":{"anyOf":[{"type":"object","description":"A goal proposed by the assistant, to confirm with goals_create"},{"type":"null"}]},"input_tokens":{"anyOf":[{"type":"integer","description":"Model input tokens used"},{"type":"null"}]},"output_tokens":{"anyOf":[{"type":"integer","description":"Model output tokens used"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}},"description":"Questions and answers, oldest first"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"assistant_conversations_get","x-permission":"analytics.read"}},"/sites/{site_id}/ask/{ask_conversation_id}/messages.json":{"post":{"operationId":"assistant_ask_followup","summary":"Ask a follow-up question in a conversation (counts toward the monthly AI questions limit). Returns the answer.","description":"Asks a follow-up question inside an existing Ask conversation, so the assistant keeps the earlier questions and answers as context. Use assistant_ask to start a new conversation instead. Get conversation_id from assistant_conversations_list. The call can take many seconds because the assistant runs read-only analytics queries. Each question counts against the workspace's monthly AI question allowance (5 on Free, 20 on Pro, 100 on Business) and fails with a limit error when it is used up. The question can be at most 2,000 characters. Returns only the new assistant message (not the whole conversation) with id, role, content (the answer), queries (the exact queries run), chart (nullable), goal_draft (nullable), input_tokens, output_tokens and created_at. Requires analytics.read and only works on your own conversations.","tags":["Assistant"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"ask_conversation_id","in":"path","required":true,"description":"Conversation id, from assistant_conversations_list or the result of assistant_ask","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Message id within the conversation"},"role":{"type":"string","description":"user (the question) or assistant (the answer)"},"content":{"type":"string","description":"Question, or the answer in Markdown"},"queries":{"type":"array","items":{"type":"object"},"description":"How I got this: the exact API queries behind the answer, as [{tool, input, status, error}]"},"chart":{"anyOf":[{"type":"object","description":"Chart of the answer: {type: line, labels, series, comparison, metric, format} or {type: table, columns, rows}"},{"type":"null"}]},"goal_draft":{"anyOf":[{"type":"object","description":"A goal proposed by the assistant, to confirm with goals_create"},{"type":"null"}]},"input_tokens":{"anyOf":[{"type":"integer","description":"Model input tokens used"},{"type":"null"}]},"output_tokens":{"anyOf":[{"type":"integer","description":"Model output tokens used"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"assistant_ask_followup","x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"question":{"type":"string","description":"Your follow-up question in plain English, at most 2,000 characters. Counts as one AI question against the monthly allowance.","examples":["Which pages had the most visitors last week?"]}},"required":["question"]}}}}}},"/workspaces/{workspace_id}/audit_log.json":{"get":{"operationId":"audit_logs_get","summary":"List audit log entries (add .csv to export)","description":"Returns the workspace audit log, a newest-first, paginated record of who changed what (settings, members, sites, goals, tokens and so on). It needs the workspace.manage permission and a plan with audit history. The Free plan has none and the call fails with a plan-limit error, Pro keeps 30 days, Business 365 days and Enterprise has no limit. Entries older than the retention window are never returned. Filter with actor (a member's email, exact match), item_type (the record kind such as Site, Goal or Membership), event (create, update or destroy), and from and to (YYYY-MM-DD, inclusive, in UTC). Each entry has id, created_at, event, item_type, item_id, target (a readable label such as Site: example.com), actor_email (null when the change was made by the system or by a deleted user), actor_name, token_name (the API token used, null for a browser session), changes (an object mapping each changed field to a [before, after] pair, with secrets removed), and ip (the address the member or API client used, null when unknown). A CSV export of the same log is available in the app only.","tags":["Audit log"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"actor","in":"query","required":false,"schema":{"type":"string","description":"Only changes made by the member with this exact email address."}},{"name":"item_type","in":"query","required":false,"schema":{"type":"string","description":"Only this kind of record, using its class name such as Site, Goal, Membership, Role or ApiToken."}},{"name":"event","in":"query","required":false,"schema":{"type":"string","description":"Only this action, one of create, update or destroy.","enum":["create","update","destroy"]}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day to include, YYYY-MM-DD in UTC. Entries older than the plan's retention are never returned."}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day to include, YYYY-MM-DD in UTC."}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"created_at":{"type":"string","format":"date-time","description":"When"},"event":{"type":"string","description":"create, update or destroy"},"item_type":{"type":"string","description":"Kind of record, e.g. Site"},"item_id":{"type":"string","format":"uuid"},"target":{"type":"string","description":"The record, by name where known"},"actor_email":{"anyOf":[{"type":"string","description":"Member who made the change"},{"type":"null"}]},"actor_name":{"type":"string"},"token_name":{"anyOf":[{"type":"string","description":"API token used, if any"},{"type":"null"}]},"changes":{"type":"object","description":"Changed fields: { field: [before, after] }"},"ip":{"anyOf":[{"type":"string","description":"The member's IP address"},{"type":"null"}]}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"audit_logs_get","x-permission":"workspace.manage"}},"/workspaces/{workspace_id}/billing/badge.json":{"post":{"operationId":"billing_badge","summary":"Opt in or out of the badge bonus (free plan)","description":"Opts a Free workspace in or out of the Privatus Analytics badge bonus, which raises the monthly event allowance. Set enabled to true to opt in. A background check then looks for the badge on the workspace's sites and verifies it, which can take a moment, so read billing_get afterwards and look at badge.verified_at. Set enabled to false to opt out, which clears the check and verification dates and removes the bonus. Opting in on a Pro or Business workspace is refused because paid plans have no bonus. Returns the workspace billing object like billing_get. Requires billing.manage.","tags":["Billing"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"workspace_id":{"type":"string"},"plan":{"type":"string","description":"free, pro, business or enterprise"},"plan_events":{"type":"integer","description":"Events a month in the paid tier"},"allowance":{"type":"integer","description":"Events a month including any badge bonus"},"billing_interval":{"anyOf":[{"type":"string","description":"month or year"},{"type":"null"}]},"price":{"anyOf":[{"type":"integer","description":"USD per billing interval"},{"type":"null"}]},"subscription_status":{"type":"string","description":"none, trialing, active, past_due, paused or canceled"},"current_period_ends_at":{"anyOf":[{"type":"string","format":"date-time","description":"Renews or ends at"},{"type":"null"}]},"cancel_at_period_end":{"type":"boolean"},"canceled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"auto_upgrade":{"type":"boolean"},"discount":{"anyOf":[{"type":"object","properties":{"program":{"type":"string","description":"nonprofit, education, open_source, open_source_free or agency"},"status":{"type":"string","description":"pending, approved (not yet on the subscription), active, rejected or revoked"},"percent":{"anyOf":[{"type":"integer","description":"Percent off Pro and Business (null for the free open-source program)"},{"type":"null"}]},"comp_events":{"anyOf":[{"type":"integer","description":"Free events a month (free open-source program only)"},{"type":"null"}]},"organization_name":{"type":"string","description":"Organization, school, project or agency name"},"website":{"anyOf":[{"type":"string","description":"Website"},{"type":"null"}]},"proof_url":{"anyOf":[{"type":"string","description":"Proof link or repository URL"},{"type":"null"}]},"license":{"anyOf":[{"type":"string","description":"OSI license (open source)"},{"type":"null"}]},"note":{"anyOf":[{"type":"string","description":"Note for the review"},{"type":"null"}]},"rejection_reason":{"anyOf":[{"type":"string","description":"Why the application was not approved"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"Applied at"},"reviewed_at":{"anyOf":[{"type":"string","format":"date-time","description":"Reviewed at"},{"type":"null"}]},"applied_at":{"anyOf":[{"type":"string","format":"date-time","description":"Discount active since"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string","format":"date-time","description":"Program ended at"},{"type":"null"}]}},"description":"The latest discount program application, or null"},{"type":"null"}]},"discount_percent":{"anyOf":[{"type":"integer","description":"Percent off Pro and Business from an approved program, or null"},{"type":"null"}]},"billing_emails":{"type":"array","items":{"type":"string"}},"tax_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"badge":{"type":"object","description":"Badge bonus (free plan)"},"usage":{"type":"object","properties":{"month":{"type":"string","format":"date","description":"First day of the month reported"},"events":{"type":"integer","description":"Billable events (pageviews and custom events)"},"bots":{"type":"integer","description":"Bot hits filtered out (not billed)"},"allowance":{"type":"integer","description":"Events included, with any badge bonus"},"percent":{"type":"number","description":"Events as a percent of the allowance"},"forecast":{"anyOf":[{"type":"integer","description":"Projected events at month end"},{"type":"null"}]},"forecast_percent":{"anyOf":[{"type":"number"},{"type":"null"}]},"days_left":{"type":"integer","description":"Days left in the month"},"status":{"type":"string","description":"ok, warning (80%+), over (a past month at or over the allowance), locked or paused"},"sites":{"type":"array","items":{"type":"object","properties":{"site_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"events":{"type":"integer","description":"Pageviews and custom events this month"},"share":{"type":"number","description":"Percent of the workspace total"}}},"description":"Events by site"},"history":{"type":"array","description":"Previous months, newest first"},"access_locked_at":{"anyOf":[{"type":"string","format":"date-time","description":"Dashboards locked by Privatus Analytics staff since"},{"type":"null"}]},"collection_paused":{"type":"boolean","description":"True while new events are dropped (the monthly limit is reached, or staff paused collection)"},"pause_reason":{"anyOf":[{"type":"string","description":"Why collection is paused: limit (the monthly allowance is reached) or staff. null when collecting"},{"type":"null"}]},"collection_paused_at":{"anyOf":[{"type":"string","format":"date-time","description":"When staff paused collection"},{"type":"null"}]},"resumes_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a limit pause lifts: the start of next month (UTC), or earlier on an upgrade. null otherwise"},{"type":"null"}]}},"description":"This month so far"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"billing.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","description":"true to opt in, which starts a check for the badge on your sites and adds the bonus once verified. false to opt out and remove the bonus. Only Free workspaces can opt in."}},"required":["enabled"]}}}}}},"/workspaces/{workspace_id}/billing/cancel.json":{"post":{"operationId":"billing_cancel","summary":"Cancel at the end of the billing period","description":"Cancels the paid subscription at the end of the current paid period. Nothing is refunded and the plan stays active until current_period_ends_at, after which the workspace moves to the Free plan. Use billing_resume to undo it before then. Fails when the workspace has no subscription or a cancellation is already scheduled. The optional reason (one of the enum values) and comment are an exit survey. A comment, if given, is emailed to the Privatus Analytics team as a feedback message from the member and is not stored. Returns the billing object with cancel_at_period_end true. Requires billing.manage.","tags":["Billing"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"workspace_id":{"type":"string"},"plan":{"type":"string","description":"free, pro, business or enterprise"},"plan_events":{"type":"integer","description":"Events a month in the paid tier"},"allowance":{"type":"integer","description":"Events a month including any badge bonus"},"billing_interval":{"anyOf":[{"type":"string","description":"month or year"},{"type":"null"}]},"price":{"anyOf":[{"type":"integer","description":"USD per billing interval"},{"type":"null"}]},"subscription_status":{"type":"string","description":"none, trialing, active, past_due, paused or canceled"},"current_period_ends_at":{"anyOf":[{"type":"string","format":"date-time","description":"Renews or ends at"},{"type":"null"}]},"cancel_at_period_end":{"type":"boolean"},"canceled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"auto_upgrade":{"type":"boolean"},"discount":{"anyOf":[{"type":"object","properties":{"program":{"type":"string","description":"nonprofit, education, open_source, open_source_free or agency"},"status":{"type":"string","description":"pending, approved (not yet on the subscription), active, rejected or revoked"},"percent":{"anyOf":[{"type":"integer","description":"Percent off Pro and Business (null for the free open-source program)"},{"type":"null"}]},"comp_events":{"anyOf":[{"type":"integer","description":"Free events a month (free open-source program only)"},{"type":"null"}]},"organization_name":{"type":"string","description":"Organization, school, project or agency name"},"website":{"anyOf":[{"type":"string","description":"Website"},{"type":"null"}]},"proof_url":{"anyOf":[{"type":"string","description":"Proof link or repository URL"},{"type":"null"}]},"license":{"anyOf":[{"type":"string","description":"OSI license (open source)"},{"type":"null"}]},"note":{"anyOf":[{"type":"string","description":"Note for the review"},{"type":"null"}]},"rejection_reason":{"anyOf":[{"type":"string","description":"Why the application was not approved"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"Applied at"},"reviewed_at":{"anyOf":[{"type":"string","format":"date-time","description":"Reviewed at"},{"type":"null"}]},"applied_at":{"anyOf":[{"type":"string","format":"date-time","description":"Discount active since"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string","format":"date-time","description":"Program ended at"},{"type":"null"}]}},"description":"The latest discount program application, or null"},{"type":"null"}]},"discount_percent":{"anyOf":[{"type":"integer","description":"Percent off Pro and Business from an approved program, or null"},{"type":"null"}]},"billing_emails":{"type":"array","items":{"type":"string"}},"tax_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"badge":{"type":"object","description":"Badge bonus (free plan)"},"usage":{"type":"object","properties":{"month":{"type":"string","format":"date","description":"First day of the month reported"},"events":{"type":"integer","description":"Billable events (pageviews and custom events)"},"bots":{"type":"integer","description":"Bot hits filtered out (not billed)"},"allowance":{"type":"integer","description":"Events included, with any badge bonus"},"percent":{"type":"number","description":"Events as a percent of the allowance"},"forecast":{"anyOf":[{"type":"integer","description":"Projected events at month end"},{"type":"null"}]},"forecast_percent":{"anyOf":[{"type":"number"},{"type":"null"}]},"days_left":{"type":"integer","description":"Days left in the month"},"status":{"type":"string","description":"ok, warning (80%+), over (a past month at or over the allowance), locked or paused"},"sites":{"type":"array","items":{"type":"object","properties":{"site_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"events":{"type":"integer","description":"Pageviews and custom events this month"},"share":{"type":"number","description":"Percent of the workspace total"}}},"description":"Events by site"},"history":{"type":"array","description":"Previous months, newest first"},"access_locked_at":{"anyOf":[{"type":"string","format":"date-time","description":"Dashboards locked by Privatus Analytics staff since"},{"type":"null"}]},"collection_paused":{"type":"boolean","description":"True while new events are dropped (the monthly limit is reached, or staff paused collection)"},"pause_reason":{"anyOf":[{"type":"string","description":"Why collection is paused: limit (the monthly allowance is reached) or staff. null when collecting"},{"type":"null"}]},"collection_paused_at":{"anyOf":[{"type":"string","format":"date-time","description":"When staff paused collection"},{"type":"null"}]},"resumes_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a limit pause lifts: the start of next month (UTC), or earlier on an upgrade. null otherwise"},{"type":"null"}]}},"description":"This month so far"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"billing.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","description":"Optional exit survey reason, one of too_expensive, missing_features, switching_tool, not_using, temporary or other.","enum":["too_expensive","missing_features","switching_tool","not_using","temporary","other"]},"comment":{"type":"string","description":"Optional free text about what we could do better. It is emailed to the team and not stored."}}}}}}}},"/workspaces/{workspace_id}/billing/change_plan.json":{"post":{"operationId":"billing_change_plan","summary":"Change plan, tier or interval (prorated)","description":"Moves the existing subscription to another plan, event tier or billing interval. This charges money. The change takes effect immediately and Paddle prorates it, so a charge or credit is applied to the payment method on file right away. Run billing_preview first with the same inputs to see the exact amounts. Fails if the workspace has no subscription (use billing_checkout for that), if the target is the current plan, tier and interval, or if no price exists for the plan and events combination. The events value must be one of the tiers from plans_list. Returns the updated billing object. Requires billing.manage.","tags":["Billing"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"workspace_id":{"type":"string"},"plan":{"type":"string","description":"free, pro, business or enterprise"},"plan_events":{"type":"integer","description":"Events a month in the paid tier"},"allowance":{"type":"integer","description":"Events a month including any badge bonus"},"billing_interval":{"anyOf":[{"type":"string","description":"month or year"},{"type":"null"}]},"price":{"anyOf":[{"type":"integer","description":"USD per billing interval"},{"type":"null"}]},"subscription_status":{"type":"string","description":"none, trialing, active, past_due, paused or canceled"},"current_period_ends_at":{"anyOf":[{"type":"string","format":"date-time","description":"Renews or ends at"},{"type":"null"}]},"cancel_at_period_end":{"type":"boolean"},"canceled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"auto_upgrade":{"type":"boolean"},"discount":{"anyOf":[{"type":"object","properties":{"program":{"type":"string","description":"nonprofit, education, open_source, open_source_free or agency"},"status":{"type":"string","description":"pending, approved (not yet on the subscription), active, rejected or revoked"},"percent":{"anyOf":[{"type":"integer","description":"Percent off Pro and Business (null for the free open-source program)"},{"type":"null"}]},"comp_events":{"anyOf":[{"type":"integer","description":"Free events a month (free open-source program only)"},{"type":"null"}]},"organization_name":{"type":"string","description":"Organization, school, project or agency name"},"website":{"anyOf":[{"type":"string","description":"Website"},{"type":"null"}]},"proof_url":{"anyOf":[{"type":"string","description":"Proof link or repository URL"},{"type":"null"}]},"license":{"anyOf":[{"type":"string","description":"OSI license (open source)"},{"type":"null"}]},"note":{"anyOf":[{"type":"string","description":"Note for the review"},{"type":"null"}]},"rejection_reason":{"anyOf":[{"type":"string","description":"Why the application was not approved"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"Applied at"},"reviewed_at":{"anyOf":[{"type":"string","format":"date-time","description":"Reviewed at"},{"type":"null"}]},"applied_at":{"anyOf":[{"type":"string","format":"date-time","description":"Discount active since"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string","format":"date-time","description":"Program ended at"},{"type":"null"}]}},"description":"The latest discount program application, or null"},{"type":"null"}]},"discount_percent":{"anyOf":[{"type":"integer","description":"Percent off Pro and Business from an approved program, or null"},{"type":"null"}]},"billing_emails":{"type":"array","items":{"type":"string"}},"tax_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"badge":{"type":"object","description":"Badge bonus (free plan)"},"usage":{"type":"object","properties":{"month":{"type":"string","format":"date","description":"First day of the month reported"},"events":{"type":"integer","description":"Billable events (pageviews and custom events)"},"bots":{"type":"integer","description":"Bot hits filtered out (not billed)"},"allowance":{"type":"integer","description":"Events included, with any badge bonus"},"percent":{"type":"number","description":"Events as a percent of the allowance"},"forecast":{"anyOf":[{"type":"integer","description":"Projected events at month end"},{"type":"null"}]},"forecast_percent":{"anyOf":[{"type":"number"},{"type":"null"}]},"days_left":{"type":"integer","description":"Days left in the month"},"status":{"type":"string","description":"ok, warning (80%+), over (a past month at or over the allowance), locked or paused"},"sites":{"type":"array","items":{"type":"object","properties":{"site_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"events":{"type":"integer","description":"Pageviews and custom events this month"},"share":{"type":"number","description":"Percent of the workspace total"}}},"description":"Events by site"},"history":{"type":"array","description":"Previous months, newest first"},"access_locked_at":{"anyOf":[{"type":"string","format":"date-time","description":"Dashboards locked by Privatus Analytics staff since"},{"type":"null"}]},"collection_paused":{"type":"boolean","description":"True while new events are dropped (the monthly limit is reached, or staff paused collection)"},"pause_reason":{"anyOf":[{"type":"string","description":"Why collection is paused: limit (the monthly allowance is reached) or staff. null when collecting"},{"type":"null"}]},"collection_paused_at":{"anyOf":[{"type":"string","format":"date-time","description":"When staff paused collection"},{"type":"null"}]},"resumes_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a limit pause lifts: the start of next month (UTC), or earlier on an upgrade. null otherwise"},{"type":"null"}]}},"description":"This month so far"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"billing.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string","description":"Paid plan to buy or switch to, pro or business.","enum":["pro","business"]},"events":{"type":"integer","description":"Events a month of the tier, a whole number exactly as listed in the tiers of plans_list, for example 250000, 1000000 or 10000000. Any other number is rejected.","examples":[1000000]},"interval":{"type":"string","description":"Billing interval, month or year. Yearly costs 10 times the monthly amount (2 months free). Defaults to month.","enum":["month","year"],"default":"month"}},"required":["plan","events"]}}}}}},"/workspaces/{workspace_id}/billing/checkout.json":{"post":{"operationId":"billing_checkout","summary":"Start a Paddle checkout for a paid plan","description":"Starts a Paddle checkout for a workspace that has no subscription yet and returns a hosted checkout URL. Nothing is charged until a person completes the checkout in a browser, so give the url to the person. Use billing_change_plan instead when the workspace already has a subscription. Inputs are plan (pro or business), events (an events a month tier from plans_list) and interval (month or year, default month). Prices include VAT or sales tax. An approved discount program is applied automatically and reported in discount_id. Returns transaction_id, url (nullable), price_id, plan, events, interval, amount (whole USD for the interval), client_token and environment (sandbox or production, used by the Paddle overlay), custom_data and discount_id (nullable). Fails if the workspace already has a subscription. Requires billing.manage.","tags":["Billing"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"transaction_id":{"type":"string","description":"Paddle transaction id (txn_...)"},"url":{"anyOf":[{"type":"string","description":"Hosted checkout URL"},{"type":"null"}]},"price_id":{"type":"string"},"plan":{"type":"string"},"events":{"type":"integer"},"interval":{"type":"string"},"amount":{"type":"integer","description":"USD per interval"},"client_token":{"anyOf":[{"type":"string","description":"Paddle.js client-side token"},{"type":"null"}]},"environment":{"type":"string","description":"sandbox or production"},"custom_data":{"type":"object","description":"Passed to Paddle to link the subscription"},"discount_id":{"anyOf":[{"type":"string","description":"Paddle discount id of an approved program, applied to this checkout"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"billing.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string","description":"Paid plan to buy or switch to, pro or business.","enum":["pro","business"]},"events":{"type":"integer","description":"Events a month of the tier, a whole number exactly as listed in the tiers of plans_list, for example 250000, 1000000 or 10000000. Any other number is rejected.","examples":[1000000]},"interval":{"type":"string","description":"Billing interval, month or year. Yearly costs 10 times the monthly amount (2 months free). Defaults to month.","enum":["month","year"],"default":"month"}},"required":["plan","events"]}}}}}},"/workspaces/{workspace_id}/billing/discount.json":{"post":{"operationId":"billing_discount","summary":"Apply for a discount program (nonprofit, education, open source or agency)","description":"Applies for a discount program for the workspace. This submits an application for staff review and emails the Privatus Analytics team, it does not grant a discount by itself. Programs are nonprofit, education, open_source (50 percent off), open_source_free (free Pro up to 1M events a month) and agency (20 percent off every workspace you own). Only one open application (pending, approved or active) is allowed per workspace, and you can apply again after a rejection or revocation. license is kept only for the two open source programs. Returns the application with program, status, percent, comp_events (nullable), organization_name, website, proof_url, license, note, rejection_reason, created_at, reviewed_at, applied_at and revoked_at (nullable timestamps). Check progress later in the discount field of billing_get. Requires billing.manage.","tags":["Billing"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"program":{"type":"string","description":"nonprofit, education, open_source, open_source_free or agency"},"status":{"type":"string","description":"pending, approved (not yet on the subscription), active, rejected or revoked"},"percent":{"anyOf":[{"type":"integer","description":"Percent off Pro and Business (null for the free open-source program)"},{"type":"null"}]},"comp_events":{"anyOf":[{"type":"integer","description":"Free events a month (free open-source program only)"},{"type":"null"}]},"organization_name":{"type":"string","description":"Organization, school, project or agency name"},"website":{"anyOf":[{"type":"string","description":"Website"},{"type":"null"}]},"proof_url":{"anyOf":[{"type":"string","description":"Proof link or repository URL"},{"type":"null"}]},"license":{"anyOf":[{"type":"string","description":"OSI license (open source)"},{"type":"null"}]},"note":{"anyOf":[{"type":"string","description":"Note for the review"},{"type":"null"}]},"rejection_reason":{"anyOf":[{"type":"string","description":"Why the application was not approved"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"Applied at"},"reviewed_at":{"anyOf":[{"type":"string","format":"date-time","description":"Reviewed at"},{"type":"null"}]},"applied_at":{"anyOf":[{"type":"string","format":"date-time","description":"Discount active since"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string","format":"date-time","description":"Program ended at"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"billing.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"program":{"type":"string","description":"Program to apply for, one of nonprofit, education, open_source (50% off), open_source_free (free Pro up to 1M events a month) or agency (20% off every workspace you own). One open application per workspace.","enum":["nonprofit","education","open_source","open_source_free","agency"]},"organization_name":{"type":"string","description":"Name of the organization, school, project or agency"},"website":{"type":"string","description":"Its website"},"proof_url":{"type":"string","description":"Public https link that proves eligibility, for example a registry page, an accreditation page or, for open source, the repository URL."},"license":{"type":"string","description":"OSI license identifier of the project, for example MIT or Apache-2.0. Only used for open_source and open_source_free, ignored otherwise."},"note":{"type":"string","description":"Anything that helps the review, up to 1,000 characters"}},"required":["program","organization_name"]}}}}}},"/workspaces/{workspace_id}/billing/payment_method.json":{"post":{"operationId":"billing_payment_method","summary":"Get a link to update the payment method","description":"Returns a Paddle link where a person can update the subscription's payment method. Nothing is changed by the call itself. Give the url to the person to open in a browser. The result has kind (payment_method) and url. Fails when the workspace has no active subscription. For invoices, addresses and every other billing detail use billing_portal. Requires billing.manage.","tags":["Billing"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"kind":{"type":"string","description":"portal, payment_method or invoice"},"url":{"anyOf":[{"type":"string","description":"Short-lived Paddle URL"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"billing.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/workspaces/{workspace_id}/billing/portal.json":{"post":{"operationId":"billing_portal","summary":"Get a Paddle customer portal link","description":"Returns a link to the Paddle customer portal, where a person can see invoices, payment methods and addresses. Nothing is changed by the call itself. Give the url to the person to open in a browser, The result has kind (portal) and url. Fails if the workspace has no Paddle customer yet (it never checked out) or when the customer is shared with other workspaces the caller cannot access, because the portal exposes all of the customer's data. Use billing_payment_method for just the card. Requires billing.manage.","tags":["Billing"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"kind":{"type":"string","description":"portal, payment_method or invoice"},"url":{"anyOf":[{"type":"string","description":"Short-lived Paddle URL"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"billing.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/workspaces/{workspace_id}/billing/preview.json":{"get":{"operationId":"billing_preview","summary":"Preview a plan change with proration","description":"Shows what moving the subscription to another plan, tier or interval would cost right now, without changing anything. Always run it before billing_change_plan with the same plan, events and interval inputs. Fails if the workspace has no subscription or the target equals the current price. Returns plan, events, interval, price_id, amount (whole USD list price for the interval), currency, charge_minor (what would be charged now), credit_minor (credit for unused time) and result_minor (net amount) all in minor currency units, result_action (charge or credit, nullable), next_billed_at (nullable) and warnings (strings, for example last month's usage exceeding the new tier or plan limits such as sites or members that the new plan would break). Requires billing.manage.","tags":["Billing"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"plan","in":"query","required":false,"schema":{"type":"string","description":"Paid plan to buy or switch to, pro or business.","enum":["pro","business"]}},{"name":"events","in":"query","required":false,"schema":{"type":"integer","description":"Events a month of the tier, a whole number exactly as listed in the tiers of plans_list, for example 250000, 1000000 or 10000000. Any other number is rejected.","examples":[1000000]}},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Billing interval, month or year. Yearly costs 10 times the monthly amount (2 months free). Defaults to month.","enum":["month","year"],"default":"month"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"plan":{"type":"string"},"events":{"type":"integer"},"interval":{"type":"string"},"price_id":{"type":"string"},"amount":{"type":"integer","description":"New price in USD per interval"},"currency":{"type":"string"},"charge_minor":{"type":"integer","description":"Charged now, in minor units"},"credit_minor":{"type":"integer","description":"Credit for unused time, minor units"},"result_action":{"anyOf":[{"type":"string","description":"charge or credit"},{"type":"null"}]},"result_minor":{"type":"integer","description":"Net charge or credit, minor units"},"next_billed_at":{"anyOf":[{"type":"string"},{"type":"null"}]},"warnings":{"type":"array","items":{"type":"string"},"description":"Usage or limits the new plan would not cover"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"billing_preview","x-permission":"billing.manage"}},"/workspaces/{workspace_id}/billing/resume.json":{"post":{"operationId":"billing_resume","summary":"Undo a scheduled cancellation or resume a pause","description":"Undoes a scheduled cancellation, or resumes a paused subscription, so the plan keeps renewing. Use it after billing_cancel and before current_period_ends_at. A paused subscription resumes immediately. Fails when there is no scheduled cancellation and the subscription is not paused. Returns the updated billing object. Requires billing.manage.","tags":["Billing"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"workspace_id":{"type":"string"},"plan":{"type":"string","description":"free, pro, business or enterprise"},"plan_events":{"type":"integer","description":"Events a month in the paid tier"},"allowance":{"type":"integer","description":"Events a month including any badge bonus"},"billing_interval":{"anyOf":[{"type":"string","description":"month or year"},{"type":"null"}]},"price":{"anyOf":[{"type":"integer","description":"USD per billing interval"},{"type":"null"}]},"subscription_status":{"type":"string","description":"none, trialing, active, past_due, paused or canceled"},"current_period_ends_at":{"anyOf":[{"type":"string","format":"date-time","description":"Renews or ends at"},{"type":"null"}]},"cancel_at_period_end":{"type":"boolean"},"canceled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"auto_upgrade":{"type":"boolean"},"discount":{"anyOf":[{"type":"object","properties":{"program":{"type":"string","description":"nonprofit, education, open_source, open_source_free or agency"},"status":{"type":"string","description":"pending, approved (not yet on the subscription), active, rejected or revoked"},"percent":{"anyOf":[{"type":"integer","description":"Percent off Pro and Business (null for the free open-source program)"},{"type":"null"}]},"comp_events":{"anyOf":[{"type":"integer","description":"Free events a month (free open-source program only)"},{"type":"null"}]},"organization_name":{"type":"string","description":"Organization, school, project or agency name"},"website":{"anyOf":[{"type":"string","description":"Website"},{"type":"null"}]},"proof_url":{"anyOf":[{"type":"string","description":"Proof link or repository URL"},{"type":"null"}]},"license":{"anyOf":[{"type":"string","description":"OSI license (open source)"},{"type":"null"}]},"note":{"anyOf":[{"type":"string","description":"Note for the review"},{"type":"null"}]},"rejection_reason":{"anyOf":[{"type":"string","description":"Why the application was not approved"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"Applied at"},"reviewed_at":{"anyOf":[{"type":"string","format":"date-time","description":"Reviewed at"},{"type":"null"}]},"applied_at":{"anyOf":[{"type":"string","format":"date-time","description":"Discount active since"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string","format":"date-time","description":"Program ended at"},{"type":"null"}]}},"description":"The latest discount program application, or null"},{"type":"null"}]},"discount_percent":{"anyOf":[{"type":"integer","description":"Percent off Pro and Business from an approved program, or null"},{"type":"null"}]},"billing_emails":{"type":"array","items":{"type":"string"}},"tax_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"badge":{"type":"object","description":"Badge bonus (free plan)"},"usage":{"type":"object","properties":{"month":{"type":"string","format":"date","description":"First day of the month reported"},"events":{"type":"integer","description":"Billable events (pageviews and custom events)"},"bots":{"type":"integer","description":"Bot hits filtered out (not billed)"},"allowance":{"type":"integer","description":"Events included, with any badge bonus"},"percent":{"type":"number","description":"Events as a percent of the allowance"},"forecast":{"anyOf":[{"type":"integer","description":"Projected events at month end"},{"type":"null"}]},"forecast_percent":{"anyOf":[{"type":"number"},{"type":"null"}]},"days_left":{"type":"integer","description":"Days left in the month"},"status":{"type":"string","description":"ok, warning (80%+), over (a past month at or over the allowance), locked or paused"},"sites":{"type":"array","items":{"type":"object","properties":{"site_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"events":{"type":"integer","description":"Pageviews and custom events this month"},"share":{"type":"number","description":"Percent of the workspace total"}}},"description":"Events by site"},"history":{"type":"array","description":"Previous months, newest first"},"access_locked_at":{"anyOf":[{"type":"string","format":"date-time","description":"Dashboards locked by Privatus Analytics staff since"},{"type":"null"}]},"collection_paused":{"type":"boolean","description":"True while new events are dropped (the monthly limit is reached, or staff paused collection)"},"pause_reason":{"anyOf":[{"type":"string","description":"Why collection is paused: limit (the monthly allowance is reached) or staff. null when collecting"},{"type":"null"}]},"collection_paused_at":{"anyOf":[{"type":"string","format":"date-time","description":"When staff paused collection"},{"type":"null"}]},"resumes_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a limit pause lifts: the start of next month (UTC), or earlier on an upgrade. null otherwise"},{"type":"null"}]}},"description":"This month so far"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"billing.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/workspaces/{workspace_id}/billing.json":{"get":{"operationId":"billing_get","summary":"Get the plan, subscription and usage","description":"Returns the workspace's plan and billing state. Use it before changing anything in billing, and to learn whether the subscription is active or cancelling. Fields include workspace_id, plan (free, pro, business or enterprise), plan_events (the sold events a month tier), allowance (events a month actually allowed, including any badge bonus), billing_interval (month or year, nullable), price (whole USD for the interval, nullable), subscription_status, current_period_ends_at, cancel_at_period_end (true when a cancellation is scheduled), canceled_at, auto_upgrade, discount (the latest discount application, nullable), discount_percent, billing_emails (array), tax_id, badge (opted_in, verified_at, checked_at and the bonus size) and usage (the same object billing_usage returns). Requires billing.manage. Invoices are in billing_invoices_list and a month-by-month usage view is billing_usage.","tags":["Billing"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"workspace_id":{"type":"string"},"plan":{"type":"string","description":"free, pro, business or enterprise"},"plan_events":{"type":"integer","description":"Events a month in the paid tier"},"allowance":{"type":"integer","description":"Events a month including any badge bonus"},"billing_interval":{"anyOf":[{"type":"string","description":"month or year"},{"type":"null"}]},"price":{"anyOf":[{"type":"integer","description":"USD per billing interval"},{"type":"null"}]},"subscription_status":{"type":"string","description":"none, trialing, active, past_due, paused or canceled"},"current_period_ends_at":{"anyOf":[{"type":"string","format":"date-time","description":"Renews or ends at"},{"type":"null"}]},"cancel_at_period_end":{"type":"boolean"},"canceled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"auto_upgrade":{"type":"boolean"},"discount":{"anyOf":[{"type":"object","properties":{"program":{"type":"string","description":"nonprofit, education, open_source, open_source_free or agency"},"status":{"type":"string","description":"pending, approved (not yet on the subscription), active, rejected or revoked"},"percent":{"anyOf":[{"type":"integer","description":"Percent off Pro and Business (null for the free open-source program)"},{"type":"null"}]},"comp_events":{"anyOf":[{"type":"integer","description":"Free events a month (free open-source program only)"},{"type":"null"}]},"organization_name":{"type":"string","description":"Organization, school, project or agency name"},"website":{"anyOf":[{"type":"string","description":"Website"},{"type":"null"}]},"proof_url":{"anyOf":[{"type":"string","description":"Proof link or repository URL"},{"type":"null"}]},"license":{"anyOf":[{"type":"string","description":"OSI license (open source)"},{"type":"null"}]},"note":{"anyOf":[{"type":"string","description":"Note for the review"},{"type":"null"}]},"rejection_reason":{"anyOf":[{"type":"string","description":"Why the application was not approved"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"Applied at"},"reviewed_at":{"anyOf":[{"type":"string","format":"date-time","description":"Reviewed at"},{"type":"null"}]},"applied_at":{"anyOf":[{"type":"string","format":"date-time","description":"Discount active since"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string","format":"date-time","description":"Program ended at"},{"type":"null"}]}},"description":"The latest discount program application, or null"},{"type":"null"}]},"discount_percent":{"anyOf":[{"type":"integer","description":"Percent off Pro and Business from an approved program, or null"},{"type":"null"}]},"billing_emails":{"type":"array","items":{"type":"string"}},"tax_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"badge":{"type":"object","description":"Badge bonus (free plan)"},"usage":{"type":"object","properties":{"month":{"type":"string","format":"date","description":"First day of the month reported"},"events":{"type":"integer","description":"Billable events (pageviews and custom events)"},"bots":{"type":"integer","description":"Bot hits filtered out (not billed)"},"allowance":{"type":"integer","description":"Events included, with any badge bonus"},"percent":{"type":"number","description":"Events as a percent of the allowance"},"forecast":{"anyOf":[{"type":"integer","description":"Projected events at month end"},{"type":"null"}]},"forecast_percent":{"anyOf":[{"type":"number"},{"type":"null"}]},"days_left":{"type":"integer","description":"Days left in the month"},"status":{"type":"string","description":"ok, warning (80%+), over (a past month at or over the allowance), locked or paused"},"sites":{"type":"array","items":{"type":"object","properties":{"site_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"events":{"type":"integer","description":"Pageviews and custom events this month"},"share":{"type":"number","description":"Percent of the workspace total"}}},"description":"Events by site"},"history":{"type":"array","description":"Previous months, newest first"},"access_locked_at":{"anyOf":[{"type":"string","format":"date-time","description":"Dashboards locked by Privatus Analytics staff since"},{"type":"null"}]},"collection_paused":{"type":"boolean","description":"True while new events are dropped (the monthly limit is reached, or staff paused collection)"},"pause_reason":{"anyOf":[{"type":"string","description":"Why collection is paused: limit (the monthly allowance is reached) or staff. null when collecting"},{"type":"null"}]},"collection_paused_at":{"anyOf":[{"type":"string","format":"date-time","description":"When staff paused collection"},{"type":"null"}]},"resumes_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a limit pause lifts: the start of next month (UTC), or earlier on an upgrade. null otherwise"},{"type":"null"}]}},"description":"This month so far"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"billing_get","x-permission":"billing.manage"},"patch":{"operationId":"billing_update","summary":"Update billing emails, tax id and auto-upgrade","description":"Updates the workspace's billing settings. Only the inputs you send change. billing_emails is an array of up to 5 extra addresses for invoices and billing notices and replaces the whole list. tax_id is stored on the workspace and is not added to invoices, so it must also be entered in the checkout. auto_upgrade is false by default. When true, reaching the monthly event limit moves the workspace to the next tier and charges the difference instead of pausing collection. Turning it on while collection is already paused at the limit upgrades and charges immediately and sends a confirmation email, and if Paddle refuses the upgrade nothing is saved. Returns the billing object like billing_get. Requires billing.manage.","tags":["Billing"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"workspace_id":{"type":"string"},"plan":{"type":"string","description":"free, pro, business or enterprise"},"plan_events":{"type":"integer","description":"Events a month in the paid tier"},"allowance":{"type":"integer","description":"Events a month including any badge bonus"},"billing_interval":{"anyOf":[{"type":"string","description":"month or year"},{"type":"null"}]},"price":{"anyOf":[{"type":"integer","description":"USD per billing interval"},{"type":"null"}]},"subscription_status":{"type":"string","description":"none, trialing, active, past_due, paused or canceled"},"current_period_ends_at":{"anyOf":[{"type":"string","format":"date-time","description":"Renews or ends at"},{"type":"null"}]},"cancel_at_period_end":{"type":"boolean"},"canceled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"auto_upgrade":{"type":"boolean"},"discount":{"anyOf":[{"type":"object","properties":{"program":{"type":"string","description":"nonprofit, education, open_source, open_source_free or agency"},"status":{"type":"string","description":"pending, approved (not yet on the subscription), active, rejected or revoked"},"percent":{"anyOf":[{"type":"integer","description":"Percent off Pro and Business (null for the free open-source program)"},{"type":"null"}]},"comp_events":{"anyOf":[{"type":"integer","description":"Free events a month (free open-source program only)"},{"type":"null"}]},"organization_name":{"type":"string","description":"Organization, school, project or agency name"},"website":{"anyOf":[{"type":"string","description":"Website"},{"type":"null"}]},"proof_url":{"anyOf":[{"type":"string","description":"Proof link or repository URL"},{"type":"null"}]},"license":{"anyOf":[{"type":"string","description":"OSI license (open source)"},{"type":"null"}]},"note":{"anyOf":[{"type":"string","description":"Note for the review"},{"type":"null"}]},"rejection_reason":{"anyOf":[{"type":"string","description":"Why the application was not approved"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"Applied at"},"reviewed_at":{"anyOf":[{"type":"string","format":"date-time","description":"Reviewed at"},{"type":"null"}]},"applied_at":{"anyOf":[{"type":"string","format":"date-time","description":"Discount active since"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string","format":"date-time","description":"Program ended at"},{"type":"null"}]}},"description":"The latest discount program application, or null"},{"type":"null"}]},"discount_percent":{"anyOf":[{"type":"integer","description":"Percent off Pro and Business from an approved program, or null"},{"type":"null"}]},"billing_emails":{"type":"array","items":{"type":"string"}},"tax_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"badge":{"type":"object","description":"Badge bonus (free plan)"},"usage":{"type":"object","properties":{"month":{"type":"string","format":"date","description":"First day of the month reported"},"events":{"type":"integer","description":"Billable events (pageviews and custom events)"},"bots":{"type":"integer","description":"Bot hits filtered out (not billed)"},"allowance":{"type":"integer","description":"Events included, with any badge bonus"},"percent":{"type":"number","description":"Events as a percent of the allowance"},"forecast":{"anyOf":[{"type":"integer","description":"Projected events at month end"},{"type":"null"}]},"forecast_percent":{"anyOf":[{"type":"number"},{"type":"null"}]},"days_left":{"type":"integer","description":"Days left in the month"},"status":{"type":"string","description":"ok, warning (80%+), over (a past month at or over the allowance), locked or paused"},"sites":{"type":"array","items":{"type":"object","properties":{"site_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"events":{"type":"integer","description":"Pageviews and custom events this month"},"share":{"type":"number","description":"Percent of the workspace total"}}},"description":"Events by site"},"history":{"type":"array","description":"Previous months, newest first"},"access_locked_at":{"anyOf":[{"type":"string","format":"date-time","description":"Dashboards locked by Privatus Analytics staff since"},{"type":"null"}]},"collection_paused":{"type":"boolean","description":"True while new events are dropped (the monthly limit is reached, or staff paused collection)"},"pause_reason":{"anyOf":[{"type":"string","description":"Why collection is paused: limit (the monthly allowance is reached) or staff. null when collecting"},{"type":"null"}]},"collection_paused_at":{"anyOf":[{"type":"string","format":"date-time","description":"When staff paused collection"},{"type":"null"}]},"resumes_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a limit pause lifts: the start of next month (UTC), or earlier on an upgrade. null otherwise"},{"type":"null"}]}},"description":"This month so far"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"billing.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"billing_emails":{"type":"array","items":{"type":"string"},"description":"Extra addresses for invoices and billing notices (up to 5)"},"tax_id":{"type":"string","description":"VAT, GST or other tax id, saved on the workspace. It is not added to invoices, so enter it in the checkout for that"},"auto_upgrade":{"type":"boolean","description":"true to move to the next tier and charge the difference when the monthly limit is reached, instead of pausing collection. Off by default. Turning it on while collection is paused at the limit upgrades and charges right away"}}}}}}}},"/workspaces/{workspace_id}/billing/usage.json":{"get":{"operationId":"billing_usage","summary":"Get this month's usage, forecast and per-site split","description":"Returns the workspace's event usage for one month. Use it to check how close the workspace is to its hard monthly limit. Inputs are month (any day in the month, defaults to the current month). Only pageviews and custom events count. Fields are month, events, bots (aggregate bot count, not billed), allowance, percent (0 to 100 and above, one decimal), forecast and forecast_percent (straight-line projection to month end, null for past months), days_left, status (ok, warning at 80 percent, over at 100 percent, paused or locked), sites (per site site_id, domain, name, events and share percent, largest first), history (previous months as month and events), access_locked_at, collection_paused (true when new events are being dropped), pause_reason (limit or staff, nullable), collection_paused_at and resumes_at (the 1st of next month when paused by the limit). Requires billing.manage.","tags":["Billing"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"month","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Any date in the month to report, in YYYY-MM-DD format, for example 2026-09-01. Defaults to the current month. Only the current month has a forecast and a pause state.","examples":["2026-09-01"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"month":{"type":"string","format":"date","description":"First day of the month reported"},"events":{"type":"integer","description":"Billable events (pageviews and custom events)"},"bots":{"type":"integer","description":"Bot hits filtered out (not billed)"},"allowance":{"type":"integer","description":"Events included, with any badge bonus"},"percent":{"type":"number","description":"Events as a percent of the allowance"},"forecast":{"anyOf":[{"type":"integer","description":"Projected events at month end"},{"type":"null"}]},"forecast_percent":{"anyOf":[{"type":"number"},{"type":"null"}]},"days_left":{"type":"integer","description":"Days left in the month"},"status":{"type":"string","description":"ok, warning (80%+), over (a past month at or over the allowance), locked or paused"},"sites":{"type":"array","items":{"type":"object","properties":{"site_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"events":{"type":"integer","description":"Pageviews and custom events this month"},"share":{"type":"number","description":"Percent of the workspace total"}}},"description":"Events by site"},"history":{"type":"array","description":"Previous months, newest first"},"access_locked_at":{"anyOf":[{"type":"string","format":"date-time","description":"Dashboards locked by Privatus Analytics staff since"},{"type":"null"}]},"collection_paused":{"type":"boolean","description":"True while new events are dropped (the monthly limit is reached, or staff paused collection)"},"pause_reason":{"anyOf":[{"type":"string","description":"Why collection is paused: limit (the monthly allowance is reached) or staff. null when collecting"},{"type":"null"}]},"collection_paused_at":{"anyOf":[{"type":"string","format":"date-time","description":"When staff paused collection"},{"type":"null"}]},"resumes_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a limit pause lifts: the start of next month (UTC), or earlier on an upgrade. null otherwise"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"billing_usage","x-permission":"billing.manage"}},"/workspaces/{workspace_id}/billing/invoices.json":{"get":{"operationId":"billing_invoices_list","summary":"List invoices","description":"Lists the workspace's billing transactions, newest first. Each item has id (use it with billing_invoices_get), invoice_number (nullable), status, amount_minor (integer in minor currency units, so 900 means 9.00), currency (ISO code such as USD) and billed_at (nullable ISO 8601). Paginated with page and per_page (maximum 100). It lists transactions only. To get the PDF call billing_invoices_get, and to update the card use billing_payment_method. Requires billing.manage.","tags":["Billing"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Paddle transaction id"},"invoice_number":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","description":"paid, completed, payment_failed, ..."},"amount_minor":{"type":"integer","description":"Total in minor units (cents)"},"currency":{"type":"string"},"billed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"billing_invoices_list","x-permission":"billing.manage"}},"/workspaces/{workspace_id}/billing/invoices/{id}.json":{"get":{"operationId":"billing_invoices_get","summary":"Get the PDF link for an invoice","description":"Returns a link to the PDF invoice of one billed transaction. Get the invoice id from billing_invoices_list (the id field, a Paddle transaction id). The result has kind (invoice) and url, which is a link to the PDF from Paddle, so fetch or share it soon after the call. Fails if the id does not belong to this workspace or Paddle has no invoice for it. Requires billing.manage.","tags":["Billing"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by billing_invoices_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"kind":{"type":"string","description":"portal, payment_method or invoice"},"url":{"anyOf":[{"type":"string","description":"Short-lived Paddle URL"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"billing_invoices_get","x-permission":"billing.manage"}},"/sites/{site_id}/bot-detection.json":{"get":{"operationId":"bot_detection_report","summary":"Advanced Bot Detection report: hits on the site's honeypot pages, by page and by what gave the bot away","description":"Reports the hits on the site's honeypot pages. A honeypot page is a page reached only through a hidden link and set up as the Advanced Bot Detection page in the app shows. These hits are bots, so they are never pageviews or visits and do not appear in stats_overview or stats_breakdown. Choose the range with period (7d, 30d (default), 90d or 12mo). Hits are kept for 12 months. The result has period, from (the start of the range), has_data (false until the first hit), totals (hits, distinct pages, automated (hits where the tracker saw an automated browser) and no_interaction (hits with no pointer, key or touch input)), pages (up to 50 rows with path, hits and last_hit_at), reasons (hits per result of the standard bot filter: known_bot, automation, datacenter, empty_user_agent, referrer_spam, or undetected for a hit the filter would have counted as a person) and recent (the latest 50 hits with occurred_at, path, country, browser, device, bot_reason, automation and interacted). No IP address or User-Agent is kept with a hit, only keyed hashes of them that can't identify anyone, and those are never returned. Needs analytics.read and the Business or Enterprise plan (402 plan_limit otherwise).","tags":["Bot detection"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range in the site's timezone: 7d, 30d (default), 90d or 12mo. Hits older than 12 months are deleted","enum":["7d","30d","90d","12mo"],"default":"30d"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"bot_detection_report","x-permission":"analytics.read"}},"/sites/{site_id}/campaigns/costs.json":{"post":{"operationId":"campaign_costs_create","summary":"Set the spend for a campaign in a month","description":"Records ad spend for one campaign in one month, so campaigns_list can show cost per acquisition and return on ad spend. If an entry for the same campaign and month already exists it is replaced, not duplicated, so this is also safe to call twice. campaign is the utm_campaign value as it appears in your tracked links, month is YYYY-MM (a full date such as 2026-09-15 is accepted and snaps to the first of the month), and amount is in major units as a number (1250.50, not minor units). currency is an optional 3-letter ISO code and defaults to the site currency. The response returns the stored entry with amount_minor in minor units. For many rows at once use campaign_costs_import. Needs content.write. Needs the Business or Enterprise plan (402 plan_limit otherwise).","tags":["Campaigns"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Cost entry id"},"campaign":{"type":"string","description":"utm_campaign value"},"month":{"type":"string","description":"Month, YYYY-MM"},"amount_minor":{"type":"integer","description":"Spend in minor units"},"currency":{"type":"string","description":"ISO 4217 currency of the amount"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"campaign_costs_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"type":"string","description":"The utm_campaign value the spend belongs to, exactly as used in your tracked links (e.g. spring_sale). Matching is case-insensitive when listing. One entry exists per campaign and month, saving again replaces the amount","examples":["spring_sale"]},"month":{"type":"string","description":"Month the spend is for as YYYY-MM (e.g. 2026-09). A full date such as 2026-09-15 is accepted and snaps to the first of that month","examples":["2026-09"]},"amount":{"type":"number","description":"Spend for the month in major currency units as a number, e.g. 1250.50 for 1,250.50. Not minor units. Must not be negative"},"currency":{"type":"string","description":"3-letter ISO 4217 code in capitals, e.g. USD. Defaults to the site currency"}},"required":["campaign","month","amount"]}}}}},"get":{"operationId":"campaign_costs_list","summary":"List campaign cost entries","description":"Lists the ad spend entries recorded for a site, newest month first, then by campaign name. Each row is one campaign in one month with amount_minor (an integer in minor currency units, so 125050 means 1,250.50), currency (ISO 4217, uppercase), month as YYYY-MM, and the entry id (a UUID, use it for campaign_costs_update and campaign_costs_delete). Pass campaign to see one campaign only (case-insensitive match on the utm_campaign value). Paginated with page and per_page (max 100). Costs feed CPA and ROAS in campaigns_list, so this is where to check what spend a campaign has. Needs analytics.read. Needs the Business or Enterprise plan (402 plan_limit otherwise).","tags":["Campaigns"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"campaign","in":"query","required":false,"schema":{"type":"string","description":"Only entries for this utm_campaign value (case-insensitive exact match)"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Cost entry id"},"campaign":{"type":"string","description":"utm_campaign value"},"month":{"type":"string","description":"Month, YYYY-MM"},"amount_minor":{"type":"integer","description":"Spend in minor units"},"currency":{"type":"string","description":"ISO 4217 currency of the amount"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"campaign_costs_list","x-permission":"analytics.read"}},"/sites/{site_id}/campaigns/costs/{id}.json":{"delete":{"operationId":"campaign_costs_delete","summary":"Delete a campaign cost entry","description":"Permanently deletes one spend entry, found by its id from campaign_costs_list. This cannot be undone, and CPA and ROAS for that campaign and month stop including the spend right away. Other months and campaigns are not touched. Returns the deleted entry. Needs content.write. Needs the Business or Enterprise plan (402 plan_limit otherwise).","tags":["Campaigns"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by campaign_costs_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Cost entry id"},"campaign":{"type":"string","description":"utm_campaign value"},"month":{"type":"string","description":"Month, YYYY-MM"},"amount_minor":{"type":"integer","description":"Spend in minor units"},"currency":{"type":"string","description":"ISO 4217 currency of the amount"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"campaign_costs_delete","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"patch":{"operationId":"campaign_costs_update","summary":"Change a campaign cost entry","description":"Changes an existing spend entry, found by its id from campaign_costs_list. Only the inputs you send change, so send just amount to correct a number. amount is in major units (1250.50) and is stored as minor units, month is YYYY-MM, currency is a 3-letter ISO code. Changing campaign or month to a combination that another entry already has fails with a validation error instead of merging. To correct spend for a campaign and month without knowing the id, call campaign_costs_create, which replaces the existing entry. Needs content.write. Needs the Business or Enterprise plan (402 plan_limit otherwise).","tags":["Campaigns"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by campaign_costs_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Cost entry id"},"campaign":{"type":"string","description":"utm_campaign value"},"month":{"type":"string","description":"Month, YYYY-MM"},"amount_minor":{"type":"integer","description":"Spend in minor units"},"currency":{"type":"string","description":"ISO 4217 currency of the amount"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"campaign_costs_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"type":"string","description":"New utm_campaign value. Fails if another entry already has this campaign and month"},"month":{"type":"string","description":"New month as YYYY-MM (a full date snaps to the first of the month). Fails if another entry already has this campaign and month"},"amount":{"type":"number","description":"New spend in major currency units as a number, e.g. 1250.50. Not minor units"},"currency":{"type":"string","description":"New 3-letter ISO 4217 code, e.g. USD"}}}}}}}},"/sites/{site_id}/campaigns/costs/import.json":{"post":{"operationId":"campaign_costs_import","summary":"Import campaign costs from CSV (campaign,month,amount[,currency])","description":"Bulk-imports ad spend from CSV, the quick way to load many campaigns and months. Send the CSV text in csv (best for tools and API calls) or upload a file in file (multipart only). The first row must be a header containing campaign, month and amount, with an optional currency column, for example campaign,month,amount,currency then spring_sale,2026-09,1250.50,USD. Month is YYYY-MM, amount is in major units, currency defaults to the site currency. Rows upsert by campaign and month, so re-importing the same file does not duplicate. Limits are 1 MB and 5,000 rows. A bad row does not stop the import. The response has imported (count saved), failed (count rejected) and errors (the first 50 messages, each naming its row, where row 2 is the first data row). A missing header column, an oversized file or malformed CSV fails the whole request. Needs content.write. Needs the Business or Enterprise plan (402 plan_limit otherwise).","tags":["Campaigns"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"imported":{"type":"integer","description":"Rows saved"},"failed":{"type":"integer","description":"Rows skipped"},"errors":{"type":"array","items":{"type":"string"},"description":"Why rows were skipped (first 50)"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"campaign_costs_import","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"CSV file upload, multipart requests only. Max 1 MB and 5,000 rows. Send csv instead when calling through MCP or JSON"},"csv":{"type":"string","description":"CSV text with a header row containing campaign, month and amount, plus an optional currency column. Example: campaign,month,amount,currency then spring_sale,2026-09,1250.50,USD. Month is YYYY-MM and amount is in major units. Rows upsert by campaign and month. Max 1 MB and 5,000 rows. Send either csv or file"}}}}}}}},"/sites/{site_id}/campaigns/builder.json":{"get":{"operationId":"campaigns_builder","summary":"Build and validate a UTM-tagged URL","description":"Builds a UTM-tagged URL for a landing page and checks the values. Nothing is saved and no data is read, so it is safe to call repeatedly. Pass destination (a full https:// URL) plus utm_source, utm_medium, utm_campaign, utm_content and utm_term as needed, or pick a preset (newsletter, social, paid_search and so on) to fill utm_source and utm_medium when you leave them blank. Returns url (null when there is an error), valid, destination, preset, the cleaned utm_* values, issues (a list of {field, level, code, message}, where level error blocks the URL and warning only suggests a fix such as lowercasing, and code is lowercase, spaces, personal_data, destination_missing or destination_invalid) and presets (the available preset values). Values are cleaned to lowercase without spaces. Use campaigns_hygiene to find messy UTM values that already exist in your traffic and campaigns_list to report on campaigns that have run. To keep a tagged link with a short URL and click counts, use links_create instead.","tags":["Campaigns"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"destination","in":"query","required":false,"schema":{"type":"string","description":"Full landing page URL starting with http:// or https://, for example https://example.com/pricing. Required for a valid result","examples":["https://example.com/pricing"]}},{"name":"preset","in":"query","required":false,"schema":{"type":"string","description":"Fills utm_source and utm_medium with typical values for a channel when you leave them blank. Values you send always win","enum":["newsletter","social","paid_search","paid_social","print","partner"]}},{"name":"utm_source","in":"query","required":false,"schema":{"type":"string","description":"Where the traffic comes from, for example newsletter or linkedin. Cleaned to lowercase without spaces"}},{"name":"utm_medium","in":"query","required":false,"schema":{"type":"string","description":"Marketing medium, for example email, cpc or social. Cleaned to lowercase without spaces"}},{"name":"utm_campaign","in":"query","required":false,"schema":{"type":"string","description":"Campaign name, for example spring_sale. Cleaned to lowercase without spaces. Campaign reports group by this value"}},{"name":"utm_content","in":"query","required":false,"schema":{"type":"string","description":"Variant, e.g. header_button"}},{"name":"utm_term","in":"query","required":false,"schema":{"type":"string","description":"Paid search keyword"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"url":{"anyOf":[{"type":"string","description":"Tagged URL (null while there are errors)"},{"type":"null"}]},"valid":{"type":"boolean","description":"True when there are no errors"},"destination":{"anyOf":[{"type":"string"},{"type":"null"}]},"preset":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_source":{"anyOf":[{"type":"string","description":"Normalized utm_source"},{"type":"null"}]},"utm_medium":{"anyOf":[{"type":"string","description":"Normalized utm_medium"},{"type":"null"}]},"utm_campaign":{"anyOf":[{"type":"string","description":"Normalized utm_campaign"},{"type":"null"}]},"utm_content":{"anyOf":[{"type":"string","description":"Normalized utm_content"},{"type":"null"}]},"utm_term":{"anyOf":[{"type":"string","description":"Normalized utm_term"},{"type":"null"}]},"issues":{"type":"array","items":{"type":"object"},"description":"field, level (error or warning), code (lowercase, spaces, personal_data, destination_missing or destination_invalid, the same in every language) and message"},"presets":{"type":"object","description":"Channel presets: utm_source/utm_medium per preset"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"campaigns_builder","x-permission":"analytics.read"}},"/sites/{site_id}/campaigns/hygiene.json":{"get":{"operationId":"campaigns_hygiene","summary":"UTM hygiene: near-duplicate values, style issues and unknown sources","description":"Finds messy UTM values in the traffic of a period so you can fix tagging. Returns period, duplicates, style_issues and unknown_sources. duplicates groups values of utm_source, utm_medium or utm_campaign that differ only by case, spaces or punctuation (Facebook, facebook and face-book), each as {field, suggestion, variants: [{value, visits}]} with the most visited spelling suggested. style_issues lists values that break the lowercase, no-spaces convention as {field, value, visits, suggestion} (up to 50). unknown_sources lists utm_source values that are not a recognized channel as {value, visits} (up to 50). Only the top 500 values per field are scanned. Counts are visits. Suggestions are advice only and nothing is changed. To merge variants into one channel, use channel_rules_create. Takes the shared period and filters inputs. Use campaigns_list for performance and campaigns_builder to create clean tagged URLs.","tags":["Campaigns"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"period":{"type":"object","description":"from/to of the period (UTC)"},"duplicates":{"type":"array","items":{"type":"object"},"description":"Near-duplicate values: field, suggestion and variants [{value, visits}]"},"style_issues":{"type":"array","items":{"type":"object"},"description":"Values that are not lowercase with underscores: field, value, visits, suggestion"},"unknown_sources":{"type":"array","items":{"type":"object"},"description":"utm_source values we do not recognize: value, visits"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"campaigns_hygiene","x-permission":"analytics.read"}},"/sites/{site_id}/campaigns.json":{"get":{"operationId":"campaigns_list","summary":"Campaign rollup with conversions, revenue, cost, CPA and ROAS","description":"Campaign performance report built from utm_campaign, with cost and return on ad spend. Returns period, currency (the site currency), goal_id and goal_name (the goal whose conversions are counted), campaigns, totals and unconverted_costs. Each campaign has visitors, visits, conversions, conversion_rate (percent from 0 to 100, conversions divided by visits), revenue and sources (rows per source and medium with the same metrics). When costs exist (from campaign_costs_list) a campaign also has cost, cpa (cost per conversion, null when there are no conversions) and roas (revenue divided by cost, a ratio such as 2.5, null when there is no cost). Money (revenue, cost, cpa) is an integer in minor units (cents) of the site currency. Costs are matched to campaign names case-insensitively and prorated by days of each month inside the period. A campaign with cost but no traffic is still listed. unconverted_costs lists spend with no exchange rate yet as {campaign, amount_minor, currency} in its own currency, left out of cost, cpa and roas. At most 100 campaigns, busiest first. Only visits with a utm_campaign are included. goal_id defaults to the first active goal, so pass it explicitly to measure a specific goal (ids come from goals_list). Use campaigns_hygiene to clean up names and stats_breakdown with dimension utm_campaign for a plain traffic split.","tags":["Campaigns"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"goal_id","in":"query","required":false,"schema":{"type":"string","description":"Goal id (goal_..., from goals_list) whose conversions are counted for every campaign. Defaults to the first active goal by name. The goal must belong to this site"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"period":{"type":"object","description":"from/to of the period (UTC)"},"currency":{"type":"string","description":"Site currency for revenue and cost"},"goal_id":{"anyOf":[{"type":"string","description":"Goal counted as a conversion"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string"},{"type":"null"}]},"campaigns":{"type":"array","items":{"type":"object"},"description":"Per utm_campaign: visitors, visits, conversions, conversion_rate, revenue, cost, cpa (minor units), roas (revenue ÷ cost) and sources [{source, medium, visitors, visits, conversions, conversion_rate, revenue}]"},"totals":{"type":"object","description":"Sums over all listed campaigns"},"unconverted_costs":{"type":"array","items":{"type":"object"},"description":"Spend with no exchange rate yet, left out of cost, cpa and roas: [{campaign, amount_minor, currency}], each in its own currency"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"campaigns_list","x-permission":"analytics.read"}},"/sites/{site_id}/campaigns/links.json":{"post":{"operationId":"links_create","summary":"Save a UTM-tagged link to the library","description":"Saves a UTM-tagged link to the site's link library (path takes site_id). name (up to 120 characters) and destination (an http or https URL up to 2048 characters) are required. The utm values are cleaned automatically, lowercased, trimmed and with spaces turned into underscores, and a value that looks like personal data (an email address for example) is rejected. Up to 20 tags are kept, comma separated entries are split and tags are lowercased and cut at 40 characters. It only stores the link, it does not track anything by itself. The returned url is the destination with the UTM parameters added, and a UTM parameter already in the destination is replaced. Use links_qr for a QR code.","tags":["Campaigns"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Link id, e.g. lnk_7Q2K9XH3AB"},"name":{"type":"string"},"destination":{"type":"string","description":"Landing page URL"},"utm_source":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_medium":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_campaign":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_content":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_term":{"anyOf":[{"type":"string"},{"type":"null"}]},"url":{"type":"string","description":"Full tagged URL to share"},"tags":{"type":"array","items":{"type":"string"}},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"links_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Link name, up to 120 characters","examples":["Spring newsletter"]},"destination":{"type":"string","description":"Landing page URL, http or https, up to 2048 characters. Existing utm_ parameters in it are replaced by the ones you set","examples":["https://example.com/pricing"]},"utm_source":{"type":"string","description":"Where the traffic comes from, e.g. newsletter. Lowercased, trimmed, spaces become underscores. Personal data is rejected"},"utm_medium":{"type":"string","description":"Marketing medium, e.g. email or cpc. Lowercased, trimmed, spaces become underscores"},"utm_campaign":{"type":"string","description":"Campaign name, e.g. spring_sale. Lowercased, trimmed, spaces become underscores"},"utm_content":{"type":"string","description":"Variant, e.g. header_button. Lowercased, trimmed, spaces become underscores"},"utm_term":{"type":"string","description":"Paid search keyword. Lowercased, trimmed, spaces become underscores"},"tags":{"type":"array","items":{"type":"string"},"description":"Tags for finding the link later. Up to 20, lowercased and cut at 40 characters. Comma separated entries are split","default":[]},"notes":{"type":"string","description":"Free text notes"}},"required":["name","destination"]}}}}},"get":{"operationId":"links_list","summary":"List saved campaign links","description":"Lists the saved campaign links (UTM-tagged URLs) of one site (path takes site_id), newest first and paginated. Each link has id (lnk_...), name, destination, utm_source, utm_medium, utm_campaign, utm_content, utm_term, url (the destination with the UTM parameters added, ready to share), tags, notes, created_at and updated_at. query searches name, destination and utm_campaign, tag keeps only links with that tag. The response meta has the pagination plus tags, every tag of the links of the site, sorted. This is the saved library, to see how campaigns performed use campaigns_list or stats_breakdown with dimension utm_campaign.","tags":["Campaigns"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Case-insensitive search in name, destination and utm_campaign"}},{"name":"tag","in":"query","required":false,"schema":{"type":"string","description":"Only links with this tag (case-insensitive, exact match)"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Link id, e.g. lnk_7Q2K9XH3AB"},"name":{"type":"string"},"destination":{"type":"string","description":"Landing page URL"},"utm_source":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_medium":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_campaign":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_content":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_term":{"anyOf":[{"type":"string"},{"type":"null"}]},"url":{"type":"string","description":"Full tagged URL to share"},"tags":{"type":"array","items":{"type":"string"}},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"links_list","x-permission":"analytics.read"}},"/sites/{site_id}/campaigns/links/{id}.json":{"delete":{"operationId":"links_delete","summary":"Delete a saved link","description":"Removes a saved link from the library. This only deletes the saved entry, URLs you already shared keep working and their visits are still counted by campaign. It cannot be undone. The id (lnk_...) comes from links_list. Returns the deleted link.","tags":["Campaigns"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by links_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Link id, e.g. lnk_7Q2K9XH3AB"},"name":{"type":"string"},"destination":{"type":"string","description":"Landing page URL"},"utm_source":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_medium":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_campaign":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_content":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_term":{"anyOf":[{"type":"string"},{"type":"null"}]},"url":{"type":"string","description":"Full tagged URL to share"},"tags":{"type":"array","items":{"type":"string"}},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"links_delete","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"links_get","summary":"Get a saved campaign link","description":"Returns one saved campaign link by id (lnk_..., from links_list). The response has name, destination, utm_source, utm_medium, utm_campaign, utm_content, utm_term (each null when unset), url (the full tagged URL), tags, notes, created_at and updated_at. Use links_qr for a print ready QR code of the same URL.","tags":["Campaigns"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by links_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Link id, e.g. lnk_7Q2K9XH3AB"},"name":{"type":"string"},"destination":{"type":"string","description":"Landing page URL"},"utm_source":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_medium":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_campaign":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_content":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_term":{"anyOf":[{"type":"string"},{"type":"null"}]},"url":{"type":"string","description":"Full tagged URL to share"},"tags":{"type":"array","items":{"type":"string"}},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"links_get","x-permission":"analytics.read"},"patch":{"operationId":"links_update","summary":"Change a saved link","description":"Changes a saved campaign link (id from links_list). Only the inputs you send change. The same cleaning and personal data checks as links_create apply. Sending tags replaces the whole tag list. Send an empty string for a utm field to clear it. Returns the updated link with its recomputed url.","tags":["Campaigns"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by links_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Link id, e.g. lnk_7Q2K9XH3AB"},"name":{"type":"string"},"destination":{"type":"string","description":"Landing page URL"},"utm_source":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_medium":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_campaign":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_content":{"anyOf":[{"type":"string"},{"type":"null"}]},"utm_term":{"anyOf":[{"type":"string"},{"type":"null"}]},"url":{"type":"string","description":"Full tagged URL to share"},"tags":{"type":"array","items":{"type":"string"}},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"links_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Link name, up to 120 characters","examples":["Spring newsletter"]},"destination":{"type":"string","description":"Landing page URL, http or https, up to 2048 characters","examples":["https://example.com/pricing"]},"utm_source":{"type":"string","description":"New utm_source. Lowercased, trimmed, spaces become underscores. Send an empty string to clear it"},"utm_medium":{"type":"string","description":"New utm_medium. Send an empty string to clear it"},"utm_campaign":{"type":"string","description":"New utm_campaign. Send an empty string to clear it"},"utm_content":{"type":"string","description":"New utm_content. Send an empty string to clear it"},"utm_term":{"type":"string","description":"New utm_term. Send an empty string to clear it"},"tags":{"type":"array","items":{"type":"string"},"description":"Replaces the whole tag list. Up to 20, lowercased and cut at 40 characters"},"notes":{"type":"string","description":"Free text notes"}}}}}}}},"/sites/{site_id}/campaigns/links/{id}/qr.json":{"get":{"operationId":"links_qr","summary":"QR code (SVG) for a saved link","description":"Returns a QR code for a saved link's full tagged URL, for print. The response has link_id, url (the tagged URL encoded in the code) and svg (a complete standalone SVG document as a string, black on white). size is the module size in pixels, from 2 to 20 (default 6), which scales the image. The id (lnk_...) comes from links_list. Use links_get when you only need the URL.","tags":["Campaigns"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by links_list","schema":{"type":"string"}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","description":"Module size in pixels, 2 to 20 (default 6). Larger values give a bigger image","default":6}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"link_id":{"type":"string","description":"Link id"},"url":{"type":"string","description":"The encoded (tagged) URL"},"svg":{"type":"string","description":"Standalone SVG document of the QR code"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"links_qr","x-permission":"analytics.read"}},"/sites/{site_id}/channel_rules.json":{"post":{"operationId":"channel_rules_create","summary":"Add a channel rule","description":"Adds a custom channel rule at the end of the list, so it runs after all existing rules and the built-in taxonomy only applies when no rule matches. channel is the name to assign (up to 32 characters, e.g. Partners). conditions is a non-empty list of objects with field (referrer_host, utm_source, utm_medium, utm_campaign, ref or path), operator (is, contains, starts_with or regex) and value. All conditions must match for the rule to apply, and matching is case-insensitive. A condition with a blank value is dropped, and a rule left with no conditions is rejected. A regex that does not compile is rejected. The rule applies to new visits within minutes and does not change history. Use channel_rules_move to reorder and channel_rules_preview to test it. Needs sites.manage.","tags":["Channel rules"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Rule id"},"channel":{"type":"string","description":"Channel assigned when all conditions match"},"position":{"type":"integer","description":"Evaluation order (first match wins)"},"conditions":{"type":"array","description":"Conditions: field, operator, value"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"channel_rules_create","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channel":{"type":"string","description":"Channel name to assign, up to 32 characters, e.g. Partners. Shown as the channel in reports"},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","enum":["referrer_host","utm_source","utm_medium","utm_campaign","ref","path"]},"operator":{"type":"string","enum":["is","contains","starts_with","regex"]},"value":{"type":"string"}}},"description":"Non-empty list of conditions that must ALL match for the rule to apply. Each is an object with field, operator and value, e.g. [{\"field\": \"utm_source\", \"operator\": \"is\", \"value\": \"newsletter\"}]. Fields: referrer_host (hostname without www, e.g. news.ycombinator.com), utm_source, utm_medium, utm_campaign, ref (the ref, via or source parameter), path (landing page path, e.g. /pricing). Operators: is (exact), contains, starts_with and regex. Matching is case-insensitive. A condition with an empty value is dropped"}},"required":["channel","conditions"]}}}}},"get":{"operationId":"channel_rules_list","summary":"List channel rules in order","description":"Lists the custom channel rules of a site in evaluation order (position 1 first). Rules run top to bottom against each new visit and the first rule whose conditions all match decides the channel. A visit that matches no rule gets the built-in channel (direct, organic_search, paid_search, email and so on). Each rule has id (a UUID), channel (the name it assigns), position (1-based), conditions (a list of field, operator and value objects, all of which must match) and created_at. Rules only affect visits recorded after the rule exists and never rewrite old data. Use channel_rules_preview to test a sample visit. Needs analytics.read.","tags":["Channel rules"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Rule id"},"channel":{"type":"string","description":"Channel assigned when all conditions match"},"position":{"type":"integer","description":"Evaluation order (first match wins)"},"conditions":{"type":"array","description":"Conditions: field, operator, value"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"channel_rules_list","x-permission":"analytics.read"}},"/sites/{site_id}/channel_rules/{id}.json":{"delete":{"operationId":"channel_rules_delete","summary":"Delete a channel rule","description":"Deletes a custom channel rule, found by its id from channel_rules_list. Visits it already classified keep their channel, and new visits fall through to the next matching rule or the built-in taxonomy. Remaining rules keep their order. Returns the deleted rule. Needs sites.manage.","tags":["Channel rules"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by channel_rules_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Rule id"},"channel":{"type":"string","description":"Channel assigned when all conditions match"},"position":{"type":"integer","description":"Evaluation order (first match wins)"},"conditions":{"type":"array","description":"Conditions: field, operator, value"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"channel_rules_delete","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"patch":{"operationId":"channel_rules_update","summary":"Change a channel rule","description":"Changes a custom channel rule, found by its id from channel_rules_list. Send channel to rename the channel it assigns and conditions to replace the whole conditions list (the list is replaced, not merged, so send every condition you want to keep). Omitted inputs are left alone. Condition fields, operators and regex validity are checked the same way as in channel_rules_create. The change applies to new visits only. To change the order use channel_rules_move. Needs sites.manage.","tags":["Channel rules"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by channel_rules_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Rule id"},"channel":{"type":"string","description":"Channel assigned when all conditions match"},"position":{"type":"integer","description":"Evaluation order (first match wins)"},"conditions":{"type":"array","description":"Conditions: field, operator, value"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"channel_rules_update","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channel":{"type":"string","description":"New channel name to assign, up to 32 characters. Leave out to keep the current one"},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","enum":["referrer_host","utm_source","utm_medium","utm_campaign","ref","path"]},"operator":{"type":"string","enum":["is","contains","starts_with","regex"]},"value":{"type":"string"}}},"description":"Replaces the whole list of conditions (not merged), so send every condition to keep. All must match. Each is an object with field (referrer_host, utm_source, utm_medium, utm_campaign, ref or path), operator (is, contains, starts_with or regex) and value. Example: [{\"field\": \"utm_source\", \"operator\": \"is\", \"value\": \"newsletter\"}]. Leave out to keep the current conditions"}}}}}}}},"/sites/{site_id}/channel_rules/{id}/move.json":{"patch":{"operationId":"channel_rules_move","summary":"Move a channel rule up or down","description":"Moves a channel rule within the evaluation order, because the first matching rule wins and order decides which channel a visit gets. direction is up or down (one place), or top or bottom (to the ends). A rule already at the edge stays put without error. Positions are renumbered 1 to n and the updated rule is returned with its new position. Use channel_rules_list first to see the current order. Needs sites.manage.","tags":["Channel rules"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by channel_rules_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Rule id"},"channel":{"type":"string","description":"Channel assigned when all conditions match"},"position":{"type":"integer","description":"Evaluation order (first match wins)"},"conditions":{"type":"array","description":"Conditions: field, operator, value"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"channel_rules_move","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"direction":{"type":"string","description":"up or down moves the rule one place, top or bottom moves it to the first or last position. Rules run top to bottom and the first match wins","enum":["up","down","top","bottom"]}},"required":["direction"]}}}}}},"/sites/{site_id}/channel_rules/preview.json":{"post":{"operationId":"channel_rules_preview","summary":"Preview the channel for a sample referrer and UTM tags","description":"Dry run that tells you which channel a sample visit would get with the site's current rules. Nothing is stored. Send any of referrer (a URL or bare hostname, www and m prefixes are ignored), utm_source, utm_medium, utm_campaign, ref, path (landing path such as /pricing) and paid_click (true if the URL carried a click id like gclid). The result has channel (the winning channel name), custom_rule (true when a custom rule decided it, false when the built-in taxonomy did) and referrer_host (the cleaned hostname used for matching). A referrer on the site's own domains counts as internal. Use this after channel_rules_create or channel_rules_move to confirm the effect. Needs analytics.read.","tags":["Channel rules"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"channel_rules_preview","x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"referrer":{"type":"string","description":"Referrer of the sample visit as a URL or bare hostname, e.g. https://news.ycombinator.com/item?id=1. www and m prefixes are ignored. Leave out for a direct visit"},"utm_source":{"type":"string","description":"utm_source of the sample visit, e.g. newsletter"},"utm_medium":{"type":"string","description":"utm_medium of the sample visit, e.g. email or cpc"},"utm_campaign":{"type":"string","description":"utm_campaign of the sample visit"},"ref":{"type":"string","description":"Value of the ref, via or source query parameter on the landing URL"},"path":{"type":"string","description":"Landing page path of the sample visit, e.g. /pricing"},"paid_click":{"type":"boolean","description":"true if the landing URL carried an ad click id such as gclid or fbclid. Default false","default":false}}}}}}}},"/embed/ads/e.json":{"post":{"operationId":"ad_serving_event","summary":"Record that a creative was shown, seen or clicked, called by the ad loader","tags":["Collection"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"site":{"type":"string","description":"Public site id (s)"},"creative":{"type":"string","description":"Public creative id (c)"},"experiment":{"type":"string","description":"Public id of the experiment the creative was picked by (x), if any"},"type":{"type":"string","description":"What happened (t): i for an impression, v for a viewable impression (half of the creative on screen for one second), c for a click"},"url":{"type":"string","description":"The page the slot is on (u), as host and path"},"timezone":{"type":"string","description":"The browser's time zone name (tz)"},"language":{"type":"string","description":"The browser's language (l)"},"screen_width":{"type":"integer","description":"The screen's width in CSS pixels (sw)"}},"required":["site","creative","type"]}}}},"security":[]}},"/embed/ads/{site}.json":{"get":{"operationId":"ad_serving_slots","summary":"A site's ad slots and the creatives each one shows, called by the ad loader","tags":["Collection"],"parameters":[{"name":"site","in":"path","required":true,"description":"Site of the resource","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/api/overlay.json":{"post":{"operationId":"click_overlays_read","summary":"The clicks of one page for the click overlay, called by pa.overlay.js with its pass","tags":["Collection"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"pass":{"type":"string","description":"The overlay pass from the page address, after #privatus-overlay="},"url":{"type":"string","description":"The page URL as the tracker reports it"},"period":{"type":"string","description":"Time to count: 7d, 30d or 90d. Default 30d","default":"30d"},"device":{"type":"string","description":"Only clicks from this kind of device: desktop, mobile or tablet. Leave it out for all"},"hash_mode":{"type":"boolean","description":"Set to true when the site tells pages apart by the part after # in the address (hash routing). The page then keeps that part. Default false","default":false}},"required":["pass","url"]}}}},"security":[]}},"/api/logs.json":{"post":{"operationId":"crawler_logs_create","summary":"Send server access logs for AI crawler reporting (JSON {lines: [...]} or combined log text, with the site's crawler log key as Bearer token)","tags":["Collection"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"lines":{"type":"array","items":{"type":"object","properties":{"ts":{"type":"string"},"path":{"type":"string","default":"/"},"status":{"type":"integer"},"user_agent":{"type":"string","default":""}}},"description":"Log lines: [{ts, path, status, user_agent}] (max 1000)"}},"required":["lines"]}}}},"security":[]}},"/api/event.json":{"post":{"operationId":"ingest_event","summary":"Collect a browser hit (used by /js/pa.js)","tags":["Collection"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"site":{"type":"string","description":"Site id (pa_…)"},"type":{"type":"string","description":"Hit type","enum":["pageview","event","engagement","vital","click"]},"url":{"type":"string","description":"Full page URL"},"referrer":{"type":"string","description":"document.referrer"},"name":{"type":"string","description":"Event name (type=event) or vital name"},"props":{"type":"object","additionalProperties":true,"description":"Event properties: up to 30 string/number/boolean values","default":{}},"screen_width":{"type":"integer","description":"Screen width in pixels"},"language":{"type":"string","description":"navigator.language"},"engaged_ms":{"type":"integer","description":"Visible time on page (engagement)"},"scroll_depth":{"type":"integer","description":"Max scroll depth % (engagement)"},"value":{"type":"number","description":"Web Vital value (type=vital)"},"selector":{"type":"string","description":"Clicked element selector (type=click)"},"hash_mode":{"type":"boolean","description":"Keep the #fragment (hash-routed sites)","default":false},"dnt":{"type":"boolean","description":"Do Not Track is on","default":false},"gpc":{"type":"boolean","description":"Global Privacy Control is on","default":false},"interacted":{"type":"boolean","description":"1 once a trusted input (pointer, key, touch or wheel) was seen on the page, 0 before. No coordinates or timing"},"revenue":{"type":"number","description":"Revenue in major units, e.g. 49.99"},"currency":{"type":"string","description":"ISO 4217 currency of revenue"},"honeypot":{"type":"boolean","description":"Set by the tracker for Advanced Bot Detection, on a page the site owner set up as a honeypot that no person can reach. The hit is never counted as a pageview. On Pro, Business and Enterprise it is kept for Advanced Bot Detection, with keyed hashes of its IP address and User-Agent in place of the values, so it can't identify anyone"},"automation":{"type":"string","description":"Only with honeypot: the automation the tracker saw in the browser (webdriver, phantom, nightmare or cypress). Left out when it saw none"},"challenge":{"type":"boolean","description":"Set by the tracker for Advanced Bot Detection, on a \"confirm you're human\" page (data-hp=\"ch\") shown to a random few visitors, people and bots alike. The hit is never counted as a pageview or as a bot. On Pro, Business and Enterprise it is kept for Advanced Bot Detection, with keyed hashes of its IP address and User-Agent in place of the values, so it can't identify anyone"},"timezone":{"type":"string","description":"The IANA time zone of the browser. Read for the bot score, and kept only with a hit from a page with data-hp"},"preview":{"type":"string","description":"From an experiment preview link (pa_preview). The variant it names is shown and the page view is not counted for the experiment"}},"required":["site","type","url"]}}}},"security":[]}},"/api/experiment.json":{"get":{"operationId":"ingest_experiment","summary":"Whether an experiment sends this visitor to a variant page, called by the experiments head script","tags":["Collection"],"parameters":[{"name":"site","in":"query","required":false,"schema":{"type":"string","description":"Public site id"}},{"name":"url","in":"query","required":false,"schema":{"type":"string","description":"The page URL, without its query string unless an experiment targets channels"}},{"name":"referrer","in":"query","required":false,"schema":{"type":"string","description":"The page's referrer, sent only when an experiment targets channels"}},{"name":"preview","in":"query","required":false,"schema":{"type":"string","description":"A variant id from a preview link (var_...). That variant is shown and nothing is counted"}},{"name":"dnt","in":"query","required":false,"schema":{"type":"boolean","description":"Whether the browser sends Do Not Track","default":false}},{"name":"gpc","in":"query","required":false,"schema":{"type":"boolean","description":"Whether the browser sends Global Privacy Control","default":false}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"x":{"anyOf":[{"type":"string","description":"The path of the same site to send the visitor to, or null to stay on the page"},{"type":"null"}]},"p":{"type":"boolean","description":"True when the answer comes from a preview link"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/js/exp/{site}.json":{"get":{"operationId":"ingest_experiment_script","summary":"The script the optional experiments head tag loads for a site","tags":["Collection"],"parameters":[{"name":"site","in":"path","required":true,"description":"Site of the resource","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/api/survey.json":{"post":{"operationId":"ingest_survey","summary":"Record that a survey card was shown, dismissed or answered","tags":["Collection"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"site":{"type":"string","description":"Public site id"},"survey":{"type":"string","description":"Public survey id"},"kind":{"type":"string","description":"What happened: shown, dismiss or answer","enum":["shown","dismiss","answer"]},"url":{"type":"string","description":"The full page URL"},"answers":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"The answers so far, each { q: question key, v: value }","default":[]},"completed":{"type":"boolean","description":"Whether the last question was answered","default":false},"dnt":{"type":"boolean","description":"Whether the browser sends Do Not Track","default":false},"gpc":{"type":"boolean","description":"Whether the browser sends Global Privacy Control","default":false}},"required":["site","survey","kind","url"]}}}},"security":[]}},"/api/surveys.json":{"get":{"operationId":"ingest_surveys","summary":"What survey to show on a page, called by the tracker's ask module","tags":["Collection"],"parameters":[{"name":"site","in":"query","required":false,"schema":{"type":"string","description":"Public site id"}},{"name":"url","in":"query","required":false,"schema":{"type":"string","description":"The full page URL"}},{"name":"dnt","in":"query","required":false,"schema":{"type":"boolean","description":"Whether the browser sends Do Not Track","default":false}},{"name":"gpc","in":"query","required":false,"schema":{"type":"boolean","description":"Whether the browser sends Global Privacy Control","default":false}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Public survey id"},"position":{"type":"string"},"thank_you":{"anyOf":[{"type":"string"},{"type":"null"}]},"trigger":{"type":"object","description":"When to show the card: kind, delay_seconds and scroll_percent"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions to ask, in order"},"labels":{"type":"object","description":"The words the card needs for its own buttons"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/sites/{site_id}/crawlers/connection.json":{"delete":{"operationId":"crawlers_cloudflare_disconnect","summary":"Disconnect Cloudflare and delete its stored API token and the crawler hits it imported","description":"Disconnects Cloudflare from a site. This deletes the stored API token and every crawler hit that was imported from Cloudflare, and it cannot be undone. Hits that came from shipped server logs stay. The token still exists in your Cloudflare account until you delete it there. Fails if the site has no connection. Returns the removed connection. Needs sites.manage.","tags":["Crawlers"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"zone_id":{"type":"string","description":"Cloudflare zone id"},"zone_name":{"type":"string","description":"Cloudflare zone name, e.g. example.com"},"status":{"type":"string","description":"active or error"},"last_synced_at":{"anyOf":[{"type":"string","format":"date-time","description":"When crawler hits were last imported, or null before the first import"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/crawlers/sync.json":{"post":{"operationId":"crawlers_cloudflare_sync","summary":"Import crawler hits from Cloudflare now","description":"Queues an immediate Cloudflare import for a site that is already connected, instead of waiting for the regular schedule. It returns right away (HTTP 202) with the connection, and the import runs in the background. Poll crawlers_report and watch cloudflare.last_synced_at to see when it finished. Fails if the site has no Cloudflare connection. Needs sites.manage.","tags":["Crawlers"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"zone_id":{"type":"string","description":"Cloudflare zone id"},"zone_name":{"type":"string","description":"Cloudflare zone name, e.g. example.com"},"status":{"type":"string","description":"active or error"},"last_synced_at":{"anyOf":[{"type":"string","format":"date-time","description":"When crawler hits were last imported, or null before the first import"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"crawlers_cloudflare_sync","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/crawlers.json":{"get":{"operationId":"crawlers_report","summary":"AI crawlers report: hits by crawler over time, top paths per crawler, by category","description":"Reports which AI, search and SEO crawlers fetch the site, how often and which paths, from shipped server logs and the Cloudflare import. This is crawler traffic, not visitor traffic, so it does not appear in stats_breakdown. category is ai (default), search, seo, other or all, and crawler narrows to one named bot such as GPTBot or ClaudeBot. Choose the range with period (default 30d) or custom from and to. The result has period (from and to as dates), category, crawler, totals (hits, distinct paths, distinct crawlers), categories (hits per category, ignoring the category filter), crawlers (up to 50 rows with crawler, category, hits, paths), series (labels per day and daily hits for the top 8 crawlers), top_paths (the 10 most fetched paths for each of the top 8 crawlers), has_data (false until any hits exist) and cloudflare (the connection with zone, status and last_synced_at, or null). Results are cached for up to 30 minutes except right after a Cloudflare change. Needs analytics.read.","tags":["Crawlers"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset in the site's timezone, e.g. 7d (default), 30d, 90d, mtd, last_month, ytd, all, or custom (then from and to are required)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day as YYYY-MM-DD, in the site's timezone. Only used when period is custom"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day as YYYY-MM-DD, inclusive. Only used when period is custom"}},{"name":"category","in":"query","required":false,"schema":{"type":"string","description":"Which kind of crawler to include: ai (default, AI training, search and assistant bots), search (search engines), seo (SEO tools), other or all. The categories field of the result always shows every category","enum":["all","ai","search","seo","other"],"default":"ai"}},{"name":"crawler","in":"query","required":false,"schema":{"type":"string","description":"Only this crawler by its exact name, e.g. GPTBot, ClaudeBot, PerplexityBot, Googlebot, Bingbot or AhrefsBot. Take names from the crawlers rows of an earlier report"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"crawlers_report","x-permission":"analytics.read"}},"/workspaces/{workspace_id}/dashboards/{id}/cards/{index}.json":{"get":{"operationId":"dashboards_card","summary":"Data for one card of a custom dashboard","description":"Returns the live data of one card of a custom dashboard. Dashboards are lists of cards (see dashboards_get for the card list) and each card loads separately, so call this once per card with its position in index, counted from 0. Returns index, type, title, site_id, site_name, params, status and data. status is ok, not_available (the card has nothing to show, for example a funnel card on a site with no funnels or an uptime card with no checks) or no_access (the card belongs to a site your token or role cannot open, and then title, params and data are empty). The shape of data depends on type. metric gives {metric, value, previous, change, period} compared with the previous period. chart gives {metric, interval, period, series: [{date, value}]}. breakdown gives {dimension, label, rows}. goal gives {rows} of goal completions. live gives {visitors}. funnel gives {funnel_id, name, overall_conversion_rate, steps}. uptime gives {checks: [{name, status, uptime}]}. vitals gives {scorecard}. subscriptions gives {currency, mrr_minor, previous_mrr_minor (30 days ago), change (percent, null without MRR 30 days ago), active_subscriptions, subscription_churn_rate (last 30 days)} and is not_available while the site has no payment provider connected. Card params default to period 30d, metric visitors, dimension page and 5 rows (limit is capped at 10). An index outside the list returns 404. Use dashboards_get first to see how many cards there are.","tags":["Dashboards"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by the tools that list or create it","schema":{"type":"string"}},{"name":"index","in":"path","required":true,"description":"Position of the card on the dashboard, counting from 0","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"dashboards_card","x-permission":"analytics.read"}},"/workspaces/{workspace_id}/dashboards.json":{"post":{"operationId":"dashboards_create","summary":"Create a custom dashboard","description":"Creates a custom dashboard in a workspace. A custom dashboard is a named, ordered list of up to 40 cards, and the cards can come from different sites of the workspace. Pass name (up to 100 characters) and cards, a list of objects with type (metric, chart, breakdown, goal, live, funnel, uptime, vitals or subscriptions), site_id (pa_..., from sites_list) and optionally title (up to 80 characters) and params. Params used per type are metric (period, metric), chart (period, metric, interval), breakdown (period, dimension, limit), goal (period, limit), funnel (period, funnel_id), uptime (limit) and vitals (period). live and subscriptions take none. Other params are dropped. The period must be a preset such as 30d (not custom) and metric one of visitors, visits, pageviews, views_per_visit, bounce_rate or visit_duration. Every card must point to a site your token can access, and a token limited to some sites must include at least one card. Returns the dashboard with id (dash_...), name, cards and timestamps. Read it with dashboards_get and load each card's numbers with dashboards_card. Needs the content.write permission. The plan sets how many dashboards a workspace has: 1 on Free, 3 on Pro, unlimited on Business. One over the count is refused with a validation error.","tags":["Dashboards"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Dashboard id, e.g. dash_7Q2K9XH3AB"},"name":{"type":"string"},"cards":{"type":"array","items":{"type":"object"},"description":"Cards in order: [{type, site_id, title, params}]. A card for a site you can't access is {type, status: \"no_access\"}"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"dashboards_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Dashboard name","examples":["Client: Acme"]},"cards":{"type":"array","items":{},"description":"Cards in order (max 40): [{\"type\": \"metric|chart|breakdown|goal|live|funnel|uptime|vitals|subscriptions\", \"site_id\": \"pa_…\", \"title\": \"optional\", \"params\": {\"period\": \"30d\", \"metric\": \"visitors\", \"dimension\": \"page\", \"funnel_id\": \"fun_…\"}}]. Params a type does not use are ignored","default":[]}},"required":["name"]}}}}},"get":{"operationId":"dashboards_list","summary":"List custom dashboards","description":"Lists the custom dashboards of a workspace, ordered by name. Each item has id (dash_...), name, cards and timestamps, the same shape as dashboards_get. A token limited to some sites only sees dashboards that include a card of one of its sites, and cards of other sites are blanked to {type, status: no_access}. Paginated with page and per_page (max 100). Use dashboards_card to load the data of a card and dashboards_create to add a dashboard. For a single site, stats_overview gives the same kind of numbers without a dashboard.","tags":["Dashboards"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Dashboard id, e.g. dash_7Q2K9XH3AB"},"name":{"type":"string"},"cards":{"type":"array","items":{"type":"object"},"description":"Cards in order: [{type, site_id, title, params}]. A card for a site you can't access is {type, status: \"no_access\"}"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"dashboards_list","x-permission":"analytics.read"}},"/workspaces/{workspace_id}/dashboards/{id}.json":{"delete":{"operationId":"dashboards_delete","summary":"Delete a custom dashboard","description":"Permanently deletes a custom dashboard. Only the dashboard layout is removed, no analytics data is touched, and there is no undo. You need access to every site that has a card on the dashboard, and the dashboard needs at least one card of a site you can access. Returns the deleted dashboard. Use dashboards_update to change a dashboard instead. Ids (dash_...) come from dashboards_list. Needs the content.write permission.","tags":["Dashboards"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by the tools that list or create it","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Dashboard id, e.g. dash_7Q2K9XH3AB"},"name":{"type":"string"},"cards":{"type":"array","items":{"type":"object"},"description":"Cards in order: [{type, site_id, title, params}]. A card for a site you can't access is {type, status: \"no_access\"}"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"dashboards_delete","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"dashboards_get","summary":"Get a custom dashboard and its cards","description":"Returns one custom dashboard: id (dash_...), name, cards and created_at and updated_at. Each card is {type, site_id, title, params} (type is metric, chart, breakdown, goal, live, funnel, uptime, vitals or subscriptions). A card on a site you cannot access is returned as {type, status: no_access} with no other fields. This returns the layout only, not the numbers. Load the numbers of a card with dashboards_card, using the card's position counted from 0. Ids come from dashboards_list. A dashboard over the plan's count (1 on Free, 3 on Pro) is kept and locked: it responds with 402 plan_limit until the workspace upgrades or deletes another one.","tags":["Dashboards"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by the tools that list or create it","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Dashboard id, e.g. dash_7Q2K9XH3AB"},"name":{"type":"string"},"cards":{"type":"array","items":{"type":"object"},"description":"Cards in order: [{type, site_id, title, params}]. A card for a site you can't access is {type, status: \"no_access\"}"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"dashboards_get","x-permission":"analytics.read"},"patch":{"operationId":"dashboards_update","summary":"Rename a custom dashboard or replace its cards","description":"Renames a custom dashboard and/or replaces its whole list of cards. Only the fields you send change, and name is left alone when empty. Sending cards replaces every card, so send the full list in the order you want, taken from dashboards_get and edited. Card format and params per type are the same as in dashboards_create (max 40 cards). A card shown as {type, status: no_access} belongs to a site you cannot open. Send it back unchanged to keep it, it cannot be edited and the last card of such a site cannot be removed. A token limited to some sites cannot leave the dashboard empty. Returns the updated dashboard. Needs the content.write permission.","tags":["Dashboards"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by the tools that list or create it","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Dashboard id, e.g. dash_7Q2K9XH3AB"},"name":{"type":"string"},"cards":{"type":"array","items":{"type":"object"},"description":"Cards in order: [{type, site_id, title, params}]. A card for a site you can't access is {type, status: \"no_access\"}"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"dashboards_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New name (unchanged when empty)"},"cards":{"type":"array","items":{},"description":"Replaces all cards. Cards in order (max 40): [{\"type\": \"metric|chart|breakdown|goal|live|funnel|uptime|vitals|subscriptions\", \"site_id\": \"pa_…\", \"title\": \"optional\", \"params\": {\"period\": \"30d\", \"metric\": \"visitors\", \"dimension\": \"page\", \"funnel_id\": \"fun_…\"}}]. Params a type does not use are ignored. A card for a site you can't access is shown as {\"type\": \"…\", \"status\": \"no_access\"}: send it back as it is to keep it. It can't be changed, and the last card of such a site can't be removed"}}}}}}}},"/docs/api.json":{"get":{"operationId":"docs_api","summary":"List every API operation and MCP tool","description":"Returns the full catalog of every API operation. Most are MCP tools too, and mcp is false for the ones that are HTTP only or that a person does in the app (deleting data, billing, access and security). Use it to discover which tool or endpoint exists and exactly what it takes. Each item has tool_name, summary, description (nullable), group, verb (HTTP method), path (template with placeholders), permission (the permission a member or token needs, nullable for public tools), mcp (true when it runs as an MCP tool), input_schema (JSON Schema of the inputs) and response_schema (JSON Schema of the response). The response is large. For one tool you already know, prefer the docs pages (docs_search). docs_openapi returns the same information as an OpenAPI document. Public, no authentication needed.","tags":["Documentation"],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"tool_name":{"type":"string","description":"MCP tool name and OpenAPI operationId"},"summary":{"type":"string"},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"group":{"type":"string"},"verb":{"type":"string","description":"HTTP method"},"path":{"type":"string","description":"Path template. Add .json for JSON"},"permission":{"anyOf":[{"type":"string"},{"type":"null"}]},"mcp":{"type":"boolean","description":"Whether the operation runs as an MCP tool. False for HTTP-only operations and for the ones a person does in the app (deleting data, billing, access and security), whose tool only returns a link"},"input_schema":{"type":"object","description":"JSON Schema of the inputs"},"response_schema":{"type":"object","description":"JSON Schema of `data`"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/docs.json":{"get":{"operationId":"docs_list","summary":"List documentation pages","description":"Lists every documentation page with title, description, path (such as /docs/api/authentication), section and no body. Use it to browse what exists. To find a page by topic use docs_search, and to read one use docs_get with its section and page. Paginated with page and per_page (maximum 100). Public, no authentication needed.","tags":["Documentation"],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","description":"Page title"},"description":{"type":"string","description":"One-line summary"},"path":{"type":"string","description":"Page path. Add .md for Markdown or .json for JSON"},"section":{"type":"string","description":"Section slug, e.g. tracker"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"docs_list","security":[]}},"/openapi.json":{"get":{"operationId":"docs_openapi","summary":"OpenAPI 3.1 document for the whole API","description":"Returns the OpenAPI 3 document describing the whole public API as raw JSON (not wrapped in a data field). Use it when you need a machine-readable spec for code generation. For a browsable list of operations with their input and response schemas, docs_api is easier to read. It describes the same operations that are exposed as MCP tools. Public, no authentication needed.","tags":["Documentation"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/docs/search.json":{"get":{"operationId":"docs_search","summary":"Search the documentation","description":"Searches the documentation on the server and returns ranked pages. Use it to find how a feature works before guessing. q is split into up to 10 terms, every term must appear in the page, and title and heading matches rank highest. An empty q returns every page in the catalog order. limit defaults to 20 when q is given and is at most 100. Each result has title, path (use the section and page parts with docs_get), section, headings (list of id and text, useful as the heading anchor), excerpt and score (null when q is empty). Searches the language of the request, English by default. Public, no authentication needed.","tags":["Documentation"],"parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"Search text, up to 10 words. Every word must appear in a page. Leave blank to list every page.","examples":["content security policy"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Maximum results, 1 to 100. Defaults to 20 when q is given and to all pages when q is blank."}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"title":{"type":"string","description":"Page title"},"path":{"type":"string","description":"Page path"},"section":{"type":"string","description":"Section title"},"headings":{"type":"array","items":{"type":"object"},"description":"Headings on the page: { id, text }"},"excerpt":{"type":"string","description":"Description or first sentences"},"score":{"anyOf":[{"type":"integer","description":"Relevance (only when searching with q)"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"docs_search","security":[]}},"/docs/{section}/{page}.json":{"get":{"operationId":"docs_get","summary":"Read a documentation page (Markdown and HTML)","description":"section and page come from the page path /docs/<section>/<page>. Use page \"index\" for a section overview.","tags":["Documentation"],"parameters":[{"name":"section","in":"path","required":true,"description":"Docs section, the first part of /docs/<section>/<page>, from docs_list","schema":{"type":"string"}},{"name":"page","in":"path","required":true,"description":"Docs page, the second part of /docs/<section>/<page>, from docs_list. Use index for the section overview","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"title":{"type":"string","description":"Page title"},"description":{"type":"string","description":"One-line summary"},"path":{"type":"string","description":"Page path. Add .md for Markdown or .json for JSON"},"section":{"type":"string","description":"Section slug, e.g. tracker"},"headings":{"type":"array","items":{"type":"object"},"description":"Sections on the page (id and text)"},"full_markdown":{"type":"string","description":"The page as Markdown (title included)"},"html":{"type":"string","description":"The page body rendered as HTML"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"docs_get","security":[]}},"/sites/{site_id}/domain-rating.json":{"get":{"operationId":"domain_rating_report","summary":"Domain Rating report: the latest rating, inbound and outbound links, the change since the release before and the history by month","description":"Returns the site's Domain Rating, a 0 to 100 estimate of how strong the links pointing at its domain are, plus inbound and outbound link counts and their history. This is Privatus Analytics' own score, not a Google metric. Ratings are updated once a month per release, so changes show monthly. months (1 to 120, default 12) sets how many monthly points of history to include. The result has domain, checked_at (when the site was last checked, null if never), release (the month of the latest data as YYYY-MM), rating, inbound_links, outbound_links (each null if not yet known), changes (the same three metrics as the difference against the previous release, null when either is unknown) and history (one row per month with month, rating, inbound_links, outbound_links, oldest first). A new site can be unrated for a few minutes. Needs analytics.read.","tags":["Domain Rating"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"months","in":"query","required":false,"schema":{"type":"integer","description":"How many monthly releases of history to return, from 1 to 120 (default 12). Values outside that range are rejected","default":12}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"domain_rating_report","x-permission":"analytics.read"}},"/recipients/{id}.json":{"delete":{"operationId":"email_report_recipients_delete","summary":"Remove a recipient from an email report","description":"Removes one address from an email report (id of the recipient, from email_report_recipients_list). The address stops receiving reports and its row is deleted. If the address had unsubscribed on its own the opt-out stays on record, so removing it does not allow anyone to invite it again. To change many addresses at once send the full list through email_reports_update instead. Returns the removed recipient.","tags":["Email reports"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by email_report_recipients_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Recipient id, e.g. rcp_7Q2K9XH3AB"},"email":{"type":"string","description":"The address"},"status":{"type":"string","description":"active, pending, declined or unsubscribed"},"invited_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last invite was sent"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a pending invite expires"},{"type":"null"}]},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the address became active"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"email_report_recipients_delete","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/reports/{report_id}/recipients.json":{"get":{"operationId":"email_report_recipients_list","summary":"List the recipients of an email report with their status","description":"Statuses: active (gets reports), pending (invited, not yet accepted), declined or unsubscribed. Add or remove addresses through the report's recipients list.","tags":["Email reports"],"parameters":[{"name":"report_id","in":"path","required":true,"description":"Email report id, from email_reports_list","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Only recipients with this status: active (receives reports), pending (invited, not accepted yet), declined or unsubscribed","enum":["pending","active","declined","unsubscribed"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Recipient id, e.g. rcp_7Q2K9XH3AB"},"email":{"type":"string","description":"The address"},"status":{"type":"string","description":"active, pending, declined or unsubscribed"},"invited_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last invite was sent"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a pending invite expires"},{"type":"null"}]},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the address became active"},{"type":"null"}]}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"email_report_recipients_list","x-permission":"analytics.read"}},"/recipients/{id}/resend.json":{"post":{"operationId":"email_report_recipients_resend","summary":"Resend a pending report invite","description":"Sends the invite again with new links. Allowed once every 7 days per address per report.","tags":["Email reports"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by email_report_recipients_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Recipient id, e.g. rcp_7Q2K9XH3AB"},"email":{"type":"string","description":"The address"},"status":{"type":"string","description":"active, pending, declined or unsubscribed"},"invited_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last invite was sent"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a pending invite expires"},{"type":"null"}]},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the address became active"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"email_report_recipients_resend","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/workspaces/{workspace_id}/reports.json":{"post":{"operationId":"email_reports_create","summary":"Create an email report","description":"Creates a scheduled analytics email report covering one or more sites (path takes workspace_id). Required are name and site_ids (pa_... ids). frequency is daily, weekly (default, sent on weekday) or monthly (the 1st of the month), hour is the hour of day 0 to 23 in the workspace timezone (default 8) and weekday is 0 for Sunday to 6 for Saturday (default 1, only used by weekly reports). blocks picks the content from kpis, chart, pages, sources, goals, campaigns, vitals, uptime, testimonials and subscriptions (default kpis, chart, pages, sources, goals, testimonials, subscriptions). subscriptions shows MRR and what moved it in the period, for a site with a payment provider connected. recipients is a list of email addresses (up to 50). Members of the workspace are active at once, any other address is pending and gets an invitation email, and receives reports only after accepting it. Addresses that opted out are refused. If recipients is omitted the calling user is added. An enabled report needs at least one recipient. The Free plan allows 3 reports, paid plans are unlimited. Returns the report with next_run_at. Use email_reports_send_test to preview it.","tags":["Email reports"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Report id, e.g. rep_7Q2K9XH3AB"},"name":{"type":"string"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Site ids in the report"},"frequency":{"type":"string","description":"daily, weekly or monthly"},"hour":{"type":"integer","description":"Send hour (workspace timezone)"},"weekday":{"type":"integer","description":"Weekly: 0 = Sunday … 6 = Saturday"},"recipients":{"type":"array","items":{"type":"string"},"description":"Every address on the report, whatever its status"},"recipient_details":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Recipient id, e.g. rcp_7Q2K9XH3AB"},"email":{"type":"string","description":"The address"},"status":{"type":"string","description":"active, pending, declined or unsubscribed"},"invited_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last invite was sent"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a pending invite expires"},{"type":"null"}]},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the address became active"},{"type":"null"}]}}},"description":"Each recipient with its opt-in status (only active recipients get reports)"},"blocks":{"type":"array","items":{"type":"string"},"description":"Content blocks"},"attach_pdf":{"type":"boolean"},"intro":{"anyOf":[{"type":"string"},{"type":"null"}]},"enabled":{"type":"boolean"},"last_sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"email_reports_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"site_ids":{"type":"array","items":{"type":"string"},"description":"Site ids (pa_..., from sites_list) the report covers. At least one is required"},"frequency":{"type":"string","description":"weekly (default, on weekday), daily or monthly (on the 1st). Each covers the complete previous day, 7 days or month","enum":["daily","weekly","monthly"]},"hour":{"type":"integer","description":"Hour of the day to send, 0 to 23, in the workspace timezone (default 8)"},"weekday":{"type":"integer","description":"Weekly reports only: 0 is Sunday to 6 is Saturday (default 1, Monday)"},"recipients":{"type":"array","items":{"type":"string"},"description":"Email addresses, up to 50 (no account needed). Entries may be comma or newline separated. Members of the workspace are active at once. Anyone else gets an invite email and receives reports only after accepting it. Addresses that opted out are refused. Left out, the calling user is added"},"blocks":{"type":"array","items":{"type":"string","enum":["kpis","chart","pages","sources","goals","campaigns","vitals","uptime","testimonials","subscriptions"]},"description":"Content sections in the email, any of kpis, chart, pages, sources, goals, campaigns, vitals, uptime, testimonials, subscriptions. Default kpis, chart, pages, sources, goals, testimonials, subscriptions"},"attach_pdf":{"type":"boolean","description":"Attach a PDF copy of the report (default false)"},"intro":{"type":"string","description":"Custom text shown at the top of the email, up to 2000 characters"},"enabled":{"type":"boolean","description":"Send on schedule (default true). An enabled report needs at least one recipient"},"name":{"type":"string","description":"Report name, up to 120 characters","examples":["Weekly traffic"]}},"required":["name"]}}}}},"get":{"operationId":"email_reports_list","summary":"List email reports","description":"Lists the scheduled email reports of a workspace (path takes workspace_id), sorted by name and paginated. Each report has id (rep_...), name, site_ids, frequency, hour, weekday, recipients (every address on the report), recipient_details (id, email, status, invited_at, expires_at, confirmed_at for each), blocks, attach_pdf, intro, enabled, last_sent_at, next_run_at and created_at. Filter by frequency (daily, weekly or monthly). A caller limited to some sites only sees reports whose sites are all theirs. Only recipients with status active actually receive reports. Use email_reports_deliveries for the send log.","tags":["Email reports"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"frequency","in":"query","required":false,"schema":{"type":"string","description":"Only reports with this frequency","enum":["daily","weekly","monthly"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Report id, e.g. rep_7Q2K9XH3AB"},"name":{"type":"string"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Site ids in the report"},"frequency":{"type":"string","description":"daily, weekly or monthly"},"hour":{"type":"integer","description":"Send hour (workspace timezone)"},"weekday":{"type":"integer","description":"Weekly: 0 = Sunday … 6 = Saturday"},"recipients":{"type":"array","items":{"type":"string"},"description":"Every address on the report, whatever its status"},"recipient_details":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Recipient id, e.g. rcp_7Q2K9XH3AB"},"email":{"type":"string","description":"The address"},"status":{"type":"string","description":"active, pending, declined or unsubscribed"},"invited_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last invite was sent"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a pending invite expires"},{"type":"null"}]},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the address became active"},{"type":"null"}]}}},"description":"Each recipient with its opt-in status (only active recipients get reports)"},"blocks":{"type":"array","items":{"type":"string"},"description":"Content blocks"},"attach_pdf":{"type":"boolean"},"intro":{"anyOf":[{"type":"string"},{"type":"null"}]},"enabled":{"type":"boolean"},"last_sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"email_reports_list","x-permission":"analytics.read"}},"/reports/{id}/deliveries.json":{"get":{"operationId":"email_reports_deliveries","summary":"Delivery log of an email report","description":"Lists the send log of one email report, newest first and paginated. Each entry has status (sent for a scheduled send, test, failed or skipped), recipients_count, error (the reason for a failure, otherwise null) and sent_at. Filter with status. Use it to confirm a scheduled report went out or to see why it failed. Use email_reports_send_test to trigger a test email.","tags":["Email reports"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by email_reports_list","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Only deliveries with this status: sent (scheduled), test, failed or skipped","enum":["sent","test","failed","skipped"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string","description":"sent, test, failed or skipped"},"recipients_count":{"type":"integer"},"error":{"anyOf":[{"type":"string"},{"type":"null"}]},"sent_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"email_reports_deliveries","x-permission":"analytics.read"}},"/reports/{id}.json":{"delete":{"operationId":"email_reports_delete","summary":"Delete an email report","description":"Permanently deletes an email report together with its recipients and delivery log. This cannot be undone and no further emails are sent. To stop sending but keep the report use email_reports_update with enabled false. The id (rep_...) comes from email_reports_list. Returns the deleted report.","tags":["Email reports"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by email_reports_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Report id, e.g. rep_7Q2K9XH3AB"},"name":{"type":"string"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Site ids in the report"},"frequency":{"type":"string","description":"daily, weekly or monthly"},"hour":{"type":"integer","description":"Send hour (workspace timezone)"},"weekday":{"type":"integer","description":"Weekly: 0 = Sunday … 6 = Saturday"},"recipients":{"type":"array","items":{"type":"string"},"description":"Every address on the report, whatever its status"},"recipient_details":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Recipient id, e.g. rcp_7Q2K9XH3AB"},"email":{"type":"string","description":"The address"},"status":{"type":"string","description":"active, pending, declined or unsubscribed"},"invited_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last invite was sent"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a pending invite expires"},{"type":"null"}]},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the address became active"},{"type":"null"}]}}},"description":"Each recipient with its opt-in status (only active recipients get reports)"},"blocks":{"type":"array","items":{"type":"string"},"description":"Content blocks"},"attach_pdf":{"type":"boolean"},"intro":{"anyOf":[{"type":"string"},{"type":"null"}]},"enabled":{"type":"boolean"},"last_sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"email_reports_delete","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"email_reports_get","summary":"Get an email report","description":"Returns one email report by id (rep_..., from email_reports_list). The response has name, site_ids, frequency, hour, weekday, recipients, recipient_details with each address and its opt-in status, blocks, attach_pdf, intro, enabled, last_sent_at and next_run_at (UTC timestamps). recipients lists every address including pending ones, only addresses with status active in recipient_details receive reports. Use email_reports_deliveries for what was sent.","tags":["Email reports"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by email_reports_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Report id, e.g. rep_7Q2K9XH3AB"},"name":{"type":"string"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Site ids in the report"},"frequency":{"type":"string","description":"daily, weekly or monthly"},"hour":{"type":"integer","description":"Send hour (workspace timezone)"},"weekday":{"type":"integer","description":"Weekly: 0 = Sunday … 6 = Saturday"},"recipients":{"type":"array","items":{"type":"string"},"description":"Every address on the report, whatever its status"},"recipient_details":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Recipient id, e.g. rcp_7Q2K9XH3AB"},"email":{"type":"string","description":"The address"},"status":{"type":"string","description":"active, pending, declined or unsubscribed"},"invited_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last invite was sent"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a pending invite expires"},{"type":"null"}]},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the address became active"},{"type":"null"}]}}},"description":"Each recipient with its opt-in status (only active recipients get reports)"},"blocks":{"type":"array","items":{"type":"string"},"description":"Content blocks"},"attach_pdf":{"type":"boolean"},"intro":{"anyOf":[{"type":"string"},{"type":"null"}]},"enabled":{"type":"boolean"},"last_sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"email_reports_get","x-permission":"analytics.read"},"patch":{"operationId":"email_reports_update","summary":"Update an email report","description":"Changes an email report (id from email_reports_list). Only the inputs you send change. Sending recipients replaces the whole list. Addresses you drop are removed, new ones follow the same opt-in rules as email_reports_create (members are active at once, others get an invitation email) and addresses already on the report keep their status. Changing frequency, hour, weekday or enabled recalculates next_run_at. Set enabled false to pause. Use email_report_recipients_list to see opt-in status and email_report_recipients_resend or email_report_recipients_delete to manage single addresses.","tags":["Email reports"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by email_reports_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Report id, e.g. rep_7Q2K9XH3AB"},"name":{"type":"string"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Site ids in the report"},"frequency":{"type":"string","description":"daily, weekly or monthly"},"hour":{"type":"integer","description":"Send hour (workspace timezone)"},"weekday":{"type":"integer","description":"Weekly: 0 = Sunday … 6 = Saturday"},"recipients":{"type":"array","items":{"type":"string"},"description":"Every address on the report, whatever its status"},"recipient_details":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Recipient id, e.g. rcp_7Q2K9XH3AB"},"email":{"type":"string","description":"The address"},"status":{"type":"string","description":"active, pending, declined or unsubscribed"},"invited_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last invite was sent"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a pending invite expires"},{"type":"null"}]},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the address became active"},{"type":"null"}]}}},"description":"Each recipient with its opt-in status (only active recipients get reports)"},"blocks":{"type":"array","items":{"type":"string"},"description":"Content blocks"},"attach_pdf":{"type":"boolean"},"intro":{"anyOf":[{"type":"string"},{"type":"null"}]},"enabled":{"type":"boolean"},"last_sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"email_reports_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"site_ids":{"type":"array","items":{"type":"string"},"description":"Replaces the site ids (pa_..., from sites_list) the report covers"},"frequency":{"type":"string","description":"daily, weekly (on weekday) or monthly (on the 1st)","enum":["daily","weekly","monthly"]},"hour":{"type":"integer","description":"Hour of the day to send, 0 to 23, in the workspace timezone"},"weekday":{"type":"integer","description":"Weekly reports only: 0 is Sunday to 6 is Saturday"},"recipients":{"type":"array","items":{"type":"string"},"description":"Replaces the whole address list. Addresses left out are removed, addresses already on the report keep their status, new members are active at once and other new addresses get an invite email. Up to 50, comma or newline separated entries are split"},"blocks":{"type":"array","items":{"type":"string","enum":["kpis","chart","pages","sources","goals","campaigns","vitals","uptime","testimonials","subscriptions"]},"description":"Replaces the content sections, any of kpis, chart, pages, sources, goals, campaigns, vitals, uptime, testimonials, subscriptions"},"attach_pdf":{"type":"boolean","description":"Attach a PDF copy of the report"},"intro":{"type":"string","description":"Custom text shown at the top of the email, up to 2000 characters. Send an empty string to remove it"},"enabled":{"type":"boolean","description":"Send on schedule. Set false to pause"},"name":{"type":"string","description":"Report name, up to 120 characters"}}}}}}}},"/reports/{id}/send_test.json":{"post":{"operationId":"email_reports_send_test","summary":"Send an email report now as a test","description":"Sends the report to one address right now as a test, without changing its schedule or last_sent_at. Sends a real email, so only use it when the user wants that. recipient defaults to the calling user and may only be the caller, another member of the workspace or an active recipient of the report. For any other address the test goes to the caller instead. Test sends are rate limited per workspace and per outside address, and a refused send returns a rate limit error. Returns the delivery with status (test, or failed with the reason in error), recipients_count and sent_at. Use email_reports_deliveries for the full log.","tags":["Email reports"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by email_reports_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string","description":"sent, test, failed or skipped"},"recipients_count":{"type":"integer"},"error":{"anyOf":[{"type":"string"},{"type":"null"}]},"sent_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"email_reports_send_test","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"recipient":{"type":"string","description":"Email address to send the test to (default the calling user). Only the caller, members of the workspace and active recipients of the report are allowed, any other address sends to the caller instead"}}}}}}}},"/reports/invites/{token}/accept.json":{"post":{"operationId":"report_invites_accept","summary":"Accept a report invite","tags":["Email reports"],"parameters":[{"name":"token","in":"path","required":true,"description":"Invite token from the email","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Recipient id, e.g. rcp_7Q2K9XH3AB"},"email":{"type":"string","description":"The address"},"status":{"type":"string","description":"active, pending, declined or unsubscribed"},"invited_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last invite was sent"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a pending invite expires"},{"type":"null"}]},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the address became active"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Invite token from the email"}},"required":["token"]}}}},"security":[]}},"/reports/invites/{token}/decline.json":{"post":{"operationId":"report_invites_decline","summary":"Decline a report invite","tags":["Email reports"],"parameters":[{"name":"token","in":"path","required":true,"description":"Invite token from the email","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Recipient id, e.g. rcp_7Q2K9XH3AB"},"email":{"type":"string","description":"The address"},"status":{"type":"string","description":"active, pending, declined or unsubscribed"},"invited_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last invite was sent"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a pending invite expires"},{"type":"null"}]},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the address became active"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Invite token from the email"}},"required":["token"]}}}},"security":[]}},"/reports/resubscribe/{token}.json":{"post":{"operationId":"report_resubscribes_confirm","summary":"Receive reports again after opting out","tags":["Email reports"],"parameters":[{"name":"token","in":"path","required":true,"description":"Signed opt-in token from the confirmation email","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Signed opt-in token from the confirmation email"}},"required":["token"]}}}},"security":[]}},"/reports/unsubscribe/{token}/resubscribe.json":{"post":{"operationId":"report_resubscribes_create","summary":"Email an address a link to receive reports again","tags":["Email reports"],"parameters":[{"name":"token","in":"path","required":true,"description":"Signed unsubscribe token from the report email","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Signed unsubscribe token from the report email"}},"required":["token"]}}}},"security":[]}},"/reports/unsubscribe/{token}.json":{"post":{"operationId":"report_unsubscribes_create","summary":"Unsubscribe an address from an email report","tags":["Email reports"],"parameters":[{"name":"token","in":"path","required":true,"description":"Signed unsubscribe token from the email","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Signed unsubscribe token from the email"}},"required":["token"]}}}},"security":[]}},"/email/preferences/{token}/unsubscribe.json":{"post":{"operationId":"email_preferences_unsubscribe_all","summary":"Stop every email to an address that it can turn off, with the token from its email settings link","tags":["Email settings"],"parameters":[{"name":"token","in":"path","required":true,"description":"The token from the email settings link at the foot of one of our emails","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"The token from the email settings link at the foot of one of our emails"}},"required":["token"]}}}},"security":[]}},"/email/preferences/{token}.json":{"post":{"operationId":"email_preferences_update","summary":"Turn emails to an address off or on with the token from its email settings link","tags":["Email settings"],"parameters":[{"name":"token","in":"path","required":true,"description":"The token from the email settings link at the foot of one of our emails","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"The token from the email settings link at the foot of one of our emails"},"stop":{"type":"array","items":{"type":"string"},"description":"Keys of the emails to turn off, as listed on the page (marketing, product, site_audit, newsletter, report:rep_..., alert_channel:nch_..., uptime_check:upc_..., status_page:sp_...)","default":[]},"resume":{"type":"array","items":{"type":"string"},"description":"Keys of alert_channel or uptime_check emails to turn back on for this address","default":[]},"keep":{"type":"array","items":{"type":"string"},"description":"The full list of keys to keep getting. Every listed email not in it is turned off, and alert and uptime emails in it come back on"}},"required":["token"]}}}},"security":[]}},"/sites/{site_id}/events/properties.json":{"get":{"operationId":"event_properties_list","summary":"List event property keys seen in the last 30 days","description":"Lists the property keys that custom events carried in the last 30 days, with display settings. Returns a list of {key, events, display_name, hidden, export_safe}. events is how many custom events carried the key (0 for a key that has settings but was not seen recently), display_name is the rename (null when none), hidden says the key is hidden from reports, and export_safe says it is marked as containing no personal data. At most 200 keys are returned, most used first. Pass event to see only keys seen on one raw event name. Property values are never returned here, use stats_breakdown with dimension prop:<key> or events_get for values. Change settings with event_properties_update.","tags":["Events"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"event","in":"query","required":false,"schema":{"type":"string","description":"Only keys seen on this raw event name, as stored (see raw_names in events_list). Leave empty for all custom events"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"event_properties_list","x-permission":"analytics.read"},"patch":{"operationId":"event_properties_update","summary":"Rename or hide an event property key","description":"Renames, hides or marks as export-safe one event property key, for the whole site. Only the inputs you send change. key must be the key as stored (lowercase letters, digits and underscores, up to 64 characters, for example plan). display_name is a label of up to 64 characters (send it empty to remove the rename). hidden removes the key from reports and the event detail pivot while the data is kept. export_safe declares that the key never holds personal data, which includes its values in raw exports and warehouse syncs, so set it only when that is true. Renames and hiding apply when reports are read and rewrite no stored data. Returns {key, display_name, hidden, export_safe}. Needs the sites.manage permission. List the keys with event_properties_list.","tags":["Events"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"event_properties_update","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string","description":"Property key exactly as stored. Lowercase letters, digits and underscores only, 1 to 64 characters, for example plan"},"display_name":{"type":"string","description":"Label to show instead of the key, up to 64 characters. Send an empty string to remove the rename"},"hidden":{"type":"boolean","description":"Hide this key from reports"},"export_safe":{"type":"boolean","description":"The key contains no personal data, so it is included in raw exports and warehouse syncs"}},"required":["key"]}}}}}},"/sites/{site_id}/events.json":{"delete":{"operationId":"events_delete","summary":"Delete an event and its history (runs in the background, confirm by typing the name)","description":"Permanently deletes a custom event and its whole history. This cannot be undone. The raw event name must be sent twice, in name and again in confirm, as a safety check. Returns {name, status: queued} with HTTP 202 because the rows are removed in the background in batches, so numbers keep changing until it finishes. The event is also hidden right away, and the deletion is recorded in the audit log. Pageviews are not affected. If you only want to stop showing an event, use events_update with hidden true, which keeps the data. Needs the sites.manage permission. Names come from events_list (use the raw_names field if the event was renamed or merged).","tags":["Events"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Raw event name to delete, exactly as stored (see raw_names in events_list). All history of this event is deleted"},"confirm":{"type":"string","description":"Must be exactly the same text as name, as a safety check. A different value is rejected"}},"required":["name","confirm"]}}}}},"get":{"operationId":"events_list","summary":"List events with completions, visits, conversion rate and first/last seen","description":"The events explorer: every custom event in the period. Returns period, events and hidden. Each event has name (the display name after renames and merges), raw_names (the names the tracker sent), completions, visits, conversion_rate (percent of visits, 0 to 100), revenue (minor units, cents), first_seen and last_seen (ISO 8601 timestamps within the period) and currency (the revenue currency, null when unset). hidden lists events you hid as {name, display_name}. Use search to keep events whose name contains some text. Pageviews are not events here. Use events_get for one event in depth and stats_breakdown with dimension event for a ranked, paginated list. Takes the shared period, compare, filters and segment inputs.","tags":["Events"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"search","in":"query","required":false,"schema":{"type":"string","description":"Only events whose name contains this text, case-insensitive"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"events_list","x-permission":"analytics.read"}},"/sites/{site_id}/events/merge.json":{"post":{"operationId":"events_merge","summary":"Merge several events into one display name","description":"Merges several raw event names into one display name, for example signup_click and signup_button into Signup. Reports then show a single event with the combined counts. It works when reports are read and the stored events are not changed or deleted. Pass names (the raw names, at least one) and into (the display name). Returns one settings object per merged name, each {name, display_name, hidden, currency, updated_at}. To undo, call events_update for a name with an empty display_name. Needs the sites.manage permission. Names come from events_list (raw_names).","tags":["Events"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"name":{"type":"string","description":"Raw event name as sent by the tracker"},"display_name":{"anyOf":[{"type":"string","description":"Name shown in reports"},{"type":"null"}]},"hidden":{"type":"boolean","description":"Hidden from reports"},"currency":{"anyOf":[{"type":"string","description":"Revenue currency"},{"type":"null"}]},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"events_merge","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"names":{"type":"array","items":{"type":"string"},"description":"Raw event names to merge, as stored (see raw_names in events_list), for example [\"signup_click\",\"signup_button\"]"},"into":{"type":"string","description":"Display name that the merged events are shown under, up to 120 characters","examples":["Signup"]}},"required":["names","into"]}}}}}},"/sites/{site_id}/events/detail.json":{"get":{"operationId":"events_get","summary":"One event: chart, property pivot, number property aggregates, pages and sources","description":"Detail of one custom event. Pass name exactly as shown in events_list (the display name after renames and merges). Returns period, name, raw_names (the stored names behind it), interval, totals, setting, series, property_keys, pivot, numeric, pages, channels and referrers. totals has completions, visits (visits that fired it), revenue (minor units, cents) and conversion_rate (percent of all visits in the period). series is completions per time bucket. setting has display_name, hidden and currency. property_keys lists the property keys seen. Send properties (up to 3 keys) to get pivot, rows of {values, completions, visits} for each value combination, top 100. numeric gives sum, average and other figures for properties that hold numbers. pages, channels and referrers are the top 10 places the event fired, as {value, completions, visits}. Use events_list for all events, stats_breakdown with dimension prop:<key> for one property across the site, and events_update to rename it.","tags":["Events"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"name","in":"query","required":false,"schema":{"type":"string","description":"Event name as shown in events_list (the display name after renames and merges), for example Signup","examples":["Signup"]}},{"name":"properties","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Up to 3 property keys (lowercase letters, digits and underscores, up to 64 characters) to pivot by, for example [\"plan\",\"method\"]. Returns the top 100 value combinations","default":[]}},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Chart bucket size. auto picks one to suit the range","enum":["auto","minute","hour","day","week","month","quarter","year"],"default":"auto"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"events_get","x-permission":"analytics.read"}},"/sites/{site_id}/events/settings.json":{"patch":{"operationId":"events_update","summary":"Rename, hide or unhide an event, or set its currency","description":"Changes how one custom event is shown: rename it with display_name, hide or unhide it with hidden, or set the revenue currency. name is the raw event name as the tracker sent it (see raw_names in events_list). Only the inputs you send change. An empty display_name removes the rename. hidden removes the event from lists and reports while its data is kept. currency is a three-letter ISO 4217 code such as USD, stored in uppercase. This works when reports are read and no stored events are rewritten. Returns {name, display_name, hidden, currency, updated_at}. To combine several events use events_merge, and to erase data use events_delete. Needs the sites.manage permission.","tags":["Events"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"name":{"type":"string","description":"Raw event name as sent by the tracker"},"display_name":{"anyOf":[{"type":"string","description":"Name shown in reports"},{"type":"null"}]},"hidden":{"type":"boolean","description":"Hidden from reports"},"currency":{"anyOf":[{"type":"string","description":"Revenue currency"},{"type":"null"}]},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"events_update","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Raw event name exactly as the tracker sent it (see raw_names in events_list), not a display name","examples":["signup_click"]},"display_name":{"type":"string","description":"Name to show instead, up to 120 characters. Send an empty string to remove the rename"},"hidden":{"type":"boolean","description":"true hides the event from lists and reports (the data is kept), false shows it again"},"currency":{"type":"string","description":"Currency of this event's revenue as a three-letter ISO 4217 code, for example USD. Stored in uppercase. Send an empty string to clear it"}},"required":["name"]}}}}}},"/sites/{site_id}/experiments.json":{"post":{"operationId":"experiments_create","summary":"Create an experiment as a draft","description":"Creates an A/B or split URL test for a site. It is saved as a draft and sends no visitor anywhere until a person starts it in the app. Required are name, path (the original page, such as /pricing), goal_id (from goals_list) and variants: a list of { name, path, weight } where the first row is the original page (its path is ignored) and each other row is a page of the same site. Leave every weight out for an even split, or send weights that add up to 100. The Free plan allows one experiment at a time with the original and one variant. Pro and up add more variants, automatic allocation, targeting, a * in the path, secondary goals, a scheduled start and exclusive groups. Requires content.write. Returns the experiment.","tags":["Experiments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, scheduled, running, paused or ended"},"kind":{"type":"string","description":"page (an A/B or split URL test) or ad (a test of the creatives of an ad placement)"},"path":{"anyOf":[{"type":"string","description":"The original page being tested. null in an ad experiment"},{"type":"null"}]},"placement_id":{"anyOf":[{"type":"string","description":"The ad placement (adp_...) whose creatives are compared. null in a page test"},{"type":"null"}]},"paths":{"type":"array","items":{"type":"string"},"description":"The pages of the site an ad experiment is limited to. Empty means all"},"goal_id":{"anyOf":[{"type":"string","description":"The goal the result is decided on. null when that goal was deleted"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of that goal. null without one"},{"type":"null"}]},"secondary_goal_ids":{"type":"array","items":{"type":"string"},"description":"Goals reported next to the main one"},"variants":{"type":"array","items":{"type":"object"},"description":"The pages compared, each { id, name, path, weight, control }. The original page comes first"},"allocation":{"type":"string","description":"manual keeps the shares as set, auto moves visitors toward the leading variant"},"traffic_share":{"type":"integer","description":"Percent of the page's visitors who take part"},"min_days":{"type":"integer","description":"Shortest duration in days"},"max_days":{"type":"integer","description":"Longest duration in days"},"min_sample":{"type":"integer","description":"Visits each variant needs before a winner can be called"},"confidence":{"type":"integer","description":"Confidence a variant must reach to win: 90, 95 or 99"},"send_to_winner":{"type":"boolean","description":"Whether every visitor is sent to the winner after the experiment ends"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices that take part. Empty means all"},"countries":{"type":"array","items":{"type":"string"},"description":"Country codes that take part. Empty means all"},"channels":{"type":"array","items":{"type":"string"},"description":"Channels that take part. Empty means all"},"exclusive_group":{"anyOf":[{"type":"string","description":"Experiments with the same group never share a visitor"},{"type":"null"}]},"starts_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled experiment starts by itself"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time","description":"When visitors first took part"},{"type":"null"}]},"ended_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it ended"},{"type":"null"}]},"end_reason":{"anyOf":[{"type":"string","description":"winner, no_winner or manual"},{"type":"null"}]},"winner_id":{"anyOf":[{"type":"string","description":"The winning variant (var_...), if there is one"},{"type":"null"}]},"locked":{"type":"boolean","description":"True when the workspace's plan no longer covers this experiment. It redirects nobody until the plan does"},"stats":{"anyOf":[{"type":"object","properties":{"visits":{"type":"integer","description":"Visits that saw any page of the experiment"},"conversions":{"type":"integer","description":"Of those, the visits that reached the goal afterwards"},"conversion_rate":{"type":"number","description":"conversions divided by visits, as a percent from 0 to 100"}},"description":"On experiments_list only: visits, conversions and conversion_rate across all variants. null until the experiment has started"},{"type":"null"}]},"results":{"anyOf":[{"type":"object","description":"On experiments_get only. goal, confidence, progress (days_running, sample_reached, ready, days_left), mismatch (whether visits are shared out as the weights say), leader_id, winner_id, decided, and variants: each with visits, conversions, conversion_rate (percent), and against the original uplift (percent), interval (low and high of the difference, in percentage points), p_value, significant and chance (percent chance that it beats the original), plus revenue and revenue_per_visit in minor units and the secondary goals. split holds the breakdown when one was asked for. timeline holds the experiment day by day in the site timezone: dates, for each variant its visits and conversions per day and its conversion_rate (percent) of everything up to that day, and events (started, paused, resumed, ended, each with at and date)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"experiments_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Internal name shown in the app, max 120 characters","examples":["Shorter pricing page"]},"kind":{"type":"string","description":"page (default), an A/B or split URL test of a page, or ad, a test of the creatives of an ad placement","enum":["page","ad"],"default":"page"},"path":{"type":"string","description":"The original page, as a path of the site that starts with a slash, such as /pricing. No address and no query string. One * stands for a part of the path (Pro and up), and every variant then needs one too","examples":["/pricing"]},"goal_id":{"type":"string","description":"Active goal (goal_..., from goals_list) the result is decided on","examples":["goal_7Q2K9XH3AB"]},"ad_placement_id":{"type":"string","description":"For kind ad: the placement (adp_..., from ad_placements_list) whose creatives are compared. Not needed for a page test","examples":["adp_7Q2K9XH3AB"]},"variants":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"For kind ad, the creatives to compare, a list of { creative_id, weight } (adc_..., ready creatives of the placement), the first being the original. For a page test, the pages to compare, a list of { name, path, weight }. The first row is the original page and its path is ignored. Each other path is a page of the same site, such as /pricing-b. weight is a percent, and the weights add up to 100. Leave every weight out for an even split"},"secondary_goal_ids":{"type":"array","items":{"type":"string"},"description":"More goals (goal_...) reported next to the main one. They never end the experiment. Pro and up","default":[]},"allocation":{"type":"string","description":"manual (default) keeps the shares you set. auto moves visitors toward the leading variant once a day (Pro and up)","enum":["manual","auto"],"default":"manual"},"traffic_share":{"type":"integer","description":"Percent of the page's visitors who take part at all, from 1 to 100. Default 100. The rest see the original page and are not counted","default":100},"min_days":{"type":"integer","description":"Shortest duration in days, from 1 to 90. Default 7. No winner is called before it","default":7},"max_days":{"type":"integer","description":"Longest duration in days, from 1 to 90, the same as min_days or more. Default 30. The experiment ends then, with or without a winner","default":30},"min_sample":{"type":"integer","description":"Visits each variant needs before a winner can be called. Default 100","default":100},"confidence":{"type":"integer","description":"Confidence a variant must reach against the original to win: 90, 95 (default) or 99","enum":[90,95,99],"default":95},"send_to_winner":{"type":"boolean","description":"After a winner is found, send every visitor of the original page to it until you turn this off. Default true","default":true},"devices":{"type":"array","items":{"type":"string","enum":["desktop","mobile","tablet"]},"description":"Only visitors on these devices take part. Empty list means all. Pro and up","default":[]},"countries":{"type":"array","items":{"type":"string"},"description":"Only visitors from these two-letter country codes take part, such as [\"US\",\"CA\"]. Empty list means all. Pro and up","default":[]},"channels":{"type":"array","items":{"type":"string"},"description":"Only visits from these channels take part. Empty list means all. Pro and up","default":[]},"exclusive_group":{"type":"string","description":"A name shared by experiments that must not overlap: a visitor takes part in one experiment of a group at most. Pro and up"},"starts_at":{"type":"string","format":"date-time","description":"When to start by itself, ISO 8601. The experiment waits as scheduled once a person has started it. Pro and up"},"paths":{"type":"array","items":{"type":"string"},"description":"For kind ad: only on these pages of the site, such as [\"/tools/*\"]. Empty list means all. Pro and up","default":[]}},"required":["name","variants"]}}}}},"get":{"operationId":"experiments_list","summary":"List a site's experiments with their visits and conversions","description":"Lists the A/B and split URL tests of a site, newest first. Filter with status (draft, scheduled, running, paused, ended or all, default all). Paginated with page and per_page (default 25, up to 100). Each experiment has id (exp_...), name, status, path (the original page), goal_id and goal_name, variants (id, name, path, weight, control), the rules for ending it, locked (true when the plan no longer covers it) and stats (visits, conversions and conversion_rate across all its variants, null until it has started). Use experiments_get for the results per variant. Requires analytics.read.","tags":["Experiments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Only experiments with this status: draft, scheduled, running, paused, ended or all","enum":["draft","scheduled","running","paused","ended","all"],"default":"all"}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","description":"Only page tests (page) or ad experiments (ad). Leave out for both","enum":["page","ad"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","description":"Page number","default":1}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","description":"Rows per page (up to 100)","default":25}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, scheduled, running, paused or ended"},"kind":{"type":"string","description":"page (an A/B or split URL test) or ad (a test of the creatives of an ad placement)"},"path":{"anyOf":[{"type":"string","description":"The original page being tested. null in an ad experiment"},{"type":"null"}]},"placement_id":{"anyOf":[{"type":"string","description":"The ad placement (adp_...) whose creatives are compared. null in a page test"},{"type":"null"}]},"paths":{"type":"array","items":{"type":"string"},"description":"The pages of the site an ad experiment is limited to. Empty means all"},"goal_id":{"anyOf":[{"type":"string","description":"The goal the result is decided on. null when that goal was deleted"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of that goal. null without one"},{"type":"null"}]},"secondary_goal_ids":{"type":"array","items":{"type":"string"},"description":"Goals reported next to the main one"},"variants":{"type":"array","items":{"type":"object"},"description":"The pages compared, each { id, name, path, weight, control }. The original page comes first"},"allocation":{"type":"string","description":"manual keeps the shares as set, auto moves visitors toward the leading variant"},"traffic_share":{"type":"integer","description":"Percent of the page's visitors who take part"},"min_days":{"type":"integer","description":"Shortest duration in days"},"max_days":{"type":"integer","description":"Longest duration in days"},"min_sample":{"type":"integer","description":"Visits each variant needs before a winner can be called"},"confidence":{"type":"integer","description":"Confidence a variant must reach to win: 90, 95 or 99"},"send_to_winner":{"type":"boolean","description":"Whether every visitor is sent to the winner after the experiment ends"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices that take part. Empty means all"},"countries":{"type":"array","items":{"type":"string"},"description":"Country codes that take part. Empty means all"},"channels":{"type":"array","items":{"type":"string"},"description":"Channels that take part. Empty means all"},"exclusive_group":{"anyOf":[{"type":"string","description":"Experiments with the same group never share a visitor"},{"type":"null"}]},"starts_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled experiment starts by itself"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time","description":"When visitors first took part"},{"type":"null"}]},"ended_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it ended"},{"type":"null"}]},"end_reason":{"anyOf":[{"type":"string","description":"winner, no_winner or manual"},{"type":"null"}]},"winner_id":{"anyOf":[{"type":"string","description":"The winning variant (var_...), if there is one"},{"type":"null"}]},"locked":{"type":"boolean","description":"True when the workspace's plan no longer covers this experiment. It redirects nobody until the plan does"},"stats":{"anyOf":[{"type":"object","properties":{"visits":{"type":"integer","description":"Visits that saw any page of the experiment"},"conversions":{"type":"integer","description":"Of those, the visits that reached the goal afterwards"},"conversion_rate":{"type":"number","description":"conversions divided by visits, as a percent from 0 to 100"}},"description":"On experiments_list only: visits, conversions and conversion_rate across all variants. null until the experiment has started"},{"type":"null"}]},"results":{"anyOf":[{"type":"object","description":"On experiments_get only. goal, confidence, progress (days_running, sample_reached, ready, days_left), mismatch (whether visits are shared out as the weights say), leader_id, winner_id, decided, and variants: each with visits, conversions, conversion_rate (percent), and against the original uplift (percent), interval (low and high of the difference, in percentage points), p_value, significant and chance (percent chance that it beats the original), plus revenue and revenue_per_visit in minor units and the secondary goals. split holds the breakdown when one was asked for. timeline holds the experiment day by day in the site timezone: dates, for each variant its visits and conversions per day and its conversion_rate (percent) of everything up to that day, and events (started, paused, resumed, ended, each with at and date)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"experiments_list","x-permission":"analytics.read"}},"/sites/{site_id}/experiments/{id}.json":{"delete":{"operationId":"experiments_delete","summary":"Delete an experiment with its results","description":"Permanently deletes an experiment with its variants and results. This cannot be undone. Use experiments_pause to stop it and keep the results. The MCP tool does not run it and responds with human_only and the page where a person deletes it. Requires content.write.","tags":["Experiments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by experiments_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, scheduled, running, paused or ended"},"kind":{"type":"string","description":"page (an A/B or split URL test) or ad (a test of the creatives of an ad placement)"},"path":{"anyOf":[{"type":"string","description":"The original page being tested. null in an ad experiment"},{"type":"null"}]},"placement_id":{"anyOf":[{"type":"string","description":"The ad placement (adp_...) whose creatives are compared. null in a page test"},{"type":"null"}]},"paths":{"type":"array","items":{"type":"string"},"description":"The pages of the site an ad experiment is limited to. Empty means all"},"goal_id":{"anyOf":[{"type":"string","description":"The goal the result is decided on. null when that goal was deleted"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of that goal. null without one"},{"type":"null"}]},"secondary_goal_ids":{"type":"array","items":{"type":"string"},"description":"Goals reported next to the main one"},"variants":{"type":"array","items":{"type":"object"},"description":"The pages compared, each { id, name, path, weight, control }. The original page comes first"},"allocation":{"type":"string","description":"manual keeps the shares as set, auto moves visitors toward the leading variant"},"traffic_share":{"type":"integer","description":"Percent of the page's visitors who take part"},"min_days":{"type":"integer","description":"Shortest duration in days"},"max_days":{"type":"integer","description":"Longest duration in days"},"min_sample":{"type":"integer","description":"Visits each variant needs before a winner can be called"},"confidence":{"type":"integer","description":"Confidence a variant must reach to win: 90, 95 or 99"},"send_to_winner":{"type":"boolean","description":"Whether every visitor is sent to the winner after the experiment ends"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices that take part. Empty means all"},"countries":{"type":"array","items":{"type":"string"},"description":"Country codes that take part. Empty means all"},"channels":{"type":"array","items":{"type":"string"},"description":"Channels that take part. Empty means all"},"exclusive_group":{"anyOf":[{"type":"string","description":"Experiments with the same group never share a visitor"},{"type":"null"}]},"starts_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled experiment starts by itself"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time","description":"When visitors first took part"},{"type":"null"}]},"ended_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it ended"},{"type":"null"}]},"end_reason":{"anyOf":[{"type":"string","description":"winner, no_winner or manual"},{"type":"null"}]},"winner_id":{"anyOf":[{"type":"string","description":"The winning variant (var_...), if there is one"},{"type":"null"}]},"locked":{"type":"boolean","description":"True when the workspace's plan no longer covers this experiment. It redirects nobody until the plan does"},"stats":{"anyOf":[{"type":"object","properties":{"visits":{"type":"integer","description":"Visits that saw any page of the experiment"},"conversions":{"type":"integer","description":"Of those, the visits that reached the goal afterwards"},"conversion_rate":{"type":"number","description":"conversions divided by visits, as a percent from 0 to 100"}},"description":"On experiments_list only: visits, conversions and conversion_rate across all variants. null until the experiment has started"},{"type":"null"}]},"results":{"anyOf":[{"type":"object","description":"On experiments_get only. goal, confidence, progress (days_running, sample_reached, ready, days_left), mismatch (whether visits are shared out as the weights say), leader_id, winner_id, decided, and variants: each with visits, conversions, conversion_rate (percent), and against the original uplift (percent), interval (low and high of the difference, in percentage points), p_value, significant and chance (percent chance that it beats the original), plus revenue and revenue_per_visit in minor units and the secondary goals. split holds the breakdown when one was asked for. timeline holds the experiment day by day in the site timezone: dates, for each variant its visits and conversions per day and its conversion_rate (percent) of everything up to that day, and events (started, paused, resumed, ended, each with at and date)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"experiments_get","summary":"Get one experiment with its results","description":"Returns one experiment by id (exp_..., from experiments_list) with its results: per variant the visits, conversions and conversion rate on the goal, and against the original the uplift, the likely range of the difference, the p-value, whether it is significant at the chosen confidence and the chance that it beats the original. results.progress says how far it is from being able to call a winner, and results.mismatch.found true means the visits are not shared out as the weights say, so the result should not be trusted. split breaks the results down by device, channel or country (Pro and up) and humans_only keeps visits the bot score calls likely human (Pro and up). A visit is counted for a variant when it saw that variant, and a conversion counts only after that. Requires analytics.read.","tags":["Experiments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by experiments_list","schema":{"type":"string"}},{"name":"split","in":"query","required":false,"schema":{"type":"string","description":"Break the results down by one visit attribute: device, channel or country. Pro and up","enum":["device","channel","country","page"]}},{"name":"humans_only","in":"query","required":false,"schema":{"type":"boolean","description":"Count only visits the bot score calls likely human. Pro and up","default":false}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, scheduled, running, paused or ended"},"kind":{"type":"string","description":"page (an A/B or split URL test) or ad (a test of the creatives of an ad placement)"},"path":{"anyOf":[{"type":"string","description":"The original page being tested. null in an ad experiment"},{"type":"null"}]},"placement_id":{"anyOf":[{"type":"string","description":"The ad placement (adp_...) whose creatives are compared. null in a page test"},{"type":"null"}]},"paths":{"type":"array","items":{"type":"string"},"description":"The pages of the site an ad experiment is limited to. Empty means all"},"goal_id":{"anyOf":[{"type":"string","description":"The goal the result is decided on. null when that goal was deleted"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of that goal. null without one"},{"type":"null"}]},"secondary_goal_ids":{"type":"array","items":{"type":"string"},"description":"Goals reported next to the main one"},"variants":{"type":"array","items":{"type":"object"},"description":"The pages compared, each { id, name, path, weight, control }. The original page comes first"},"allocation":{"type":"string","description":"manual keeps the shares as set, auto moves visitors toward the leading variant"},"traffic_share":{"type":"integer","description":"Percent of the page's visitors who take part"},"min_days":{"type":"integer","description":"Shortest duration in days"},"max_days":{"type":"integer","description":"Longest duration in days"},"min_sample":{"type":"integer","description":"Visits each variant needs before a winner can be called"},"confidence":{"type":"integer","description":"Confidence a variant must reach to win: 90, 95 or 99"},"send_to_winner":{"type":"boolean","description":"Whether every visitor is sent to the winner after the experiment ends"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices that take part. Empty means all"},"countries":{"type":"array","items":{"type":"string"},"description":"Country codes that take part. Empty means all"},"channels":{"type":"array","items":{"type":"string"},"description":"Channels that take part. Empty means all"},"exclusive_group":{"anyOf":[{"type":"string","description":"Experiments with the same group never share a visitor"},{"type":"null"}]},"starts_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled experiment starts by itself"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time","description":"When visitors first took part"},{"type":"null"}]},"ended_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it ended"},{"type":"null"}]},"end_reason":{"anyOf":[{"type":"string","description":"winner, no_winner or manual"},{"type":"null"}]},"winner_id":{"anyOf":[{"type":"string","description":"The winning variant (var_...), if there is one"},{"type":"null"}]},"locked":{"type":"boolean","description":"True when the workspace's plan no longer covers this experiment. It redirects nobody until the plan does"},"stats":{"anyOf":[{"type":"object","properties":{"visits":{"type":"integer","description":"Visits that saw any page of the experiment"},"conversions":{"type":"integer","description":"Of those, the visits that reached the goal afterwards"},"conversion_rate":{"type":"number","description":"conversions divided by visits, as a percent from 0 to 100"}},"description":"On experiments_list only: visits, conversions and conversion_rate across all variants. null until the experiment has started"},{"type":"null"}]},"results":{"anyOf":[{"type":"object","description":"On experiments_get only. goal, confidence, progress (days_running, sample_reached, ready, days_left), mismatch (whether visits are shared out as the weights say), leader_id, winner_id, decided, and variants: each with visits, conversions, conversion_rate (percent), and against the original uplift (percent), interval (low and high of the difference, in percentage points), p_value, significant and chance (percent chance that it beats the original), plus revenue and revenue_per_visit in minor units and the secondary goals. split holds the breakdown when one was asked for. timeline holds the experiment day by day in the site timezone: dates, for each variant its visits and conversions per day and its conversion_rate (percent) of everything up to that day, and events (started, paused, resumed, ended, each with at and date)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"experiments_get","x-permission":"analytics.read"},"patch":{"operationId":"experiments_update","summary":"Update an experiment","description":"Changes an experiment. Only the inputs you send change, and variants replaces the whole list. Once an experiment has started only name and send_to_winner can change, because new pages, shares or goals part way through would spoil the result: use experiments_duplicate and edit the copy. Requires content.write. Returns the experiment.","tags":["Experiments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by experiments_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, scheduled, running, paused or ended"},"kind":{"type":"string","description":"page (an A/B or split URL test) or ad (a test of the creatives of an ad placement)"},"path":{"anyOf":[{"type":"string","description":"The original page being tested. null in an ad experiment"},{"type":"null"}]},"placement_id":{"anyOf":[{"type":"string","description":"The ad placement (adp_...) whose creatives are compared. null in a page test"},{"type":"null"}]},"paths":{"type":"array","items":{"type":"string"},"description":"The pages of the site an ad experiment is limited to. Empty means all"},"goal_id":{"anyOf":[{"type":"string","description":"The goal the result is decided on. null when that goal was deleted"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of that goal. null without one"},{"type":"null"}]},"secondary_goal_ids":{"type":"array","items":{"type":"string"},"description":"Goals reported next to the main one"},"variants":{"type":"array","items":{"type":"object"},"description":"The pages compared, each { id, name, path, weight, control }. The original page comes first"},"allocation":{"type":"string","description":"manual keeps the shares as set, auto moves visitors toward the leading variant"},"traffic_share":{"type":"integer","description":"Percent of the page's visitors who take part"},"min_days":{"type":"integer","description":"Shortest duration in days"},"max_days":{"type":"integer","description":"Longest duration in days"},"min_sample":{"type":"integer","description":"Visits each variant needs before a winner can be called"},"confidence":{"type":"integer","description":"Confidence a variant must reach to win: 90, 95 or 99"},"send_to_winner":{"type":"boolean","description":"Whether every visitor is sent to the winner after the experiment ends"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices that take part. Empty means all"},"countries":{"type":"array","items":{"type":"string"},"description":"Country codes that take part. Empty means all"},"channels":{"type":"array","items":{"type":"string"},"description":"Channels that take part. Empty means all"},"exclusive_group":{"anyOf":[{"type":"string","description":"Experiments with the same group never share a visitor"},{"type":"null"}]},"starts_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled experiment starts by itself"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time","description":"When visitors first took part"},{"type":"null"}]},"ended_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it ended"},{"type":"null"}]},"end_reason":{"anyOf":[{"type":"string","description":"winner, no_winner or manual"},{"type":"null"}]},"winner_id":{"anyOf":[{"type":"string","description":"The winning variant (var_...), if there is one"},{"type":"null"}]},"locked":{"type":"boolean","description":"True when the workspace's plan no longer covers this experiment. It redirects nobody until the plan does"},"stats":{"anyOf":[{"type":"object","properties":{"visits":{"type":"integer","description":"Visits that saw any page of the experiment"},"conversions":{"type":"integer","description":"Of those, the visits that reached the goal afterwards"},"conversion_rate":{"type":"number","description":"conversions divided by visits, as a percent from 0 to 100"}},"description":"On experiments_list only: visits, conversions and conversion_rate across all variants. null until the experiment has started"},{"type":"null"}]},"results":{"anyOf":[{"type":"object","description":"On experiments_get only. goal, confidence, progress (days_running, sample_reached, ready, days_left), mismatch (whether visits are shared out as the weights say), leader_id, winner_id, decided, and variants: each with visits, conversions, conversion_rate (percent), and against the original uplift (percent), interval (low and high of the difference, in percentage points), p_value, significant and chance (percent chance that it beats the original), plus revenue and revenue_per_visit in minor units and the secondary goals. split holds the breakdown when one was asked for. timeline holds the experiment day by day in the site timezone: dates, for each variant its visits and conversions per day and its conversion_rate (percent) of everything up to that day, and events (started, paused, resumed, ended, each with at and date)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"experiments_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New internal name, max 120 characters","examples":["Shorter pricing page"]},"path":{"type":"string","description":"The original page, as a path of the site that starts with a slash, such as /pricing. No address and no query string. One * stands for a part of the path (Pro and up), and every variant then needs one too","examples":["/pricing"]},"goal_id":{"type":"string","description":"Active goal (goal_..., from goals_list) the result is decided on","examples":["goal_7Q2K9XH3AB"]},"variants":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"The complete new list, replacing the current one: for an ad experiment { creative_id, weight }, for a page test { name, path, weight }. The first row is the original page and its path is ignored. Each other path is a page of the same site, such as /pricing-b. weight is a percent, and the weights add up to 100. Leave every weight out for an even split"},"secondary_goal_ids":{"type":"array","items":{"type":"string"},"description":"More goals (goal_...) reported next to the main one. They never end the experiment. Pro and up"},"allocation":{"type":"string","description":"manual (default) keeps the shares you set. auto moves visitors toward the leading variant once a day (Pro and up)","enum":["manual","auto"]},"traffic_share":{"type":"integer","description":"Percent of the page's visitors who take part at all, from 1 to 100. Default 100. The rest see the original page and are not counted"},"min_days":{"type":"integer","description":"Shortest duration in days, from 1 to 90. Default 7. No winner is called before it"},"max_days":{"type":"integer","description":"Longest duration in days, from 1 to 90, the same as min_days or more. Default 30. The experiment ends then, with or without a winner"},"min_sample":{"type":"integer","description":"Visits each variant needs before a winner can be called. Default 100"},"confidence":{"type":"integer","description":"Confidence a variant must reach against the original to win: 90, 95 (default) or 99","enum":[90,95,99]},"send_to_winner":{"type":"boolean","description":"After a winner is found, send every visitor of the original page to it until you turn this off. Default true"},"devices":{"type":"array","items":{"type":"string","enum":["desktop","mobile","tablet"]},"description":"Only visitors on these devices take part. Empty list means all. Pro and up"},"countries":{"type":"array","items":{"type":"string"},"description":"Only visitors from these two-letter country codes take part, such as [\"US\",\"CA\"]. Empty list means all. Pro and up"},"channels":{"type":"array","items":{"type":"string"},"description":"Only visits from these channels take part. Empty list means all. Pro and up"},"exclusive_group":{"type":"string","description":"A name shared by experiments that must not overlap: a visitor takes part in one experiment of a group at most. Pro and up"},"starts_at":{"type":"string","format":"date-time","description":"When to start by itself, ISO 8601. The experiment waits as scheduled once a person has started it. Pro and up"},"paths":{"type":"array","items":{"type":"string"},"description":"For an ad experiment: only on these pages of the site. Empty list means all. Pro and up"}}}}}}}},"/sites/{site_id}/experiments/{id}/duplicate.json":{"post":{"operationId":"experiments_duplicate","summary":"Copy an experiment as a new draft","description":"Creates a draft with the same pages, shares, goal and rules as an existing experiment and none of its results. Use it to change a test that has already started. Counts toward the plan limit like a new experiment. Requires content.write. Returns the new experiment.","tags":["Experiments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by experiments_list","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, scheduled, running, paused or ended"},"kind":{"type":"string","description":"page (an A/B or split URL test) or ad (a test of the creatives of an ad placement)"},"path":{"anyOf":[{"type":"string","description":"The original page being tested. null in an ad experiment"},{"type":"null"}]},"placement_id":{"anyOf":[{"type":"string","description":"The ad placement (adp_...) whose creatives are compared. null in a page test"},{"type":"null"}]},"paths":{"type":"array","items":{"type":"string"},"description":"The pages of the site an ad experiment is limited to. Empty means all"},"goal_id":{"anyOf":[{"type":"string","description":"The goal the result is decided on. null when that goal was deleted"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of that goal. null without one"},{"type":"null"}]},"secondary_goal_ids":{"type":"array","items":{"type":"string"},"description":"Goals reported next to the main one"},"variants":{"type":"array","items":{"type":"object"},"description":"The pages compared, each { id, name, path, weight, control }. The original page comes first"},"allocation":{"type":"string","description":"manual keeps the shares as set, auto moves visitors toward the leading variant"},"traffic_share":{"type":"integer","description":"Percent of the page's visitors who take part"},"min_days":{"type":"integer","description":"Shortest duration in days"},"max_days":{"type":"integer","description":"Longest duration in days"},"min_sample":{"type":"integer","description":"Visits each variant needs before a winner can be called"},"confidence":{"type":"integer","description":"Confidence a variant must reach to win: 90, 95 or 99"},"send_to_winner":{"type":"boolean","description":"Whether every visitor is sent to the winner after the experiment ends"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices that take part. Empty means all"},"countries":{"type":"array","items":{"type":"string"},"description":"Country codes that take part. Empty means all"},"channels":{"type":"array","items":{"type":"string"},"description":"Channels that take part. Empty means all"},"exclusive_group":{"anyOf":[{"type":"string","description":"Experiments with the same group never share a visitor"},{"type":"null"}]},"starts_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled experiment starts by itself"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time","description":"When visitors first took part"},{"type":"null"}]},"ended_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it ended"},{"type":"null"}]},"end_reason":{"anyOf":[{"type":"string","description":"winner, no_winner or manual"},{"type":"null"}]},"winner_id":{"anyOf":[{"type":"string","description":"The winning variant (var_...), if there is one"},{"type":"null"}]},"locked":{"type":"boolean","description":"True when the workspace's plan no longer covers this experiment. It redirects nobody until the plan does"},"stats":{"anyOf":[{"type":"object","properties":{"visits":{"type":"integer","description":"Visits that saw any page of the experiment"},"conversions":{"type":"integer","description":"Of those, the visits that reached the goal afterwards"},"conversion_rate":{"type":"number","description":"conversions divided by visits, as a percent from 0 to 100"}},"description":"On experiments_list only: visits, conversions and conversion_rate across all variants. null until the experiment has started"},{"type":"null"}]},"results":{"anyOf":[{"type":"object","description":"On experiments_get only. goal, confidence, progress (days_running, sample_reached, ready, days_left), mismatch (whether visits are shared out as the weights say), leader_id, winner_id, decided, and variants: each with visits, conversions, conversion_rate (percent), and against the original uplift (percent), interval (low and high of the difference, in percentage points), p_value, significant and chance (percent chance that it beats the original), plus revenue and revenue_per_visit in minor units and the secondary goals. split holds the breakdown when one was asked for. timeline holds the experiment day by day in the site timezone: dates, for each variant its visits and conversions per day and its conversion_rate (percent) of everything up to that day, and events (started, paused, resumed, ended, each with at and date)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"experiments_duplicate","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/experiments/{id}/end.json":{"post":{"operationId":"experiments_end","summary":"End an experiment for good","description":"Ends a running or paused experiment. It cannot be started again, its results are kept and it no longer counts toward the plan limit. The MCP tool does not run it and responds with human_only and the page where a person ends it. The API runs it. Requires content.write.","tags":["Experiments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by experiments_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, scheduled, running, paused or ended"},"kind":{"type":"string","description":"page (an A/B or split URL test) or ad (a test of the creatives of an ad placement)"},"path":{"anyOf":[{"type":"string","description":"The original page being tested. null in an ad experiment"},{"type":"null"}]},"placement_id":{"anyOf":[{"type":"string","description":"The ad placement (adp_...) whose creatives are compared. null in a page test"},{"type":"null"}]},"paths":{"type":"array","items":{"type":"string"},"description":"The pages of the site an ad experiment is limited to. Empty means all"},"goal_id":{"anyOf":[{"type":"string","description":"The goal the result is decided on. null when that goal was deleted"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of that goal. null without one"},{"type":"null"}]},"secondary_goal_ids":{"type":"array","items":{"type":"string"},"description":"Goals reported next to the main one"},"variants":{"type":"array","items":{"type":"object"},"description":"The pages compared, each { id, name, path, weight, control }. The original page comes first"},"allocation":{"type":"string","description":"manual keeps the shares as set, auto moves visitors toward the leading variant"},"traffic_share":{"type":"integer","description":"Percent of the page's visitors who take part"},"min_days":{"type":"integer","description":"Shortest duration in days"},"max_days":{"type":"integer","description":"Longest duration in days"},"min_sample":{"type":"integer","description":"Visits each variant needs before a winner can be called"},"confidence":{"type":"integer","description":"Confidence a variant must reach to win: 90, 95 or 99"},"send_to_winner":{"type":"boolean","description":"Whether every visitor is sent to the winner after the experiment ends"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices that take part. Empty means all"},"countries":{"type":"array","items":{"type":"string"},"description":"Country codes that take part. Empty means all"},"channels":{"type":"array","items":{"type":"string"},"description":"Channels that take part. Empty means all"},"exclusive_group":{"anyOf":[{"type":"string","description":"Experiments with the same group never share a visitor"},{"type":"null"}]},"starts_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled experiment starts by itself"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time","description":"When visitors first took part"},{"type":"null"}]},"ended_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it ended"},{"type":"null"}]},"end_reason":{"anyOf":[{"type":"string","description":"winner, no_winner or manual"},{"type":"null"}]},"winner_id":{"anyOf":[{"type":"string","description":"The winning variant (var_...), if there is one"},{"type":"null"}]},"locked":{"type":"boolean","description":"True when the workspace's plan no longer covers this experiment. It redirects nobody until the plan does"},"stats":{"anyOf":[{"type":"object","properties":{"visits":{"type":"integer","description":"Visits that saw any page of the experiment"},"conversions":{"type":"integer","description":"Of those, the visits that reached the goal afterwards"},"conversion_rate":{"type":"number","description":"conversions divided by visits, as a percent from 0 to 100"}},"description":"On experiments_list only: visits, conversions and conversion_rate across all variants. null until the experiment has started"},{"type":"null"}]},"results":{"anyOf":[{"type":"object","description":"On experiments_get only. goal, confidence, progress (days_running, sample_reached, ready, days_left), mismatch (whether visits are shared out as the weights say), leader_id, winner_id, decided, and variants: each with visits, conversions, conversion_rate (percent), and against the original uplift (percent), interval (low and high of the difference, in percentage points), p_value, significant and chance (percent chance that it beats the original), plus revenue and revenue_per_visit in minor units and the secondary goals. split holds the breakdown when one was asked for. timeline holds the experiment day by day in the site timezone: dates, for each variant its visits and conversions per day and its conversion_rate (percent) of everything up to that day, and events (started, paused, resumed, ended, each with at and date)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/experiments/{id}/pause.json":{"post":{"operationId":"experiments_pause","summary":"Pause an experiment and keep its results","description":"Pauses a running or scheduled experiment. Every visitor gets the original page again at once and the results so far are kept. experiments_start resumes it. Requires content.write. Returns the experiment.","tags":["Experiments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by experiments_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, scheduled, running, paused or ended"},"kind":{"type":"string","description":"page (an A/B or split URL test) or ad (a test of the creatives of an ad placement)"},"path":{"anyOf":[{"type":"string","description":"The original page being tested. null in an ad experiment"},{"type":"null"}]},"placement_id":{"anyOf":[{"type":"string","description":"The ad placement (adp_...) whose creatives are compared. null in a page test"},{"type":"null"}]},"paths":{"type":"array","items":{"type":"string"},"description":"The pages of the site an ad experiment is limited to. Empty means all"},"goal_id":{"anyOf":[{"type":"string","description":"The goal the result is decided on. null when that goal was deleted"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of that goal. null without one"},{"type":"null"}]},"secondary_goal_ids":{"type":"array","items":{"type":"string"},"description":"Goals reported next to the main one"},"variants":{"type":"array","items":{"type":"object"},"description":"The pages compared, each { id, name, path, weight, control }. The original page comes first"},"allocation":{"type":"string","description":"manual keeps the shares as set, auto moves visitors toward the leading variant"},"traffic_share":{"type":"integer","description":"Percent of the page's visitors who take part"},"min_days":{"type":"integer","description":"Shortest duration in days"},"max_days":{"type":"integer","description":"Longest duration in days"},"min_sample":{"type":"integer","description":"Visits each variant needs before a winner can be called"},"confidence":{"type":"integer","description":"Confidence a variant must reach to win: 90, 95 or 99"},"send_to_winner":{"type":"boolean","description":"Whether every visitor is sent to the winner after the experiment ends"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices that take part. Empty means all"},"countries":{"type":"array","items":{"type":"string"},"description":"Country codes that take part. Empty means all"},"channels":{"type":"array","items":{"type":"string"},"description":"Channels that take part. Empty means all"},"exclusive_group":{"anyOf":[{"type":"string","description":"Experiments with the same group never share a visitor"},{"type":"null"}]},"starts_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled experiment starts by itself"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time","description":"When visitors first took part"},{"type":"null"}]},"ended_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it ended"},{"type":"null"}]},"end_reason":{"anyOf":[{"type":"string","description":"winner, no_winner or manual"},{"type":"null"}]},"winner_id":{"anyOf":[{"type":"string","description":"The winning variant (var_...), if there is one"},{"type":"null"}]},"locked":{"type":"boolean","description":"True when the workspace's plan no longer covers this experiment. It redirects nobody until the plan does"},"stats":{"anyOf":[{"type":"object","properties":{"visits":{"type":"integer","description":"Visits that saw any page of the experiment"},"conversions":{"type":"integer","description":"Of those, the visits that reached the goal afterwards"},"conversion_rate":{"type":"number","description":"conversions divided by visits, as a percent from 0 to 100"}},"description":"On experiments_list only: visits, conversions and conversion_rate across all variants. null until the experiment has started"},{"type":"null"}]},"results":{"anyOf":[{"type":"object","description":"On experiments_get only. goal, confidence, progress (days_running, sample_reached, ready, days_left), mismatch (whether visits are shared out as the weights say), leader_id, winner_id, decided, and variants: each with visits, conversions, conversion_rate (percent), and against the original uplift (percent), interval (low and high of the difference, in percentage points), p_value, significant and chance (percent chance that it beats the original), plus revenue and revenue_per_visit in minor units and the secondary goals. split holds the breakdown when one was asked for. timeline holds the experiment day by day in the site timezone: dates, for each variant its visits and conversions per day and its conversion_rate (percent) of everything up to that day, and events (started, paused, resumed, ended, each with at and date)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"experiments_pause","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/experiments/{id}/start.json":{"post":{"operationId":"experiments_start","summary":"Start an experiment","description":"Starts a draft or paused experiment, so visitors of the original page begin to be sent to the variants. With starts_at in the future it waits for that time. Because it redirects real visitors, the MCP tool does not run it and responds with human_only and the page where a person starts it. The API runs it. Requires content.write.","tags":["Experiments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by experiments_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, scheduled, running, paused or ended"},"kind":{"type":"string","description":"page (an A/B or split URL test) or ad (a test of the creatives of an ad placement)"},"path":{"anyOf":[{"type":"string","description":"The original page being tested. null in an ad experiment"},{"type":"null"}]},"placement_id":{"anyOf":[{"type":"string","description":"The ad placement (adp_...) whose creatives are compared. null in a page test"},{"type":"null"}]},"paths":{"type":"array","items":{"type":"string"},"description":"The pages of the site an ad experiment is limited to. Empty means all"},"goal_id":{"anyOf":[{"type":"string","description":"The goal the result is decided on. null when that goal was deleted"},{"type":"null"}]},"goal_name":{"anyOf":[{"type":"string","description":"The name of that goal. null without one"},{"type":"null"}]},"secondary_goal_ids":{"type":"array","items":{"type":"string"},"description":"Goals reported next to the main one"},"variants":{"type":"array","items":{"type":"object"},"description":"The pages compared, each { id, name, path, weight, control }. The original page comes first"},"allocation":{"type":"string","description":"manual keeps the shares as set, auto moves visitors toward the leading variant"},"traffic_share":{"type":"integer","description":"Percent of the page's visitors who take part"},"min_days":{"type":"integer","description":"Shortest duration in days"},"max_days":{"type":"integer","description":"Longest duration in days"},"min_sample":{"type":"integer","description":"Visits each variant needs before a winner can be called"},"confidence":{"type":"integer","description":"Confidence a variant must reach to win: 90, 95 or 99"},"send_to_winner":{"type":"boolean","description":"Whether every visitor is sent to the winner after the experiment ends"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices that take part. Empty means all"},"countries":{"type":"array","items":{"type":"string"},"description":"Country codes that take part. Empty means all"},"channels":{"type":"array","items":{"type":"string"},"description":"Channels that take part. Empty means all"},"exclusive_group":{"anyOf":[{"type":"string","description":"Experiments with the same group never share a visitor"},{"type":"null"}]},"starts_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled experiment starts by itself"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time","description":"When visitors first took part"},{"type":"null"}]},"ended_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it ended"},{"type":"null"}]},"end_reason":{"anyOf":[{"type":"string","description":"winner, no_winner or manual"},{"type":"null"}]},"winner_id":{"anyOf":[{"type":"string","description":"The winning variant (var_...), if there is one"},{"type":"null"}]},"locked":{"type":"boolean","description":"True when the workspace's plan no longer covers this experiment. It redirects nobody until the plan does"},"stats":{"anyOf":[{"type":"object","properties":{"visits":{"type":"integer","description":"Visits that saw any page of the experiment"},"conversions":{"type":"integer","description":"Of those, the visits that reached the goal afterwards"},"conversion_rate":{"type":"number","description":"conversions divided by visits, as a percent from 0 to 100"}},"description":"On experiments_list only: visits, conversions and conversion_rate across all variants. null until the experiment has started"},{"type":"null"}]},"results":{"anyOf":[{"type":"object","description":"On experiments_get only. goal, confidence, progress (days_running, sample_reached, ready, days_left), mismatch (whether visits are shared out as the weights say), leader_id, winner_id, decided, and variants: each with visits, conversions, conversion_rate (percent), and against the original uplift (percent), interval (low and high of the difference, in percentage points), p_value, significant and chance (percent chance that it beats the original), plus revenue and revenue_per_visit in minor units and the secondary goals. split holds the breakdown when one was asked for. timeline holds the experiment day by day in the site timezone: dates, for each variant its visits and conversions per day and its conversion_rate (percent) of everything up to that day, and events (started, paused, resumed, ended, each with at and date)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/workspaces/{workspace_id}/exports.json":{"post":{"operationId":"exports_create","summary":"Queue an export (built in the background)","description":"Queues a data export that is built in the background and returns it right away with status queued. Choose it when you need a file (CSV, JSON, XLSX, NDJSON or a ZIP of dashboard panels), and use exports_preview first to check columns and size without creating anything. For lightweight numbers use the stats tools instead. Required inputs are workspace_id (path), site_id, from and to (YYYY-MM-DD, inclusive, in the export timezone). The kind decides what is exported and which options apply. aggregated (default) gives visit metrics per time bucket and uses grouping, dimensions (up to 6), metrics, filters and segment_id. pageviews, events and raw give one row per hit and use fields, filters and segment_id, require the Pro plan or above, and are limited to 400 days (raw to 93 days). imported gives imported daily stats and uses only dimensions. dashboard gives a ZIP of the overview panels (format zip only). Allowed file_format per kind is csv, json or xlsx for aggregated, pageviews, events and imported, csv or ndjson for raw, and zip for dashboard. Options that do not apply to the chosen kind are ignored. A workspace can have at most 5 exports queued or running at once. The response is the export with id (exp_...), status, row_count and expires_at (null until built). Poll exports_get until status is complete, then call exports_download. The requesting user gets an email when it is ready, a webhook export.ready is sent, and the action is written to the audit log. Event properties in the props column only include properties marked as safe to export (see event_properties_list).","tags":["Exports"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Export id, e.g. exp_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site exported (pa_…)"},{"type":"null"}]},"kind":{"type":"string","description":"aggregated, pageviews, events, imported, raw or dashboard"},"format":{"type":"string","description":"csv, json, xlsx, ndjson or zip"},"status":{"type":"string","description":"queued, running, complete, failed or expired"},"params":{"type":"object","description":"The export definition (dates, timezone, grouping, dimensions, metrics, fields, filters)"},"row_count":{"anyOf":[{"type":"integer","description":"Rows written"},{"type":"null"}]},"error":{"anyOf":[{"type":"string","description":"Why the export failed"},{"type":"null"}]},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the file is deleted"},{"type":"null"}]},"download_url":{"anyOf":[{"type":"string","description":"Path returning a short-lived signed file link (exports_download)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"exports_create","x-permission":"analytics.export","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"site_id":{"type":"string","description":"Id of the site to export, like pa_7Q2K9XH3AB (from sites_list). Required","examples":["pa_7Q2K9XH3AB"]},"kind":{"type":"string","description":"What to export. aggregated (default) is visit metrics per time bucket and dimension. pageviews, events and raw are one row per hit (pageviews only, custom events only, every hit) and need the Pro plan or above. imported is imported daily stats. dashboard is a ZIP of the overview panels","enum":["aggregated","pageviews","events","imported","raw","dashboard"],"default":"aggregated"},"file_format":{"type":"string","description":"File type, default csv. Allowed per kind: csv, json or xlsx for aggregated, pageviews, events and imported. csv or ndjson for raw. zip for dashboard","enum":["csv","json","xlsx","ndjson","zip"],"default":"csv"},"from":{"type":"string","format":"date","description":"First day to include, YYYY-MM-DD, in the export timezone. Required","examples":["2026-09-01"]},"to":{"type":"string","format":"date","description":"Last day to include (inclusive), YYYY-MM-DD, on or after from. Required. At most 400 days from from (93 days for raw)","examples":["2026-09-28"]},"timezone":{"type":"string","description":"IANA timezone name used for dates and time buckets, like America/New_York. Default is the site timezone"},"grouping":{"type":"string","description":"Time bucket for aggregated exports (also used by dashboard): hour, day (default), week, month, quarter or year","enum":["hour","day","week","month","quarter","year"],"default":"day"},"dimensions":{"type":"array","items":{"type":"string"},"description":"Up to 6 names to group by. For aggregated: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page or interaction. For imported: total, page, source, country, device, browser or os. Ignored for other kinds","default":[]},"metrics":{"type":"array","items":{"type":"string","enum":["visitors","visits","pageviews","bounce_rate","visit_duration","views_per_visit","revenue"]},"description":"Metric columns for aggregated exports. Empty means all of them","default":[]},"fields":{"type":"array","items":{"type":"string","enum":["occurred_at","kind","name","visit_id","hostname","path","referrer_host","referrer_path","channel","utm_source","utm_medium","utm_campaign","utm_content","utm_term","ref","paid_click","country","language","device","browser","browser_major","os","os_major","screen_bucket","engaged_ms","scroll_depth","revenue_minor","currency","vital_value","selector","props"]},"description":"Columns for pageviews, events and raw exports. Empty means all except visit_id, vital_value and selector. props only includes event properties marked safe to export. revenue_minor is in minor currency units. Ignored for other kinds","default":[]},"filters":{"type":"array","items":{},"description":"List of filters, each a three item array [dimension, operator, value] like [[\"country\",\"is\",\"US\"]], same format as the stats tools. Applies to aggregated, pageviews, events, raw and dashboard. Empty means no filter","default":[]},"segment_id":{"type":"string","description":"Id of a saved segment, like seg_..., from segments_list. Its filters are added to filters. Must be shared or your own. Ignored for imported"}},"required":["site_id","from","to"]}}}}},"get":{"operationId":"exports_list","summary":"List exports (the job queue)","description":"Lists the exports of a workspace for the sites you can access, newest first. Use it to find an export id, check which exports are still running or to see what has expired. Filter with site_id, status (queued, running, complete, failed or expired) and kind (aggregated, pageviews, events, imported, raw or dashboard). Paginated with page and per_page (up to 100), and returns data (a list of exports, see exports_get for the fields) plus pagination meta. Needs the workspace_id from workspaces_list.","tags":["Exports"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"site_id","in":"query","required":false,"schema":{"type":"string","description":"Only exports of this site (pa_…)"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Only exports with this status","enum":["queued","running","complete","failed","expired"]}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","description":"Only exports of this kind","enum":["aggregated","pageviews","events","imported","raw","dashboard","testimonials","testimonial_stats","testimonial_images"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Export id, e.g. exp_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site exported (pa_…)"},{"type":"null"}]},"kind":{"type":"string","description":"aggregated, pageviews, events, imported, raw or dashboard"},"format":{"type":"string","description":"csv, json, xlsx, ndjson or zip"},"status":{"type":"string","description":"queued, running, complete, failed or expired"},"params":{"type":"object","description":"The export definition (dates, timezone, grouping, dimensions, metrics, fields, filters)"},"row_count":{"anyOf":[{"type":"integer","description":"Rows written"},{"type":"null"}]},"error":{"anyOf":[{"type":"string","description":"Why the export failed"},{"type":"null"}]},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the file is deleted"},{"type":"null"}]},"download_url":{"anyOf":[{"type":"string","description":"Path returning a short-lived signed file link (exports_download)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"exports_list","x-permission":"analytics.export"}},"/exports/{id}.json":{"delete":{"operationId":"exports_delete","summary":"Delete an export and its file","description":"Permanently deletes an export and its generated file. The download link stops working at once and this cannot be undone, but you can create the export again. Use it to remove a finished or failed export you no longer need, since files are also deleted automatically 7 days after they are built. The id comes from exports_list. Returns the deleted export object as it was before deletion.","tags":["Exports"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by exports_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Export id, e.g. exp_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site exported (pa_…)"},{"type":"null"}]},"kind":{"type":"string","description":"aggregated, pageviews, events, imported, raw or dashboard"},"format":{"type":"string","description":"csv, json, xlsx, ndjson or zip"},"status":{"type":"string","description":"queued, running, complete, failed or expired"},"params":{"type":"object","description":"The export definition (dates, timezone, grouping, dimensions, metrics, fields, filters)"},"row_count":{"anyOf":[{"type":"integer","description":"Rows written"},{"type":"null"}]},"error":{"anyOf":[{"type":"string","description":"Why the export failed"},{"type":"null"}]},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the file is deleted"},{"type":"null"}]},"download_url":{"anyOf":[{"type":"string","description":"Path returning a short-lived signed file link (exports_download)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"analytics.export","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"exports_get","summary":"Get an export and its status","description":"Returns one export, including its progress. Use it to poll an export started with exports_create until status is complete or failed. Statuses are queued, running, complete, failed and expired. Fields include id (exp_...), site_id (pa_...), kind, format, status, params (the stored definition of the export), row_count (null until complete), error (set when failed), completed_at, expires_at (files are kept 7 days after completion), download_url (set only while the file can be downloaded, use exports_download to get a signed link) and created_at. The id comes from exports_create or exports_list.","tags":["Exports"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by exports_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Export id, e.g. exp_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site exported (pa_…)"},{"type":"null"}]},"kind":{"type":"string","description":"aggregated, pageviews, events, imported, raw or dashboard"},"format":{"type":"string","description":"csv, json, xlsx, ndjson or zip"},"status":{"type":"string","description":"queued, running, complete, failed or expired"},"params":{"type":"object","description":"The export definition (dates, timezone, grouping, dimensions, metrics, fields, filters)"},"row_count":{"anyOf":[{"type":"integer","description":"Rows written"},{"type":"null"}]},"error":{"anyOf":[{"type":"string","description":"Why the export failed"},{"type":"null"}]},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the file is deleted"},{"type":"null"}]},"download_url":{"anyOf":[{"type":"string","description":"Path returning a short-lived signed file link (exports_download)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"exports_get","x-permission":"analytics.export"}},"/exports/{id}/download.json":{"get":{"operationId":"exports_download","summary":"Get a signed link to the file (valid 10 minutes)","description":"Returns a short-lived download link for a finished export. Choose it after exports_get shows status complete. The response has url (a signed link that is valid for 10 minutes, fetch it right away), expires_at (when the link stops working, ISO 8601), filename and byte_size (bytes). It fails with a not found error code expired when the export is older than 7 days, and with a validation error when the export is still queued or running or when it failed (the error message says why). Call it again to get a fresh link as long as the export itself has not expired. The id comes from exports_list.","tags":["Exports"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by exports_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"exports_download","x-permission":"analytics.export"}},"/workspaces/{workspace_id}/exports/preview.json":{"post":{"operationId":"exports_preview","summary":"Preview an export: first 20 rows and the estimated row count","description":"Dry run of an export that creates nothing. It takes the same inputs as exports_create and returns kind, file_format, columns (the column names in order), rows (up to 20 sample rows as objects keyed by column) and estimated_rows (an approximate row count of the full file). For the dashboard kind the sample rows list each file name with its row count. Use it to validate dimensions, fields, filters and the date range, and to see how large the export would be before calling exports_create. It runs synchronously, so keep the date range reasonable. Validation errors are the same as for exports_create, including the Pro plan requirement for row level kinds. Nothing is stored and no email is sent.","tags":["Exports"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"exports_preview","x-permission":"analytics.export","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"site_id":{"type":"string","description":"Id of the site to export, like pa_7Q2K9XH3AB (from sites_list). Required","examples":["pa_7Q2K9XH3AB"]},"kind":{"type":"string","description":"What to export. aggregated (default) is visit metrics per time bucket and dimension. pageviews, events and raw are one row per hit (pageviews only, custom events only, every hit) and need the Pro plan or above. imported is imported daily stats. dashboard is a ZIP of the overview panels","enum":["aggregated","pageviews","events","imported","raw","dashboard"],"default":"aggregated"},"file_format":{"type":"string","description":"File type, default csv. Allowed per kind: csv, json or xlsx for aggregated, pageviews, events and imported. csv or ndjson for raw. zip for dashboard","enum":["csv","json","xlsx","ndjson","zip"],"default":"csv"},"from":{"type":"string","format":"date","description":"First day to include, YYYY-MM-DD, in the export timezone. Required","examples":["2026-09-01"]},"to":{"type":"string","format":"date","description":"Last day to include (inclusive), YYYY-MM-DD, on or after from. Required. At most 400 days from from (93 days for raw)","examples":["2026-09-28"]},"timezone":{"type":"string","description":"IANA timezone name used for dates and time buckets, like America/New_York. Default is the site timezone"},"grouping":{"type":"string","description":"Time bucket for aggregated exports (also used by dashboard): hour, day (default), week, month, quarter or year","enum":["hour","day","week","month","quarter","year"],"default":"day"},"dimensions":{"type":"array","items":{"type":"string"},"description":"Up to 6 names to group by. For aggregated: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page or interaction. For imported: total, page, source, country, device, browser or os. Ignored for other kinds","default":[]},"metrics":{"type":"array","items":{"type":"string","enum":["visitors","visits","pageviews","bounce_rate","visit_duration","views_per_visit","revenue"]},"description":"Metric columns for aggregated exports. Empty means all of them","default":[]},"fields":{"type":"array","items":{"type":"string","enum":["occurred_at","kind","name","visit_id","hostname","path","referrer_host","referrer_path","channel","utm_source","utm_medium","utm_campaign","utm_content","utm_term","ref","paid_click","country","language","device","browser","browser_major","os","os_major","screen_bucket","engaged_ms","scroll_depth","revenue_minor","currency","vital_value","selector","props"]},"description":"Columns for pageviews, events and raw exports. Empty means all except visit_id, vital_value and selector. props only includes event properties marked safe to export. revenue_minor is in minor currency units. Ignored for other kinds","default":[]},"filters":{"type":"array","items":{},"description":"List of filters, each a three item array [dimension, operator, value] like [[\"country\",\"is\",\"US\"]], same format as the stats tools. Applies to aggregated, pageviews, events, raw and dashboard. Empty means no filter","default":[]},"segment_id":{"type":"string","description":"Id of a saved segment, like seg_..., from segments_list. Its filters are added to filters. Must be shared or your own. Ignored for imported"}},"required":["site_id","from","to"]}}}}}},"/sites/{site_id}/testimonials/forms.json":{"post":{"operationId":"testimonial_forms_create","summary":"Create a form","description":"One call carries the whole form: steps, questions, skip logic, consent wording and language. Anything left out starts from a sensible default in the form's language, and the slug comes from the name. The link is https://privatus.page/f/<slug>. Low-rating routing and custom CSS need the Business plan (402 plan_limit without). Video and audio answers are offered to the giver on Pro and up.","tags":["Forms"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Form id, e.g. frm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"slug":{"type":"string","description":"The last part of the link"},"url":{"type":"string","description":"The link to send to customers"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the form's public page is closed (410)"},"language":{"type":"string","description":"Language code of the form's own text"},"kinds":{"type":"array","items":{"type":"string"},"description":"The kinds of answer accepted: text, video, audio. Video and audio are offered on Pro and up"},"version":{"type":"integer","description":"Goes up when a step, a question or the consent wording changes. Stored on every consent record"},"starter":{"type":"boolean","description":"true for the form a new site starts with"},"welcome_enabled":{"type":"boolean","description":"Whether the welcome step is shown"},"rating_enabled":{"type":"boolean","description":"Whether the form asks for a rating"},"rating_required":{"type":"boolean","description":"Whether a rating must be given"},"low_rating_routing":{"type":"boolean","description":"Whether a rating of 1 to 3 goes to private feedback. Paused on a plan without it"},"thanks_redirect":{"type":"boolean","description":"Whether the giver is sent on after 5 seconds"},"share_prompt":{"type":"boolean","description":"Whether the giver is offered to share their words"},"show_logo":{"type":"boolean","description":"Whether the brand kit logo is shown"},"show_progress":{"type":"boolean","description":"Whether progress is shown"},"turnstile":{"type":"boolean","description":"Whether the giver is checked to be a person"},"show_badge":{"anyOf":[{"type":"boolean","description":"The badge switch, or null to follow the brand kit"},{"type":"null"}]},"welcome_title":{"anyOf":[{"type":"string","description":"Title of the welcome step"},{"type":"null"}]},"welcome_message":{"anyOf":[{"type":"string","description":"Message of the welcome step"},{"type":"null"}]},"welcome_button":{"anyOf":[{"type":"string","description":"Button of the welcome step"},{"type":"null"}]},"rating_title":{"anyOf":[{"type":"string","description":"Title of the rating step"},{"type":"null"}]},"feedback_title":{"anyOf":[{"type":"string","description":"Title of the private feedback step"},{"type":"null"}]},"feedback_message":{"anyOf":[{"type":"string","description":"Message of the private feedback step"},{"type":"null"}]},"feedback_thanks":{"anyOf":[{"type":"string","description":"Closing line after private feedback"},{"type":"null"}]},"about_title":{"anyOf":[{"type":"string","description":"Title of the About you step"},{"type":"null"}]},"about_message":{"anyOf":[{"type":"string","description":"Message of the About you step"},{"type":"null"}]},"consent_title":{"anyOf":[{"type":"string","description":"Title of the consent step"},{"type":"null"}]},"consent_text":{"anyOf":[{"type":"string","description":"The consent text, stored word for word on consent records"},{"type":"null"}]},"consent_single_label":{"anyOf":[{"type":"string","description":"The checkbox wording in single mode"},{"type":"null"}]},"thanks_title":{"anyOf":[{"type":"string","description":"Title of the thank-you step"},{"type":"null"}]},"thanks_message":{"anyOf":[{"type":"string","description":"Message of the thank-you step"},{"type":"null"}]},"thanks_button_label":{"anyOf":[{"type":"string","description":"Label of the optional button"},{"type":"null"}]},"thanks_button_url":{"anyOf":[{"type":"string","description":"Where the optional button goes"},{"type":"null"}]},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, or null to follow the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or null to follow the brand kit"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"The form's custom CSS"},{"type":"null"}]},"rating_style":{"type":"string","description":"inherit, stars or hearts"},"theme":{"type":"string","description":"auto, light or dark"},"field_name":{"type":"string","description":"required or optional"},"consent_mode":{"type":"string","description":"single or separate"},"field_email":{"type":"string","description":"off, optional or required"},"field_photo":{"type":"string","description":"off, optional or required"},"field_title":{"type":"string","description":"off, optional or required"},"field_company":{"type":"string","description":"off, optional or required"},"field_company_url":{"type":"string","description":"off, optional or required"},"field_social_url":{"type":"string","description":"off, optional or required"},"consent_show_name":{"type":"string","description":"required, optional or off"},"consent_show_photo":{"type":"string","description":"required, optional or off"},"consent_show_video":{"type":"string","description":"required, optional or off"},"consent_marketing":{"type":"string","description":"required or optional"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions in order, with their skip logic"},"consent_labels":{"type":"object","description":"The checkbox wording per permission"},"url_parameters":{"type":"array","items":{"type":"object"},"description":"The URL parameters saved to custom properties"},"reward":{"anyOf":[{"type":"object","description":"The form's reward, or null"},{"type":"null"}]},"submissions_count":{"type":"integer","description":"Completed submissions, private feedback included"},"last_submission_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the form was last completed"},{"type":"null"}]},"trashed":{"type":"boolean","description":"true while it is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_forms_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","description":"The link is /f/<slug>. 3 to 60 characters: a to z, 0 to 9 and hyphens. Unique across Privatus Analytics. The default comes from the name"},"language":{"type":"string","description":"One of the site's languages. Sets the form's own buttons, errors and recorder text","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]},"kinds":{"type":"array","items":{"type":"string","enum":["text","video","audio"]},"description":"The kinds of answer accepted: any of text, video, audio. At least one. Video and audio are offered to the giver on Pro and up: on the Free plan the form collects text"},"name":{"type":"string","description":"Internal name, 1 to 100 characters. Required on create"},"welcome_title":{"type":"string","description":"Title of the welcome step, up to 120 characters"},"welcome_message":{"type":"string","description":"Message of the welcome step, up to 1,000 characters, plain text"},"welcome_button":{"type":"string","description":"Button of the welcome step, up to 40 characters"},"rating_title":{"type":"string","description":"Title of the rating step"},"feedback_title":{"type":"string","description":"Title of the private feedback step"},"feedback_message":{"type":"string","description":"Message of the private feedback step"},"feedback_thanks":{"type":"string","description":"The closing line after private feedback"},"about_title":{"type":"string","description":"Title of the About you step"},"about_message":{"type":"string","description":"Message of the About you step"},"consent_title":{"type":"string","description":"Title of the consent step"},"consent_text":{"type":"string","description":"The consent text, up to 2,000 characters. Shown in full and stored word for word on every consent record"},"consent_single_label":{"type":"string","description":"The checkbox wording in single mode"},"thanks_title":{"type":"string","description":"Title of the thank-you step"},"thanks_message":{"type":"string","description":"Message of the thank-you step"},"thanks_button_label":{"type":"string","description":"Label of the optional button"},"thanks_button_url":{"type":"string","description":"Where the optional button goes. Must be an https address"},"accent_color":{"type":"string","description":"Hex color, e.g. #06755b. Empty follows the brand kit"},"background_color":{"type":"string","description":"Hex color. Empty follows the brand kit"},"custom_css":{"type":"string","description":"Custom CSS, up to 20,000 characters. Business and up"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts. A rating is always stored as 1 to 5","enum":["inherit","stars","hearts"]},"theme":{"type":"string","description":"auto (follows the giver's device), light or dark","enum":["auto","light","dark"]},"field_name":{"type":"string","description":"required or optional","enum":["required","optional"]},"consent_mode":{"type":"string","description":"single (one required checkbox grants all four permissions) or separate (one checkbox per permission)","enum":["single","separate"]},"field_email":{"type":"string","description":"off, optional or required. An email is never shown publicly","enum":["off","optional","required"]},"field_photo":{"type":"string","description":"off, optional or required","enum":["off","optional","required"]},"field_title":{"type":"string","description":"off, optional or required","enum":["off","optional","required"]},"field_company":{"type":"string","description":"off, optional or required","enum":["off","optional","required"]},"field_company_url":{"type":"string","description":"off, optional or required. Must be an https address","enum":["off","optional","required"]},"field_social_url":{"type":"string","description":"off, optional or required. Must be an https address","enum":["off","optional","required"]},"consent_show_name":{"type":"string","description":"required, optional or off. Separate mode only","enum":["off","optional","required"]},"consent_show_photo":{"type":"string","description":"required, optional or off. Separate mode only","enum":["off","optional","required"]},"consent_show_video":{"type":"string","description":"required, optional or off. Asked only when the answer is video or audio","enum":["off","optional","required"]},"consent_marketing":{"type":"string","description":"required or optional. Separate mode only","enum":["off","optional","required"]},"welcome_enabled":{"type":"boolean","description":"false starts the form at the next step"},"rating_enabled":{"type":"boolean","description":"Whether the form asks for a rating"},"rating_required":{"type":"boolean","description":"Whether a rating must be given. Always true while low_rating_routing is on"},"low_rating_routing":{"type":"boolean","description":"true sends a rating of 1 to 3 to a private feedback step. That answer is stored as feedback, never as a testimonial, and never counts. Off by default. Business and up"},"thanks_redirect":{"type":"boolean","description":"true goes to thanks_button_url after 5 seconds. Ignored when a reward is shown"},"share_prompt":{"type":"boolean","description":"true offers the giver to share their own words. Text answers only"},"show_logo":{"type":"boolean","description":"Whether the brand kit logo is shown"},"show_progress":{"type":"boolean","description":"Whether the step count and the progress bar are shown"},"turnstile":{"type":"boolean","description":"true (the default) checks the giver is a person before the first answer is accepted"},"show_badge":{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. Always shown below the Business plan"},"questions":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"The whole list of questions, 1 to 10. Each is { key, type, title, help, required, tips, max_seconds (30, 60, 120, 180, 300 or 600, and never more than the plan takes when a recording is made), max_chars, allow_images, choices, property, logic }. type is testimonial, short_text, long_text, single_choice, multiple_choice or yes_no. Exactly one question has the type testimonial. logic is a list of { when: { source, operator, value }, go_to }: source is rating, kind, the key of this or an earlier choice or yes_no question, or param:<name>, and go_to is the key of a later question or about"},"consent_labels":{"type":"object","additionalProperties":true,"description":"The checkbox wording per permission: { show_name, show_photo, show_video, marketing }, up to 300 characters each"},"url_parameters":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Up to 20 rows of { parameter, property }: /f/<slug>?<parameter>=value saves the value to that custom property"}}}}}}},"get":{"operationId":"testimonial_forms_list","summary":"List the forms of a site","description":"Forms in the trash are listed with trashed true, and left out otherwise. Each form carries its settings, its reward and how many submissions it has had.","tags":["Forms"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"Searches the name and the slug"}},{"name":"language","in":"query","required":false,"schema":{"type":"string","description":"Only forms in this language, e.g. de","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"name (the default), created or submissions","enum":["name","created","submissions"],"default":"name"}},{"name":"direction","in":"query","required":false,"schema":{"type":"string","description":"asc or desc. The default is asc for name and desc for the others","enum":["asc","desc"]}},{"name":"trashed","in":"query","required":false,"schema":{"type":"boolean","description":"true lists the forms in the trash instead","default":false}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Form id, e.g. frm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"slug":{"type":"string","description":"The last part of the link"},"url":{"type":"string","description":"The link to send to customers"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the form's public page is closed (410)"},"language":{"type":"string","description":"Language code of the form's own text"},"kinds":{"type":"array","items":{"type":"string"},"description":"The kinds of answer accepted: text, video, audio. Video and audio are offered on Pro and up"},"version":{"type":"integer","description":"Goes up when a step, a question or the consent wording changes. Stored on every consent record"},"starter":{"type":"boolean","description":"true for the form a new site starts with"},"welcome_enabled":{"type":"boolean","description":"Whether the welcome step is shown"},"rating_enabled":{"type":"boolean","description":"Whether the form asks for a rating"},"rating_required":{"type":"boolean","description":"Whether a rating must be given"},"low_rating_routing":{"type":"boolean","description":"Whether a rating of 1 to 3 goes to private feedback. Paused on a plan without it"},"thanks_redirect":{"type":"boolean","description":"Whether the giver is sent on after 5 seconds"},"share_prompt":{"type":"boolean","description":"Whether the giver is offered to share their words"},"show_logo":{"type":"boolean","description":"Whether the brand kit logo is shown"},"show_progress":{"type":"boolean","description":"Whether progress is shown"},"turnstile":{"type":"boolean","description":"Whether the giver is checked to be a person"},"show_badge":{"anyOf":[{"type":"boolean","description":"The badge switch, or null to follow the brand kit"},{"type":"null"}]},"welcome_title":{"anyOf":[{"type":"string","description":"Title of the welcome step"},{"type":"null"}]},"welcome_message":{"anyOf":[{"type":"string","description":"Message of the welcome step"},{"type":"null"}]},"welcome_button":{"anyOf":[{"type":"string","description":"Button of the welcome step"},{"type":"null"}]},"rating_title":{"anyOf":[{"type":"string","description":"Title of the rating step"},{"type":"null"}]},"feedback_title":{"anyOf":[{"type":"string","description":"Title of the private feedback step"},{"type":"null"}]},"feedback_message":{"anyOf":[{"type":"string","description":"Message of the private feedback step"},{"type":"null"}]},"feedback_thanks":{"anyOf":[{"type":"string","description":"Closing line after private feedback"},{"type":"null"}]},"about_title":{"anyOf":[{"type":"string","description":"Title of the About you step"},{"type":"null"}]},"about_message":{"anyOf":[{"type":"string","description":"Message of the About you step"},{"type":"null"}]},"consent_title":{"anyOf":[{"type":"string","description":"Title of the consent step"},{"type":"null"}]},"consent_text":{"anyOf":[{"type":"string","description":"The consent text, stored word for word on consent records"},{"type":"null"}]},"consent_single_label":{"anyOf":[{"type":"string","description":"The checkbox wording in single mode"},{"type":"null"}]},"thanks_title":{"anyOf":[{"type":"string","description":"Title of the thank-you step"},{"type":"null"}]},"thanks_message":{"anyOf":[{"type":"string","description":"Message of the thank-you step"},{"type":"null"}]},"thanks_button_label":{"anyOf":[{"type":"string","description":"Label of the optional button"},{"type":"null"}]},"thanks_button_url":{"anyOf":[{"type":"string","description":"Where the optional button goes"},{"type":"null"}]},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, or null to follow the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or null to follow the brand kit"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"The form's custom CSS"},{"type":"null"}]},"rating_style":{"type":"string","description":"inherit, stars or hearts"},"theme":{"type":"string","description":"auto, light or dark"},"field_name":{"type":"string","description":"required or optional"},"consent_mode":{"type":"string","description":"single or separate"},"field_email":{"type":"string","description":"off, optional or required"},"field_photo":{"type":"string","description":"off, optional or required"},"field_title":{"type":"string","description":"off, optional or required"},"field_company":{"type":"string","description":"off, optional or required"},"field_company_url":{"type":"string","description":"off, optional or required"},"field_social_url":{"type":"string","description":"off, optional or required"},"consent_show_name":{"type":"string","description":"required, optional or off"},"consent_show_photo":{"type":"string","description":"required, optional or off"},"consent_show_video":{"type":"string","description":"required, optional or off"},"consent_marketing":{"type":"string","description":"required or optional"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions in order, with their skip logic"},"consent_labels":{"type":"object","description":"The checkbox wording per permission"},"url_parameters":{"type":"array","items":{"type":"object"},"description":"The URL parameters saved to custom properties"},"reward":{"anyOf":[{"type":"object","description":"The form's reward, or null"},{"type":"null"}]},"submissions_count":{"type":"integer","description":"Completed submissions, private feedback included"},"last_submission_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the form was last completed"},{"type":"null"}]},"trashed":{"type":"boolean","description":"true while it is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_forms_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/forms/{id}/permanent.json":{"delete":{"operationId":"testimonial_forms_delete","summary":"Delete a form for good","description":"Deletes the form, its submission records, its reward and its private feedback. The testimonials it collected are kept. It cannot be undone, so it is done by a person on the page. The API takes confirm (the form's name or id).","tags":["Forms"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_forms_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The id of what was deleted"},"deleted":{"type":"boolean","description":"Always true"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"string","description":"The name of the item (the person's name for a testimonial), or its id"}}}}}}}},"/sites/{site_id}/testimonials/forms/{id}.json":{"delete":{"operationId":"testimonial_forms_trash","summary":"Move a form to the trash","description":"Its link responds that the form is closed until it is restored. The trash is emptied after 30 days. Over MCP the tool changes nothing and responds with the page of the app where a person does it.","tags":["Forms"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_forms_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Form id, e.g. frm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"slug":{"type":"string","description":"The last part of the link"},"url":{"type":"string","description":"The link to send to customers"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the form's public page is closed (410)"},"language":{"type":"string","description":"Language code of the form's own text"},"kinds":{"type":"array","items":{"type":"string"},"description":"The kinds of answer accepted: text, video, audio. Video and audio are offered on Pro and up"},"version":{"type":"integer","description":"Goes up when a step, a question or the consent wording changes. Stored on every consent record"},"starter":{"type":"boolean","description":"true for the form a new site starts with"},"welcome_enabled":{"type":"boolean","description":"Whether the welcome step is shown"},"rating_enabled":{"type":"boolean","description":"Whether the form asks for a rating"},"rating_required":{"type":"boolean","description":"Whether a rating must be given"},"low_rating_routing":{"type":"boolean","description":"Whether a rating of 1 to 3 goes to private feedback. Paused on a plan without it"},"thanks_redirect":{"type":"boolean","description":"Whether the giver is sent on after 5 seconds"},"share_prompt":{"type":"boolean","description":"Whether the giver is offered to share their words"},"show_logo":{"type":"boolean","description":"Whether the brand kit logo is shown"},"show_progress":{"type":"boolean","description":"Whether progress is shown"},"turnstile":{"type":"boolean","description":"Whether the giver is checked to be a person"},"show_badge":{"anyOf":[{"type":"boolean","description":"The badge switch, or null to follow the brand kit"},{"type":"null"}]},"welcome_title":{"anyOf":[{"type":"string","description":"Title of the welcome step"},{"type":"null"}]},"welcome_message":{"anyOf":[{"type":"string","description":"Message of the welcome step"},{"type":"null"}]},"welcome_button":{"anyOf":[{"type":"string","description":"Button of the welcome step"},{"type":"null"}]},"rating_title":{"anyOf":[{"type":"string","description":"Title of the rating step"},{"type":"null"}]},"feedback_title":{"anyOf":[{"type":"string","description":"Title of the private feedback step"},{"type":"null"}]},"feedback_message":{"anyOf":[{"type":"string","description":"Message of the private feedback step"},{"type":"null"}]},"feedback_thanks":{"anyOf":[{"type":"string","description":"Closing line after private feedback"},{"type":"null"}]},"about_title":{"anyOf":[{"type":"string","description":"Title of the About you step"},{"type":"null"}]},"about_message":{"anyOf":[{"type":"string","description":"Message of the About you step"},{"type":"null"}]},"consent_title":{"anyOf":[{"type":"string","description":"Title of the consent step"},{"type":"null"}]},"consent_text":{"anyOf":[{"type":"string","description":"The consent text, stored word for word on consent records"},{"type":"null"}]},"consent_single_label":{"anyOf":[{"type":"string","description":"The checkbox wording in single mode"},{"type":"null"}]},"thanks_title":{"anyOf":[{"type":"string","description":"Title of the thank-you step"},{"type":"null"}]},"thanks_message":{"anyOf":[{"type":"string","description":"Message of the thank-you step"},{"type":"null"}]},"thanks_button_label":{"anyOf":[{"type":"string","description":"Label of the optional button"},{"type":"null"}]},"thanks_button_url":{"anyOf":[{"type":"string","description":"Where the optional button goes"},{"type":"null"}]},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, or null to follow the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or null to follow the brand kit"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"The form's custom CSS"},{"type":"null"}]},"rating_style":{"type":"string","description":"inherit, stars or hearts"},"theme":{"type":"string","description":"auto, light or dark"},"field_name":{"type":"string","description":"required or optional"},"consent_mode":{"type":"string","description":"single or separate"},"field_email":{"type":"string","description":"off, optional or required"},"field_photo":{"type":"string","description":"off, optional or required"},"field_title":{"type":"string","description":"off, optional or required"},"field_company":{"type":"string","description":"off, optional or required"},"field_company_url":{"type":"string","description":"off, optional or required"},"field_social_url":{"type":"string","description":"off, optional or required"},"consent_show_name":{"type":"string","description":"required, optional or off"},"consent_show_photo":{"type":"string","description":"required, optional or off"},"consent_show_video":{"type":"string","description":"required, optional or off"},"consent_marketing":{"type":"string","description":"required or optional"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions in order, with their skip logic"},"consent_labels":{"type":"object","description":"The checkbox wording per permission"},"url_parameters":{"type":"array","items":{"type":"object"},"description":"The URL parameters saved to custom properties"},"reward":{"anyOf":[{"type":"object","description":"The form's reward, or null"},{"type":"null"}]},"submissions_count":{"type":"integer","description":"Completed submissions, private feedback included"},"last_submission_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the form was last completed"},{"type":"null"}]},"trashed":{"type":"boolean","description":"true while it is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"testimonial_forms_get","summary":"Get one form with every step, question, rule and setting","description":"Returns the whole form as testimonial_forms_create and testimonial_forms_update take it, with its slug, its link, its reward and how many submissions it has. A form in the trash is not found here: restore it first.","tags":["Forms"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_forms_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Form id, e.g. frm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"slug":{"type":"string","description":"The last part of the link"},"url":{"type":"string","description":"The link to send to customers"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the form's public page is closed (410)"},"language":{"type":"string","description":"Language code of the form's own text"},"kinds":{"type":"array","items":{"type":"string"},"description":"The kinds of answer accepted: text, video, audio. Video and audio are offered on Pro and up"},"version":{"type":"integer","description":"Goes up when a step, a question or the consent wording changes. Stored on every consent record"},"starter":{"type":"boolean","description":"true for the form a new site starts with"},"welcome_enabled":{"type":"boolean","description":"Whether the welcome step is shown"},"rating_enabled":{"type":"boolean","description":"Whether the form asks for a rating"},"rating_required":{"type":"boolean","description":"Whether a rating must be given"},"low_rating_routing":{"type":"boolean","description":"Whether a rating of 1 to 3 goes to private feedback. Paused on a plan without it"},"thanks_redirect":{"type":"boolean","description":"Whether the giver is sent on after 5 seconds"},"share_prompt":{"type":"boolean","description":"Whether the giver is offered to share their words"},"show_logo":{"type":"boolean","description":"Whether the brand kit logo is shown"},"show_progress":{"type":"boolean","description":"Whether progress is shown"},"turnstile":{"type":"boolean","description":"Whether the giver is checked to be a person"},"show_badge":{"anyOf":[{"type":"boolean","description":"The badge switch, or null to follow the brand kit"},{"type":"null"}]},"welcome_title":{"anyOf":[{"type":"string","description":"Title of the welcome step"},{"type":"null"}]},"welcome_message":{"anyOf":[{"type":"string","description":"Message of the welcome step"},{"type":"null"}]},"welcome_button":{"anyOf":[{"type":"string","description":"Button of the welcome step"},{"type":"null"}]},"rating_title":{"anyOf":[{"type":"string","description":"Title of the rating step"},{"type":"null"}]},"feedback_title":{"anyOf":[{"type":"string","description":"Title of the private feedback step"},{"type":"null"}]},"feedback_message":{"anyOf":[{"type":"string","description":"Message of the private feedback step"},{"type":"null"}]},"feedback_thanks":{"anyOf":[{"type":"string","description":"Closing line after private feedback"},{"type":"null"}]},"about_title":{"anyOf":[{"type":"string","description":"Title of the About you step"},{"type":"null"}]},"about_message":{"anyOf":[{"type":"string","description":"Message of the About you step"},{"type":"null"}]},"consent_title":{"anyOf":[{"type":"string","description":"Title of the consent step"},{"type":"null"}]},"consent_text":{"anyOf":[{"type":"string","description":"The consent text, stored word for word on consent records"},{"type":"null"}]},"consent_single_label":{"anyOf":[{"type":"string","description":"The checkbox wording in single mode"},{"type":"null"}]},"thanks_title":{"anyOf":[{"type":"string","description":"Title of the thank-you step"},{"type":"null"}]},"thanks_message":{"anyOf":[{"type":"string","description":"Message of the thank-you step"},{"type":"null"}]},"thanks_button_label":{"anyOf":[{"type":"string","description":"Label of the optional button"},{"type":"null"}]},"thanks_button_url":{"anyOf":[{"type":"string","description":"Where the optional button goes"},{"type":"null"}]},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, or null to follow the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or null to follow the brand kit"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"The form's custom CSS"},{"type":"null"}]},"rating_style":{"type":"string","description":"inherit, stars or hearts"},"theme":{"type":"string","description":"auto, light or dark"},"field_name":{"type":"string","description":"required or optional"},"consent_mode":{"type":"string","description":"single or separate"},"field_email":{"type":"string","description":"off, optional or required"},"field_photo":{"type":"string","description":"off, optional or required"},"field_title":{"type":"string","description":"off, optional or required"},"field_company":{"type":"string","description":"off, optional or required"},"field_company_url":{"type":"string","description":"off, optional or required"},"field_social_url":{"type":"string","description":"off, optional or required"},"consent_show_name":{"type":"string","description":"required, optional or off"},"consent_show_photo":{"type":"string","description":"required, optional or off"},"consent_show_video":{"type":"string","description":"required, optional or off"},"consent_marketing":{"type":"string","description":"required or optional"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions in order, with their skip logic"},"consent_labels":{"type":"object","description":"The checkbox wording per permission"},"url_parameters":{"type":"array","items":{"type":"object"},"description":"The URL parameters saved to custom properties"},"reward":{"anyOf":[{"type":"object","description":"The form's reward, or null"},{"type":"null"}]},"submissions_count":{"type":"integer","description":"Completed submissions, private feedback included"},"last_submission_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the form was last completed"},{"type":"null"}]},"trashed":{"type":"boolean","description":"true while it is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_forms_get","x-permission":"analytics.read"},"patch":{"operationId":"testimonial_forms_update","summary":"Change a form. Only the inputs sent change","description":"A change to a step, a question or the consent wording raises the form's version, which every consent record stores. A changed slug leaves the old link redirecting. Send questions as the whole list.","tags":["Forms"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_forms_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Form id, e.g. frm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"slug":{"type":"string","description":"The last part of the link"},"url":{"type":"string","description":"The link to send to customers"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the form's public page is closed (410)"},"language":{"type":"string","description":"Language code of the form's own text"},"kinds":{"type":"array","items":{"type":"string"},"description":"The kinds of answer accepted: text, video, audio. Video and audio are offered on Pro and up"},"version":{"type":"integer","description":"Goes up when a step, a question or the consent wording changes. Stored on every consent record"},"starter":{"type":"boolean","description":"true for the form a new site starts with"},"welcome_enabled":{"type":"boolean","description":"Whether the welcome step is shown"},"rating_enabled":{"type":"boolean","description":"Whether the form asks for a rating"},"rating_required":{"type":"boolean","description":"Whether a rating must be given"},"low_rating_routing":{"type":"boolean","description":"Whether a rating of 1 to 3 goes to private feedback. Paused on a plan without it"},"thanks_redirect":{"type":"boolean","description":"Whether the giver is sent on after 5 seconds"},"share_prompt":{"type":"boolean","description":"Whether the giver is offered to share their words"},"show_logo":{"type":"boolean","description":"Whether the brand kit logo is shown"},"show_progress":{"type":"boolean","description":"Whether progress is shown"},"turnstile":{"type":"boolean","description":"Whether the giver is checked to be a person"},"show_badge":{"anyOf":[{"type":"boolean","description":"The badge switch, or null to follow the brand kit"},{"type":"null"}]},"welcome_title":{"anyOf":[{"type":"string","description":"Title of the welcome step"},{"type":"null"}]},"welcome_message":{"anyOf":[{"type":"string","description":"Message of the welcome step"},{"type":"null"}]},"welcome_button":{"anyOf":[{"type":"string","description":"Button of the welcome step"},{"type":"null"}]},"rating_title":{"anyOf":[{"type":"string","description":"Title of the rating step"},{"type":"null"}]},"feedback_title":{"anyOf":[{"type":"string","description":"Title of the private feedback step"},{"type":"null"}]},"feedback_message":{"anyOf":[{"type":"string","description":"Message of the private feedback step"},{"type":"null"}]},"feedback_thanks":{"anyOf":[{"type":"string","description":"Closing line after private feedback"},{"type":"null"}]},"about_title":{"anyOf":[{"type":"string","description":"Title of the About you step"},{"type":"null"}]},"about_message":{"anyOf":[{"type":"string","description":"Message of the About you step"},{"type":"null"}]},"consent_title":{"anyOf":[{"type":"string","description":"Title of the consent step"},{"type":"null"}]},"consent_text":{"anyOf":[{"type":"string","description":"The consent text, stored word for word on consent records"},{"type":"null"}]},"consent_single_label":{"anyOf":[{"type":"string","description":"The checkbox wording in single mode"},{"type":"null"}]},"thanks_title":{"anyOf":[{"type":"string","description":"Title of the thank-you step"},{"type":"null"}]},"thanks_message":{"anyOf":[{"type":"string","description":"Message of the thank-you step"},{"type":"null"}]},"thanks_button_label":{"anyOf":[{"type":"string","description":"Label of the optional button"},{"type":"null"}]},"thanks_button_url":{"anyOf":[{"type":"string","description":"Where the optional button goes"},{"type":"null"}]},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, or null to follow the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or null to follow the brand kit"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"The form's custom CSS"},{"type":"null"}]},"rating_style":{"type":"string","description":"inherit, stars or hearts"},"theme":{"type":"string","description":"auto, light or dark"},"field_name":{"type":"string","description":"required or optional"},"consent_mode":{"type":"string","description":"single or separate"},"field_email":{"type":"string","description":"off, optional or required"},"field_photo":{"type":"string","description":"off, optional or required"},"field_title":{"type":"string","description":"off, optional or required"},"field_company":{"type":"string","description":"off, optional or required"},"field_company_url":{"type":"string","description":"off, optional or required"},"field_social_url":{"type":"string","description":"off, optional or required"},"consent_show_name":{"type":"string","description":"required, optional or off"},"consent_show_photo":{"type":"string","description":"required, optional or off"},"consent_show_video":{"type":"string","description":"required, optional or off"},"consent_marketing":{"type":"string","description":"required or optional"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions in order, with their skip logic"},"consent_labels":{"type":"object","description":"The checkbox wording per permission"},"url_parameters":{"type":"array","items":{"type":"object"},"description":"The URL parameters saved to custom properties"},"reward":{"anyOf":[{"type":"object","description":"The form's reward, or null"},{"type":"null"}]},"submissions_count":{"type":"integer","description":"Completed submissions, private feedback included"},"last_submission_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the form was last completed"},{"type":"null"}]},"trashed":{"type":"boolean","description":"true while it is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_forms_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","description":"The link is /f/<slug>. 3 to 60 characters: a to z, 0 to 9 and hyphens. Unique across Privatus Analytics. The default comes from the name"},"language":{"type":"string","description":"One of the site's languages. Sets the form's own buttons, errors and recorder text","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]},"kinds":{"type":"array","items":{"type":"string","enum":["text","video","audio"]},"description":"The kinds of answer accepted: any of text, video, audio. At least one. Video and audio are offered to the giver on Pro and up: on the Free plan the form collects text"},"name":{"type":"string","description":"Internal name, 1 to 100 characters. Required on create"},"welcome_title":{"type":"string","description":"Title of the welcome step, up to 120 characters"},"welcome_message":{"type":"string","description":"Message of the welcome step, up to 1,000 characters, plain text"},"welcome_button":{"type":"string","description":"Button of the welcome step, up to 40 characters"},"rating_title":{"type":"string","description":"Title of the rating step"},"feedback_title":{"type":"string","description":"Title of the private feedback step"},"feedback_message":{"type":"string","description":"Message of the private feedback step"},"feedback_thanks":{"type":"string","description":"The closing line after private feedback"},"about_title":{"type":"string","description":"Title of the About you step"},"about_message":{"type":"string","description":"Message of the About you step"},"consent_title":{"type":"string","description":"Title of the consent step"},"consent_text":{"type":"string","description":"The consent text, up to 2,000 characters. Shown in full and stored word for word on every consent record"},"consent_single_label":{"type":"string","description":"The checkbox wording in single mode"},"thanks_title":{"type":"string","description":"Title of the thank-you step"},"thanks_message":{"type":"string","description":"Message of the thank-you step"},"thanks_button_label":{"type":"string","description":"Label of the optional button"},"thanks_button_url":{"type":"string","description":"Where the optional button goes. Must be an https address"},"accent_color":{"type":"string","description":"Hex color, e.g. #06755b. Empty follows the brand kit"},"background_color":{"type":"string","description":"Hex color. Empty follows the brand kit"},"custom_css":{"type":"string","description":"Custom CSS, up to 20,000 characters. Business and up"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts. A rating is always stored as 1 to 5","enum":["inherit","stars","hearts"]},"theme":{"type":"string","description":"auto (follows the giver's device), light or dark","enum":["auto","light","dark"]},"field_name":{"type":"string","description":"required or optional","enum":["required","optional"]},"consent_mode":{"type":"string","description":"single (one required checkbox grants all four permissions) or separate (one checkbox per permission)","enum":["single","separate"]},"field_email":{"type":"string","description":"off, optional or required. An email is never shown publicly","enum":["off","optional","required"]},"field_photo":{"type":"string","description":"off, optional or required","enum":["off","optional","required"]},"field_title":{"type":"string","description":"off, optional or required","enum":["off","optional","required"]},"field_company":{"type":"string","description":"off, optional or required","enum":["off","optional","required"]},"field_company_url":{"type":"string","description":"off, optional or required. Must be an https address","enum":["off","optional","required"]},"field_social_url":{"type":"string","description":"off, optional or required. Must be an https address","enum":["off","optional","required"]},"consent_show_name":{"type":"string","description":"required, optional or off. Separate mode only","enum":["off","optional","required"]},"consent_show_photo":{"type":"string","description":"required, optional or off. Separate mode only","enum":["off","optional","required"]},"consent_show_video":{"type":"string","description":"required, optional or off. Asked only when the answer is video or audio","enum":["off","optional","required"]},"consent_marketing":{"type":"string","description":"required or optional. Separate mode only","enum":["off","optional","required"]},"welcome_enabled":{"type":"boolean","description":"false starts the form at the next step"},"rating_enabled":{"type":"boolean","description":"Whether the form asks for a rating"},"rating_required":{"type":"boolean","description":"Whether a rating must be given. Always true while low_rating_routing is on"},"low_rating_routing":{"type":"boolean","description":"true sends a rating of 1 to 3 to a private feedback step. That answer is stored as feedback, never as a testimonial, and never counts. Off by default. Business and up"},"thanks_redirect":{"type":"boolean","description":"true goes to thanks_button_url after 5 seconds. Ignored when a reward is shown"},"share_prompt":{"type":"boolean","description":"true offers the giver to share their own words. Text answers only"},"show_logo":{"type":"boolean","description":"Whether the brand kit logo is shown"},"show_progress":{"type":"boolean","description":"Whether the step count and the progress bar are shown"},"turnstile":{"type":"boolean","description":"true (the default) checks the giver is a person before the first answer is accepted"},"show_badge":{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. Always shown below the Business plan"},"questions":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"The whole list of questions, 1 to 10. Each is { key, type, title, help, required, tips, max_seconds (30, 60, 120, 180, 300 or 600, and never more than the plan takes when a recording is made), max_chars, allow_images, choices, property, logic }. type is testimonial, short_text, long_text, single_choice, multiple_choice or yes_no. Exactly one question has the type testimonial. logic is a list of { when: { source, operator, value }, go_to }: source is rating, kind, the key of this or an earlier choice or yes_no question, or param:<name>, and go_to is the key of a later question or about"},"consent_labels":{"type":"object","additionalProperties":true,"description":"The checkbox wording per permission: { show_name, show_photo, show_video, marketing }, up to 300 characters each"},"url_parameters":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Up to 20 rows of { parameter, property }: /f/<slug>?<parameter>=value saves the value to that custom property"}}}}}}}},"/sites/{site_id}/testimonials/forms/{id}/duplicate.json":{"post":{"operationId":"testimonial_forms_duplicate","summary":"Copy a form, optionally into another language","description":"Copies every setting except the slug, the statistics and the reward.","tags":["Forms"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_forms_list","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Form id, e.g. frm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"slug":{"type":"string","description":"The last part of the link"},"url":{"type":"string","description":"The link to send to customers"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the form's public page is closed (410)"},"language":{"type":"string","description":"Language code of the form's own text"},"kinds":{"type":"array","items":{"type":"string"},"description":"The kinds of answer accepted: text, video, audio. Video and audio are offered on Pro and up"},"version":{"type":"integer","description":"Goes up when a step, a question or the consent wording changes. Stored on every consent record"},"starter":{"type":"boolean","description":"true for the form a new site starts with"},"welcome_enabled":{"type":"boolean","description":"Whether the welcome step is shown"},"rating_enabled":{"type":"boolean","description":"Whether the form asks for a rating"},"rating_required":{"type":"boolean","description":"Whether a rating must be given"},"low_rating_routing":{"type":"boolean","description":"Whether a rating of 1 to 3 goes to private feedback. Paused on a plan without it"},"thanks_redirect":{"type":"boolean","description":"Whether the giver is sent on after 5 seconds"},"share_prompt":{"type":"boolean","description":"Whether the giver is offered to share their words"},"show_logo":{"type":"boolean","description":"Whether the brand kit logo is shown"},"show_progress":{"type":"boolean","description":"Whether progress is shown"},"turnstile":{"type":"boolean","description":"Whether the giver is checked to be a person"},"show_badge":{"anyOf":[{"type":"boolean","description":"The badge switch, or null to follow the brand kit"},{"type":"null"}]},"welcome_title":{"anyOf":[{"type":"string","description":"Title of the welcome step"},{"type":"null"}]},"welcome_message":{"anyOf":[{"type":"string","description":"Message of the welcome step"},{"type":"null"}]},"welcome_button":{"anyOf":[{"type":"string","description":"Button of the welcome step"},{"type":"null"}]},"rating_title":{"anyOf":[{"type":"string","description":"Title of the rating step"},{"type":"null"}]},"feedback_title":{"anyOf":[{"type":"string","description":"Title of the private feedback step"},{"type":"null"}]},"feedback_message":{"anyOf":[{"type":"string","description":"Message of the private feedback step"},{"type":"null"}]},"feedback_thanks":{"anyOf":[{"type":"string","description":"Closing line after private feedback"},{"type":"null"}]},"about_title":{"anyOf":[{"type":"string","description":"Title of the About you step"},{"type":"null"}]},"about_message":{"anyOf":[{"type":"string","description":"Message of the About you step"},{"type":"null"}]},"consent_title":{"anyOf":[{"type":"string","description":"Title of the consent step"},{"type":"null"}]},"consent_text":{"anyOf":[{"type":"string","description":"The consent text, stored word for word on consent records"},{"type":"null"}]},"consent_single_label":{"anyOf":[{"type":"string","description":"The checkbox wording in single mode"},{"type":"null"}]},"thanks_title":{"anyOf":[{"type":"string","description":"Title of the thank-you step"},{"type":"null"}]},"thanks_message":{"anyOf":[{"type":"string","description":"Message of the thank-you step"},{"type":"null"}]},"thanks_button_label":{"anyOf":[{"type":"string","description":"Label of the optional button"},{"type":"null"}]},"thanks_button_url":{"anyOf":[{"type":"string","description":"Where the optional button goes"},{"type":"null"}]},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, or null to follow the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or null to follow the brand kit"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"The form's custom CSS"},{"type":"null"}]},"rating_style":{"type":"string","description":"inherit, stars or hearts"},"theme":{"type":"string","description":"auto, light or dark"},"field_name":{"type":"string","description":"required or optional"},"consent_mode":{"type":"string","description":"single or separate"},"field_email":{"type":"string","description":"off, optional or required"},"field_photo":{"type":"string","description":"off, optional or required"},"field_title":{"type":"string","description":"off, optional or required"},"field_company":{"type":"string","description":"off, optional or required"},"field_company_url":{"type":"string","description":"off, optional or required"},"field_social_url":{"type":"string","description":"off, optional or required"},"consent_show_name":{"type":"string","description":"required, optional or off"},"consent_show_photo":{"type":"string","description":"required, optional or off"},"consent_show_video":{"type":"string","description":"required, optional or off"},"consent_marketing":{"type":"string","description":"required or optional"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions in order, with their skip logic"},"consent_labels":{"type":"object","description":"The checkbox wording per permission"},"url_parameters":{"type":"array","items":{"type":"object"},"description":"The URL parameters saved to custom properties"},"reward":{"anyOf":[{"type":"object","description":"The form's reward, or null"},{"type":"null"}]},"submissions_count":{"type":"integer","description":"Completed submissions, private feedback included"},"last_submission_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the form was last completed"},{"type":"null"}]},"trashed":{"type":"boolean","description":"true while it is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_forms_duplicate","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Name of the copy. The default is the name with \"copy\""},"slug":{"type":"string","description":"Slug of the copy. The default comes from its name"},"language":{"type":"string","description":"Makes the copy a variant in this language of the site","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]}}}}}}}},"/sites/{site_id}/testimonials/forms/{id}/qr.json":{"get":{"operationId":"testimonial_forms_qr","summary":"Get a form's QR code as SVG or PNG","description":"The code holds the form's link with ?src=qr, so scans are counted as their own channel. A changed slug keeps a printed code working.","tags":["Forms"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_forms_list","schema":{"type":"string"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","description":"svg (the default) or png","enum":["svg","png"],"default":"svg"}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","description":"512, 1024 (the default) or 2048 pixels","default":1024}},{"name":"color","in":"query","required":false,"schema":{"type":"string","description":"Hex color of the code. Black, or any color whose contrast on white is at least 7 to 1","default":"#000000"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"url":{"type":"string","description":"The link inside the code"},"content_type":{"type":"string","description":"image/svg+xml or image/png"},"filename":{"type":"string","description":"A file name for it"},"svg":{"anyOf":[{"type":"string","description":"The SVG as text, or null for a PNG"},{"type":"null"}]},"png_base64":{"anyOf":[{"type":"string","description":"The PNG in Base64, or null for an SVG"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_forms_qr","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/forms/{id}/restore.json":{"post":{"operationId":"testimonial_forms_restore","summary":"Restore a form from the trash. Its link works again","description":"Takes a form out of the trash as it was, with its questions, submissions and private feedback. Its link (/f/<slug>) and its embeds take answers again. The server responds with 422 and the code not_in_trash for a form that is not in the trash.","tags":["Forms"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_forms_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Form id, e.g. frm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"slug":{"type":"string","description":"The last part of the link"},"url":{"type":"string","description":"The link to send to customers"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the form's public page is closed (410)"},"language":{"type":"string","description":"Language code of the form's own text"},"kinds":{"type":"array","items":{"type":"string"},"description":"The kinds of answer accepted: text, video, audio. Video and audio are offered on Pro and up"},"version":{"type":"integer","description":"Goes up when a step, a question or the consent wording changes. Stored on every consent record"},"starter":{"type":"boolean","description":"true for the form a new site starts with"},"welcome_enabled":{"type":"boolean","description":"Whether the welcome step is shown"},"rating_enabled":{"type":"boolean","description":"Whether the form asks for a rating"},"rating_required":{"type":"boolean","description":"Whether a rating must be given"},"low_rating_routing":{"type":"boolean","description":"Whether a rating of 1 to 3 goes to private feedback. Paused on a plan without it"},"thanks_redirect":{"type":"boolean","description":"Whether the giver is sent on after 5 seconds"},"share_prompt":{"type":"boolean","description":"Whether the giver is offered to share their words"},"show_logo":{"type":"boolean","description":"Whether the brand kit logo is shown"},"show_progress":{"type":"boolean","description":"Whether progress is shown"},"turnstile":{"type":"boolean","description":"Whether the giver is checked to be a person"},"show_badge":{"anyOf":[{"type":"boolean","description":"The badge switch, or null to follow the brand kit"},{"type":"null"}]},"welcome_title":{"anyOf":[{"type":"string","description":"Title of the welcome step"},{"type":"null"}]},"welcome_message":{"anyOf":[{"type":"string","description":"Message of the welcome step"},{"type":"null"}]},"welcome_button":{"anyOf":[{"type":"string","description":"Button of the welcome step"},{"type":"null"}]},"rating_title":{"anyOf":[{"type":"string","description":"Title of the rating step"},{"type":"null"}]},"feedback_title":{"anyOf":[{"type":"string","description":"Title of the private feedback step"},{"type":"null"}]},"feedback_message":{"anyOf":[{"type":"string","description":"Message of the private feedback step"},{"type":"null"}]},"feedback_thanks":{"anyOf":[{"type":"string","description":"Closing line after private feedback"},{"type":"null"}]},"about_title":{"anyOf":[{"type":"string","description":"Title of the About you step"},{"type":"null"}]},"about_message":{"anyOf":[{"type":"string","description":"Message of the About you step"},{"type":"null"}]},"consent_title":{"anyOf":[{"type":"string","description":"Title of the consent step"},{"type":"null"}]},"consent_text":{"anyOf":[{"type":"string","description":"The consent text, stored word for word on consent records"},{"type":"null"}]},"consent_single_label":{"anyOf":[{"type":"string","description":"The checkbox wording in single mode"},{"type":"null"}]},"thanks_title":{"anyOf":[{"type":"string","description":"Title of the thank-you step"},{"type":"null"}]},"thanks_message":{"anyOf":[{"type":"string","description":"Message of the thank-you step"},{"type":"null"}]},"thanks_button_label":{"anyOf":[{"type":"string","description":"Label of the optional button"},{"type":"null"}]},"thanks_button_url":{"anyOf":[{"type":"string","description":"Where the optional button goes"},{"type":"null"}]},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, or null to follow the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or null to follow the brand kit"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"The form's custom CSS"},{"type":"null"}]},"rating_style":{"type":"string","description":"inherit, stars or hearts"},"theme":{"type":"string","description":"auto, light or dark"},"field_name":{"type":"string","description":"required or optional"},"consent_mode":{"type":"string","description":"single or separate"},"field_email":{"type":"string","description":"off, optional or required"},"field_photo":{"type":"string","description":"off, optional or required"},"field_title":{"type":"string","description":"off, optional or required"},"field_company":{"type":"string","description":"off, optional or required"},"field_company_url":{"type":"string","description":"off, optional or required"},"field_social_url":{"type":"string","description":"off, optional or required"},"consent_show_name":{"type":"string","description":"required, optional or off"},"consent_show_photo":{"type":"string","description":"required, optional or off"},"consent_show_video":{"type":"string","description":"required, optional or off"},"consent_marketing":{"type":"string","description":"required or optional"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions in order, with their skip logic"},"consent_labels":{"type":"object","description":"The checkbox wording per permission"},"url_parameters":{"type":"array","items":{"type":"object"},"description":"The URL parameters saved to custom properties"},"reward":{"anyOf":[{"type":"object","description":"The form's reward, or null"},{"type":"null"}]},"submissions_count":{"type":"integer","description":"Completed submissions, private feedback included"},"last_submission_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the form was last completed"},{"type":"null"}]},"trashed":{"type":"boolean","description":"true while it is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_forms_restore","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials/forms/{id}/share.json":{"get":{"operationId":"testimonial_forms_share","summary":"Get a form's link, QR code links and embed snippets","description":"Returns the link, the inline embed snippet and the popup embed snippet. The popup inputs (trigger, label, position, accent) change the popup snippet.","tags":["Forms"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_forms_list","schema":{"type":"string"}},{"name":"trigger","in":"query","required":false,"schema":{"type":"string","description":"What opens the popup: button, tab (a tab on the side of the page) or own (an element of your own)","enum":["button","tab","own"],"default":"button"}},{"name":"label","in":"query","required":false,"schema":{"type":"string","description":"The button or tab label, up to 40 characters"}},{"name":"position","in":"query","required":false,"schema":{"type":"string","description":"left or right, for the tab","enum":["left","right"],"default":"right"}},{"name":"accent","in":"query","required":false,"schema":{"type":"string","description":"Hex color of the button or tab, e.g. #06755b"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"form_id":{"type":"string","description":"The form"},"url":{"type":"string","description":"The link to send to customers"},"embed_url":{"type":"string","description":"The page the embeds frame"},"qr_svg_url":{"type":"string","description":"The QR code as SVG, for a signed-in member"},"qr_png_url":{"type":"string","description":"The QR code as PNG, for a signed-in member"},"inline_snippet":{"type":"string","description":"The code that shows the form in a page"},"popup_snippet":{"type":"string","description":"The code that opens the form in a popup"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_forms_share","x-permission":"analytics.read"}},"/sites/{site_id}/funnels.json":{"post":{"operationId":"funnels_create","summary":"Create a funnel","description":"Creates a funnel, a sequence of steps that visits move through, measured per visit. Pass name and steps, an ordered list of {type, value, match, name}. type is page, event or goal. value is a path for page steps (for example /pricing), a custom event name for event steps, or a goal id (goal_..., from goals_list) for goal steps. match is only for page steps and is exact, prefix, glob (* wildcard) or regex, defaulting to glob when the value has a * and exact otherwise. name is an optional label. Steps with an empty value are dropped. order_mode is strict (each step must come after the previous one, the default) or any (steps in any order). window is visit (the default) or day, and both measure within a single visit because no visitor id is stored. Plan limits apply. Free allows 3 funnels per site and 5 steps, Pro allows 10 steps and Business 20, and a funnel needs at least 2 steps. Returns the funnel with id (fun_...). Read results with funnels_get. Needs the content.write permission.","tags":["Funnels"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Funnel id, e.g. fun_7Q2K9XH3AB"},"name":{"type":"string"},"steps":{"type":"array","items":{"type":"object"},"description":"Steps: {type: page|event|goal, value, match, name}"},"order_mode":{"type":"string","description":"strict or any"},"window":{"type":"string","description":"visit or day"},"stats":{"anyOf":[{"type":"object","properties":{"entered":{"type":"integer","description":"Visits that reached step 1"},"completed":{"type":"integer","description":"Visits that reached the last step"},"conversion_rate":{"type":"number","description":"Completed ÷ entered, %"}},"description":"Period stats (list only)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"funnels_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Funnel name, for example Signup flow","examples":["Signup flow"]},"steps":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Ordered steps, at least 2 and up to your plan limit (Free 5, Pro 10, Business 20): [{\"type\": \"page|event|goal\", \"value\": \"/pricing | Signup | goal_...\", \"match\": \"exact|prefix|glob|regex\", \"name\": \"optional label\"}]. For page steps value is a path and match defaults to glob when it contains a * and exact otherwise. For event steps value is a custom event name. For goal steps value is a goal id from goals_list. Steps with an empty value are dropped"},"order_mode":{"type":"string","description":"strict (default) needs the steps in order, any accepts them in any order","enum":["strict","any"],"default":"strict"},"window":{"type":"string","description":"visit (default) or day. Both measure inside one visit, because no visitor id is stored and a visit never spans a UTC day","enum":["visit","day"],"default":"visit"}},"required":["name","steps"]}}}}},"get":{"operationId":"funnels_list","summary":"List funnels with entries, completions and rate","description":"Lists the funnels of a site with their headline results for the period, ordered by name. Each funnel has id (fun_...), name, steps, order_mode, window and stats {entered, completed, conversion_rate}, where entered is visits that reached step 1, completed is visits that reached the last step and conversion_rate is a percent (0 to 100). Paginated with page and per_page (max 100, default 25). Takes the shared period and filters inputs. For step-by-step detail use funnels_get, and use funnels_create to add one.","tags":["Funnels"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","description":"Page number, starting at 1","default":1}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","description":"Funnels per page, 1 to 100. Default 25","default":25}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Funnel id, e.g. fun_7Q2K9XH3AB"},"name":{"type":"string"},"steps":{"type":"array","items":{"type":"object"},"description":"Steps: {type: page|event|goal, value, match, name}"},"order_mode":{"type":"string","description":"strict or any"},"window":{"type":"string","description":"visit or day"},"stats":{"anyOf":[{"type":"object","properties":{"entered":{"type":"integer","description":"Visits that reached step 1"},"completed":{"type":"integer","description":"Visits that reached the last step"},"conversion_rate":{"type":"number","description":"Completed ÷ entered, %"}},"description":"Period stats (list only)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"funnels_list","x-permission":"analytics.read"}},"/sites/{site_id}/funnels/{id}.json":{"delete":{"operationId":"funnels_delete","summary":"Delete a funnel","description":"Permanently deletes a funnel definition. No analytics data is touched, but the funnel and its settings cannot be recovered and there is no undo. Returns the deleted funnel. Ids (fun_...) come from funnels_list. Use funnels_update to change a funnel instead. Needs the content.write permission.","tags":["Funnels"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by funnels_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Funnel id, e.g. fun_7Q2K9XH3AB"},"name":{"type":"string"},"steps":{"type":"array","items":{"type":"object"},"description":"Steps: {type: page|event|goal, value, match, name}"},"order_mode":{"type":"string","description":"strict or any"},"window":{"type":"string","description":"visit or day"},"stats":{"anyOf":[{"type":"object","properties":{"entered":{"type":"integer","description":"Visits that reached step 1"},"completed":{"type":"integer","description":"Visits that reached the last step"},"conversion_rate":{"type":"number","description":"Completed ÷ entered, %"}},"description":"Period stats (list only)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"funnels_delete","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"funnels_get","summary":"Funnel report: step counts, conversion, drop-off, time between steps and where visits went instead","description":"The conversion report of one funnel for a period. Returns period, funnel_id, name, order_mode, window, steps, overall_conversion_rate, breakdown and, with compare, comparison. Each step has index (from 1), name, type, value, match, count (visits that reached it), step_conversion_rate (percent of the previous step), overall_conversion_rate (percent of step 1), dropoff and dropoff_rate (visits that left after this step), median_seconds_from_previous (null for step 1) and next_pages (top 5 pages visited next by dropped visits, with (exit) for those who left). Rates are percents from 0 to 100. Set breakdown to channel, device, country, utm_campaign, utm_source, browser or os to get the overall conversion per value (top 20). comparison has the other period's counts, overall_conversion_rate and change (percent, null when the earlier rate was 0). Page filters are ignored here because they would cut visits short, use a page step instead. Takes the shared period, compare, filters and segment inputs. Ids come from funnels_list.","tags":["Funnels"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by funnels_list","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"breakdown","in":"query","required":false,"schema":{"type":"string","description":"Split the step counts by one visit dimension and return the top 20 values with their overall conversion rate","enum":["channel","device","country","utm_campaign","utm_source","browser","os"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"period":{"type":"object","description":"from/to of the period (UTC)"},"funnel":{"type":"object","properties":{"id":{"type":"string","description":"Funnel id, e.g. fun_7Q2K9XH3AB"},"name":{"type":"string"},"steps":{"type":"array","items":{"type":"object"},"description":"Steps: {type: page|event|goal, value, match, name}"},"order_mode":{"type":"string","description":"strict or any"},"window":{"type":"string","description":"visit or day"},"stats":{"anyOf":[{"type":"object","properties":{"entered":{"type":"integer","description":"Visits that reached step 1"},"completed":{"type":"integer","description":"Visits that reached the last step"},"conversion_rate":{"type":"number","description":"Completed ÷ entered, %"}},"description":"Period stats (list only)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"description":"The funnel definition"},"order_mode":{"type":"string","description":"strict or any"},"window":{"type":"string","description":"visit or day (day is measured within a visit)"},"steps":{"type":"array","items":{"type":"object"},"description":"Per step: index, name, type, value, count, step_conversion_rate, overall_conversion_rate, dropoff, dropoff_rate, median_seconds_from_previous, next_pages [{value, count}]"},"overall_conversion_rate":{"type":"number","description":"Last step ÷ first step, %"},"breakdown":{"anyOf":[{"type":"object","description":"dimension, label and rows [{value, counts, overall_conversion_rate}]"},{"type":"null"}]},"comparison":{"anyOf":[{"type":"object","description":"period, counts per step, overall_conversion_rate and change (%)"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"funnels_get","x-permission":"analytics.read"},"patch":{"operationId":"funnels_update","summary":"Update a funnel","description":"Changes a funnel. Only the inputs you send change. Sending steps replaces the whole list of steps, so send every step in order (format and step limits are the same as in funnels_create, free allows 5 steps, Pro 10 and Business 20, and goal steps must name goals of this site). You can also change name, order_mode (strict or any) and window (visit or day). Results are computed from the definition when read, so changing a funnel applies to all history straight away and past numbers shown earlier will differ. Returns the funnel. Ids come from funnels_list. Needs the content.write permission.","tags":["Funnels"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by funnels_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Funnel id, e.g. fun_7Q2K9XH3AB"},"name":{"type":"string"},"steps":{"type":"array","items":{"type":"object"},"description":"Steps: {type: page|event|goal, value, match, name}"},"order_mode":{"type":"string","description":"strict or any"},"window":{"type":"string","description":"visit or day"},"stats":{"anyOf":[{"type":"object","properties":{"entered":{"type":"integer","description":"Visits that reached step 1"},"completed":{"type":"integer","description":"Visits that reached the last step"},"conversion_rate":{"type":"number","description":"Completed ÷ entered, %"}},"description":"Period stats (list only)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"funnels_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New funnel name. Leave out to keep it","examples":["Signup flow"]},"steps":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Replaces ALL steps, so send every step in order. Same format as when creating: [{\"type\": \"page|event|goal\", \"value\": \"/pricing | Signup | goal_...\", \"match\": \"exact|prefix|glob|regex\", \"name\": \"optional label\"}], at least 2 and up to your plan limit"},"order_mode":{"type":"string","description":"strict needs the steps in order, any accepts them in any order. Leave out to keep it","enum":["strict","any"]},"window":{"type":"string","description":"visit or day. Both measure inside one visit. Leave out to keep it","enum":["visit","day"]}}}}}}}},"/sites/{site_id}/goals/{id}/archive.json":{"post":{"operationId":"goals_archive","summary":"Archive a goal (hidden from reports)","description":"Archives a goal. An archived goal is hidden from reports, does not count toward the plan's goal limit and keeps its definition, so it can be restored later with goals_unarchive. No data is deleted. Returns the goal with archived true and archived_at set. Archiving an already archived goal does nothing. Use goals_delete to remove it for good. Needs the content.write permission.","tags":["Goals"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by goals_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Goal id, e.g. goal_7Q2K9XH3AB"},"name":{"type":"string"},"kind":{"type":"string","description":"page, event, engagement, outbound or download"},"match_type":{"type":"string","description":"exact, prefix, glob or regex"},"pattern":{"anyOf":[{"type":"string","description":"Path, domain or file pattern"},{"type":"null"}]},"hostname":{"anyOf":[{"type":"string","description":"Hostname restriction (page goals)"},{"type":"null"}]},"event_name":{"anyOf":[{"type":"string","description":"Custom event name (event goals)"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Event property conditions"},"scroll_threshold":{"anyOf":[{"type":"integer","description":"Engagement: scroll %"},{"type":"null"}]},"time_threshold_seconds":{"anyOf":[{"type":"integer","description":"Engagement: seconds on page"},{"type":"null"}]},"value_mode":{"type":"string","description":"none, fixed or revenue"},"fixed_value_minor":{"anyOf":[{"type":"integer","description":"Fixed value in minor units"},{"type":"null"}]},"count_mode":{"type":"string","description":"once_per_visit or every"},"archived":{"type":"boolean"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"completions":{"type":"integer","description":"Matching events, repeats included"},"conversions":{"type":"integer","description":"Visits with at least one completion"},"conversion_rate":{"type":"number","description":"Conversions ÷ visits (or ÷ visitors, per site setting), %"},"value":{"type":"integer","description":"Goal value in site currency minor units"},"change":{"anyOf":[{"type":"number","description":"Conversions change vs the previous period, %"},{"type":"null"}]}},"description":"Period stats (list only)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"goals_archive","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/goals.json":{"post":{"operationId":"goals_create","summary":"Create a goal","description":"Creates a conversion goal. Goals are definitions applied when reports are read, so a new goal immediately counts matching events in all existing history. Required are name and kind. kind decides which other inputs apply. page needs pattern (a path, for example /thank-you, with match_type exact, prefix, glob or regex) and can use hostname. event needs event_name and can use conditions (property tests such as {key: plan, operator: is, value: pro}, all must match, operators is, is_not, contains, gt, lt). engagement needs pattern plus scroll_threshold (percent 1 to 100) and/or time_threshold_seconds (reached when either is met). outbound matches the link domain with pattern (for example stripe.com) and download matches the file with pattern (for example *.pdf). value_mode is none (default), fixed (uses fixed_value, a decimal amount in the site currency such as 49.5, stored as fixed_value_minor in cents) or revenue (the event's own revenue). count_mode is once_per_visit (default) or every. Free workspaces allow 10 active goals per site, paid plans are unlimited. Returns the goal with id (goal_...). Needs the content.write permission.","tags":["Goals"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Goal id, e.g. goal_7Q2K9XH3AB"},"name":{"type":"string"},"kind":{"type":"string","description":"page, event, engagement, outbound or download"},"match_type":{"type":"string","description":"exact, prefix, glob or regex"},"pattern":{"anyOf":[{"type":"string","description":"Path, domain or file pattern"},{"type":"null"}]},"hostname":{"anyOf":[{"type":"string","description":"Hostname restriction (page goals)"},{"type":"null"}]},"event_name":{"anyOf":[{"type":"string","description":"Custom event name (event goals)"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Event property conditions"},"scroll_threshold":{"anyOf":[{"type":"integer","description":"Engagement: scroll %"},{"type":"null"}]},"time_threshold_seconds":{"anyOf":[{"type":"integer","description":"Engagement: seconds on page"},{"type":"null"}]},"value_mode":{"type":"string","description":"none, fixed or revenue"},"fixed_value_minor":{"anyOf":[{"type":"integer","description":"Fixed value in minor units"},{"type":"null"}]},"count_mode":{"type":"string","description":"once_per_visit or every"},"archived":{"type":"boolean"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"completions":{"type":"integer","description":"Matching events, repeats included"},"conversions":{"type":"integer","description":"Visits with at least one completion"},"conversion_rate":{"type":"number","description":"Conversions ÷ visits (or ÷ visitors, per site setting), %"},"value":{"type":"integer","description":"Goal value in site currency minor units"},"change":{"anyOf":[{"type":"number","description":"Conversions change vs the previous period, %"},{"type":"null"}]}},"description":"Period stats (list only)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"goals_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Goal name, up to 120 characters, for example Signed up","examples":["Signed up"]},"kind":{"type":"string","description":"page (visit a page), event (custom event), engagement (scroll or time on page), outbound (outbound link click) or download (file download)","enum":["page","event","engagement","outbound","download"]},"match_type":{"type":"string","description":"How pattern matches the path (page, engagement), link domain (outbound) or file (download): exact, prefix, glob (*) or regex","enum":["exact","prefix","glob","regex"],"default":"exact"},"pattern":{"type":"string","description":"Required for page, engagement, outbound and download goals. A path for page and engagement (/pricing, /blog/*), a link domain for outbound (stripe.com) or a file name for download (*.pdf). Read according to match_type"},"hostname":{"type":"string","description":"Page goals only. Count the page only on this hostname, for example docs.example.com. Leave empty for any hostname"},"event_name":{"type":"string","description":"Required for event goals. The custom event name, for example Signup"},"conditions":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Event goals only. Property tests that must ALL match: [{\"key\": \"plan\", \"operator\": \"is|is_not|contains|gt|lt\", \"value\": \"pro\"}]. key is a lowercase property key. gt and lt compare numbers","default":[]},"scroll_threshold":{"type":"integer","description":"Engagement goals only. Percent of the page scrolled, 1 to 100. The goal is met when this OR time_threshold_seconds is reached"},"time_threshold_seconds":{"type":"integer","description":"Engagement goals only. Seconds of engaged time on the page. The goal is met when this OR scroll_threshold is reached"},"value_mode":{"type":"string","description":"none, fixed (fixed_value per conversion) or revenue (the event revenue)","enum":["none","fixed","revenue"],"default":"none"},"fixed_value":{"type":"number","description":"Used when value_mode is fixed. A decimal amount in the site currency (major units, for example 49.5), stored as fixed_value_minor in cents"},"count_mode":{"type":"string","description":"Value counts once_per_visit or every completion","enum":["once_per_visit","every"],"default":"once_per_visit"}},"required":["name","kind"]}}}}},"get":{"operationId":"goals_list","summary":"List goals with completions, conversions, rate and value for a period","description":"Lists the goals of a site with their results for the period. Each goal is the definition (id goal_..., name, kind, match_type, pattern, hostname, event_name, conditions, scroll_threshold, time_threshold_seconds, value_mode, fixed_value_minor in cents, count_mode, archived, archived_at) plus stats {completions, conversions, conversion_rate, value, change}. conversion_rate is a percent (0 to 100), value is in minor units (cents) and change is the percent change in conversions against the previous period (null when the earlier count was 0). status filters to active (default), archived or all. Paginated with page and per_page (max 100, default 25). Use goals_get for the full report of one goal. Takes the shared period, compare and filters inputs.","tags":["Goals"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"active (default), archived or all","enum":["active","archived","all"],"default":"active"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","description":"Page number, starting at 1","default":1}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","description":"Goals per page, 1 to 100. Default 25","default":25}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Goal id, e.g. goal_7Q2K9XH3AB"},"name":{"type":"string"},"kind":{"type":"string","description":"page, event, engagement, outbound or download"},"match_type":{"type":"string","description":"exact, prefix, glob or regex"},"pattern":{"anyOf":[{"type":"string","description":"Path, domain or file pattern"},{"type":"null"}]},"hostname":{"anyOf":[{"type":"string","description":"Hostname restriction (page goals)"},{"type":"null"}]},"event_name":{"anyOf":[{"type":"string","description":"Custom event name (event goals)"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Event property conditions"},"scroll_threshold":{"anyOf":[{"type":"integer","description":"Engagement: scroll %"},{"type":"null"}]},"time_threshold_seconds":{"anyOf":[{"type":"integer","description":"Engagement: seconds on page"},{"type":"null"}]},"value_mode":{"type":"string","description":"none, fixed or revenue"},"fixed_value_minor":{"anyOf":[{"type":"integer","description":"Fixed value in minor units"},{"type":"null"}]},"count_mode":{"type":"string","description":"once_per_visit or every"},"archived":{"type":"boolean"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"completions":{"type":"integer","description":"Matching events, repeats included"},"conversions":{"type":"integer","description":"Visits with at least one completion"},"conversion_rate":{"type":"number","description":"Conversions ÷ visits (or ÷ visitors, per site setting), %"},"value":{"type":"integer","description":"Goal value in site currency minor units"},"change":{"anyOf":[{"type":"number","description":"Conversions change vs the previous period, %"},{"type":"null"}]}},"description":"Period stats (list only)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"goals_list","x-permission":"analytics.read"}},"/sites/{site_id}/goals/{id}.json":{"delete":{"operationId":"goals_delete","summary":"Delete a goal (data is kept)","description":"Permanently deletes a goal definition. No event data is deleted, but the goal disappears from reports, and funnel steps, journeys and experiments that point to it stop working. There is no undo. To hide a goal and keep it, use goals_archive. Returns the deleted goal. Ids (goal_...) come from goals_list. Needs the content.write permission.","tags":["Goals"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by goals_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Goal id, e.g. goal_7Q2K9XH3AB"},"name":{"type":"string"},"kind":{"type":"string","description":"page, event, engagement, outbound or download"},"match_type":{"type":"string","description":"exact, prefix, glob or regex"},"pattern":{"anyOf":[{"type":"string","description":"Path, domain or file pattern"},{"type":"null"}]},"hostname":{"anyOf":[{"type":"string","description":"Hostname restriction (page goals)"},{"type":"null"}]},"event_name":{"anyOf":[{"type":"string","description":"Custom event name (event goals)"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Event property conditions"},"scroll_threshold":{"anyOf":[{"type":"integer","description":"Engagement: scroll %"},{"type":"null"}]},"time_threshold_seconds":{"anyOf":[{"type":"integer","description":"Engagement: seconds on page"},{"type":"null"}]},"value_mode":{"type":"string","description":"none, fixed or revenue"},"fixed_value_minor":{"anyOf":[{"type":"integer","description":"Fixed value in minor units"},{"type":"null"}]},"count_mode":{"type":"string","description":"once_per_visit or every"},"archived":{"type":"boolean"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"completions":{"type":"integer","description":"Matching events, repeats included"},"conversions":{"type":"integer","description":"Visits with at least one completion"},"conversion_rate":{"type":"number","description":"Conversions ÷ visits (or ÷ visitors, per site setting), %"},"value":{"type":"integer","description":"Goal value in site currency minor units"},"change":{"anyOf":[{"type":"number","description":"Conversions change vs the previous period, %"},{"type":"null"}]}},"description":"Period stats (list only)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"goals_delete","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"goals_get","summary":"Goal report: metrics, chart, breakdowns and the journey to converting","description":"One goal in depth for a period. Returns period, goal_id, goal (the definition), metrics, interval, series, breakdowns, journey and, with compare, comparison_period, comparison and change. metrics has completions (every matching event), conversions (visits with at least one completion), conversion_rate (percent from 0 to 100) and value (minor units, cents). conversion_rate divides by visits, or by visitors when the site is set that way. series is a list of {date, completions, conversions, conversion_rate} per time bucket (set interval to change it). breakdowns holds the top 10 by conversions for channel, utm_campaign, entry_page, country and device, each as {value, completions, conversions, conversion_rate}. journey shows converting_visits, median_seconds_to_convert, median_pages_before and pages_before (top 10 pages seen before converting, with visits and share). Use goals_list for all goals at once and funnels_get for multi-step flows. Takes the shared period, compare, filters and segment inputs.","tags":["Goals"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by goals_list","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Chart bucket size for the series. auto picks one to suit the range","enum":["auto","minute","hour","day","week","month","quarter","year"],"default":"auto"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"period":{"type":"object","description":"from/to of the period (UTC)"},"goal":{"type":"object","properties":{"id":{"type":"string","description":"Goal id, e.g. goal_7Q2K9XH3AB"},"name":{"type":"string"},"kind":{"type":"string","description":"page, event, engagement, outbound or download"},"match_type":{"type":"string","description":"exact, prefix, glob or regex"},"pattern":{"anyOf":[{"type":"string","description":"Path, domain or file pattern"},{"type":"null"}]},"hostname":{"anyOf":[{"type":"string","description":"Hostname restriction (page goals)"},{"type":"null"}]},"event_name":{"anyOf":[{"type":"string","description":"Custom event name (event goals)"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Event property conditions"},"scroll_threshold":{"anyOf":[{"type":"integer","description":"Engagement: scroll %"},{"type":"null"}]},"time_threshold_seconds":{"anyOf":[{"type":"integer","description":"Engagement: seconds on page"},{"type":"null"}]},"value_mode":{"type":"string","description":"none, fixed or revenue"},"fixed_value_minor":{"anyOf":[{"type":"integer","description":"Fixed value in minor units"},{"type":"null"}]},"count_mode":{"type":"string","description":"once_per_visit or every"},"archived":{"type":"boolean"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"completions":{"type":"integer","description":"Matching events, repeats included"},"conversions":{"type":"integer","description":"Visits with at least one completion"},"conversion_rate":{"type":"number","description":"Conversions ÷ visits (or ÷ visitors, per site setting), %"},"value":{"type":"integer","description":"Goal value in site currency minor units"},"change":{"anyOf":[{"type":"number","description":"Conversions change vs the previous period, %"},{"type":"null"}]}},"description":"Period stats (list only)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"description":"The goal definition"},"metrics":{"type":"object","description":"completions, conversions, conversion_rate (%), value (minor units)"},"comparison_period":{"anyOf":[{"type":"object","description":"Comparison from/to"},{"type":"null"}]},"comparison":{"anyOf":[{"type":"object","description":"Metrics for the comparison period"},{"type":"null"}]},"change":{"anyOf":[{"type":"object","description":"Change vs comparison, % per metric"},{"type":"null"}]},"interval":{"type":"string","description":"Chart bucket size"},"series":{"type":"array","items":{"type":"object"},"description":"Per bucket: date, completions, conversions, conversion_rate"},"breakdowns":{"type":"object","description":"Top values by conversions for channel, utm_campaign, entry_page, country and device: value, completions, conversions, conversion_rate"},"journey":{"anyOf":[{"type":"object","description":"converting_visits, median_seconds_to_convert, median_pages_before and pages_before (pages viewed earlier in the visit, by converting visits)"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"goals_get","x-permission":"analytics.read"},"patch":{"operationId":"goals_update","summary":"Update a goal","description":"Changes a goal's definition. Only the inputs you send change. The new definition applies to all history straight away, so past conversion numbers will change. The inputs are the same as in goals_create, and the same combinations apply, for example event_name and conditions only matter for event goals and scroll_threshold and time_threshold_seconds only for engagement goals. fixed_value is a decimal amount in the site currency (stored in cents). Sending conditions replaces all existing conditions. Returns the goal. Ids come from goals_list. Needs the content.write permission.","tags":["Goals"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by goals_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Goal id, e.g. goal_7Q2K9XH3AB"},"name":{"type":"string"},"kind":{"type":"string","description":"page, event, engagement, outbound or download"},"match_type":{"type":"string","description":"exact, prefix, glob or regex"},"pattern":{"anyOf":[{"type":"string","description":"Path, domain or file pattern"},{"type":"null"}]},"hostname":{"anyOf":[{"type":"string","description":"Hostname restriction (page goals)"},{"type":"null"}]},"event_name":{"anyOf":[{"type":"string","description":"Custom event name (event goals)"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Event property conditions"},"scroll_threshold":{"anyOf":[{"type":"integer","description":"Engagement: scroll %"},{"type":"null"}]},"time_threshold_seconds":{"anyOf":[{"type":"integer","description":"Engagement: seconds on page"},{"type":"null"}]},"value_mode":{"type":"string","description":"none, fixed or revenue"},"fixed_value_minor":{"anyOf":[{"type":"integer","description":"Fixed value in minor units"},{"type":"null"}]},"count_mode":{"type":"string","description":"once_per_visit or every"},"archived":{"type":"boolean"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"completions":{"type":"integer","description":"Matching events, repeats included"},"conversions":{"type":"integer","description":"Visits with at least one completion"},"conversion_rate":{"type":"number","description":"Conversions ÷ visits (or ÷ visitors, per site setting), %"},"value":{"type":"integer","description":"Goal value in site currency minor units"},"change":{"anyOf":[{"type":"number","description":"Conversions change vs the previous period, %"},{"type":"null"}]}},"description":"Period stats (list only)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"goals_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New goal name. Leave out to keep it","examples":["Signed up"]},"kind":{"type":"string","description":"page (visit a page), event (custom event), engagement (scroll or time on page), outbound (outbound link click) or download (file download)","enum":["page","event","engagement","outbound","download"]},"match_type":{"type":"string","description":"How pattern matches the path (page, engagement), link domain (outbound) or file (download): exact, prefix, glob (*) or regex","enum":["exact","prefix","glob","regex"]},"pattern":{"type":"string","description":"A path for page and engagement goals (/pricing, /blog/*), a link domain for outbound (stripe.com) or a file name for download (*.pdf). Read according to match_type"},"hostname":{"type":"string","description":"Page goals only. Count the page only on this hostname. Send an empty string to clear it"},"event_name":{"type":"string","description":"Event goals only. The custom event name, for example Signup"},"conditions":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Event goals only. Replaces ALL conditions. Property tests that must ALL match: [{\"key\": \"plan\", \"operator\": \"is|is_not|contains|gt|lt\", \"value\": \"pro\"}]. Send an empty list to remove them"},"scroll_threshold":{"type":"integer","description":"Engagement goals only. Percent of the page scrolled, 1 to 100. The goal is met when this OR time_threshold_seconds is reached"},"time_threshold_seconds":{"type":"integer","description":"Engagement goals only. Seconds of engaged time on the page. The goal is met when this OR scroll_threshold is reached"},"value_mode":{"type":"string","description":"none, fixed (fixed_value per conversion) or revenue (the event revenue)","enum":["none","fixed","revenue"]},"fixed_value":{"type":"number","description":"Used when value_mode is fixed. A decimal amount in the site currency (major units, for example 49.5), stored as fixed_value_minor in cents"},"count_mode":{"type":"string","description":"Value counts once_per_visit or every completion","enum":["once_per_visit","every"]}}}}}}}},"/sites/{site_id}/goals/{id}/duplicate.json":{"post":{"operationId":"goals_duplicate","summary":"Copy a goal","description":"Copies a goal's definition into a new active goal. The copy is named name if you send it, otherwise the original name followed by (copy). It counts toward the plan's goal limit (10 active goals per site on Free). Returns the new goal with a new id. Use it to start a variation of a goal, then change it with goals_update. Needs the content.write permission.","tags":["Goals"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by goals_list","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Goal id, e.g. goal_7Q2K9XH3AB"},"name":{"type":"string"},"kind":{"type":"string","description":"page, event, engagement, outbound or download"},"match_type":{"type":"string","description":"exact, prefix, glob or regex"},"pattern":{"anyOf":[{"type":"string","description":"Path, domain or file pattern"},{"type":"null"}]},"hostname":{"anyOf":[{"type":"string","description":"Hostname restriction (page goals)"},{"type":"null"}]},"event_name":{"anyOf":[{"type":"string","description":"Custom event name (event goals)"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Event property conditions"},"scroll_threshold":{"anyOf":[{"type":"integer","description":"Engagement: scroll %"},{"type":"null"}]},"time_threshold_seconds":{"anyOf":[{"type":"integer","description":"Engagement: seconds on page"},{"type":"null"}]},"value_mode":{"type":"string","description":"none, fixed or revenue"},"fixed_value_minor":{"anyOf":[{"type":"integer","description":"Fixed value in minor units"},{"type":"null"}]},"count_mode":{"type":"string","description":"once_per_visit or every"},"archived":{"type":"boolean"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"completions":{"type":"integer","description":"Matching events, repeats included"},"conversions":{"type":"integer","description":"Visits with at least one completion"},"conversion_rate":{"type":"number","description":"Conversions ÷ visits (or ÷ visitors, per site setting), %"},"value":{"type":"integer","description":"Goal value in site currency minor units"},"change":{"anyOf":[{"type":"number","description":"Conversions change vs the previous period, %"},{"type":"null"}]}},"description":"Period stats (list only)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"goals_duplicate","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Name for the copy, up to 120 characters. Defaults to the original name followed by (copy)"}}}}}}}},"/sites/{site_id}/goals/{id}/unarchive.json":{"post":{"operationId":"goals_unarchive","summary":"Restore an archived goal","description":"Restores an archived goal so it shows in reports again. It counts toward the plan's goal limit again (10 active goals per site on Free), so the call fails with a plan limit error when the site is already full. Restoring a goal that is not archived does nothing. Returns the goal with archived false. Ids come from goals_list with status archived. Needs the content.write permission.","tags":["Goals"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by goals_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Goal id, e.g. goal_7Q2K9XH3AB"},"name":{"type":"string"},"kind":{"type":"string","description":"page, event, engagement, outbound or download"},"match_type":{"type":"string","description":"exact, prefix, glob or regex"},"pattern":{"anyOf":[{"type":"string","description":"Path, domain or file pattern"},{"type":"null"}]},"hostname":{"anyOf":[{"type":"string","description":"Hostname restriction (page goals)"},{"type":"null"}]},"event_name":{"anyOf":[{"type":"string","description":"Custom event name (event goals)"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Event property conditions"},"scroll_threshold":{"anyOf":[{"type":"integer","description":"Engagement: scroll %"},{"type":"null"}]},"time_threshold_seconds":{"anyOf":[{"type":"integer","description":"Engagement: seconds on page"},{"type":"null"}]},"value_mode":{"type":"string","description":"none, fixed or revenue"},"fixed_value_minor":{"anyOf":[{"type":"integer","description":"Fixed value in minor units"},{"type":"null"}]},"count_mode":{"type":"string","description":"once_per_visit or every"},"archived":{"type":"boolean"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"completions":{"type":"integer","description":"Matching events, repeats included"},"conversions":{"type":"integer","description":"Visits with at least one completion"},"conversion_rate":{"type":"number","description":"Conversions ÷ visits (or ÷ visitors, per site setting), %"},"value":{"type":"integer","description":"Goal value in site currency minor units"},"change":{"anyOf":[{"type":"number","description":"Conversions change vs the previous period, %"},{"type":"null"}]}},"description":"Period stats (list only)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"goals_unarchive","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/help.json":{"post":{"operationId":"support_message_send","summary":"Send a question or feedback to the Privatus Analytics team","description":"The message is emailed to the team with your account, workspace and plan details attached. The reply and a receipt go to your account email. Up to 10 messages a day.","tags":["Help and feedback"],"parameters":[],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"received":{"type":"boolean","description":"Always true when the submission was accepted"},"message":{"type":"string","description":"What happens next"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"support_message_send","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"subject":{"type":"string","description":"What the message is about (up to 150 characters)","examples":["Funnel shows no data"]},"message":{"type":"string","description":"Your question or feedback (10 to 5,000 characters)"}},"required":["subject","message"]}}}}}},"/sites/{site_id}/imports/google/connection.json":{"delete":{"operationId":"imports_google_disconnect","summary":"Disconnect your Google Analytics account and delete its stored access tokens","description":"Removes the stored Google Analytics connection of the calling member for this site's workspace, so GA4 imports can no longer read from Google until it is connected again in the app. Data that was already imported stays and is removed only by deleting its import with imports_delete. The grant is not revoked on the Google side. It fails with a validation error when there is no connection, or while one of the member's GA4 imports is queued or running. Returns an object with disconnected true. Connecting is done in the app (the Google sign in screen), there is no tool for it.","tags":["Imports"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"imports_google_disconnect","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/imports/google/properties.json":{"get":{"operationId":"imports_google_properties","summary":"List Google Analytics 4 properties to import","description":"Lists the Google Analytics 4 properties the calling member's connected Google account can read. Call it before imports_create with source ga4 to get the property_id to use. Returns a list of objects with id (like properties/123456789, pass it as property_id), name and account. It fails with a validation error when the member has not connected Google for this workspace (done in the app, there is no tool for it) or when Google rejects the request. It makes a live call to Google and changes nothing.","tags":["Imports"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"imports_google_properties","x-permission":"sites.manage"}},"/sites/{site_id}/imports.json":{"post":{"operationId":"imports_create","summary":"Start an import (GA4 property or CSV upload)","description":"Starts an import of historical data from another analytics tool into a site, processed in the background, and returns the import with status queued. Choose source ga4 to pull from the Google Analytics 4 API, which needs a Google connection made in the app, property_id (from imports_google_properties) and date_from. date_to defaults to the day before the site's first tracked event, or yesterday. Other sources (universal_analytics, fathom, simple_analytics, plausible, matomo, umami, clicky) take a CSV export uploaded as the file input (multipart form upload, up to 50 MB), which makes them impractical to start over MCP and best done in the app. dimension is only needed to override detection of what the CSV rows break down, for example Matomo Label exports. Imported rows never count toward the event allowance and only appear in stats when you pass include_imported true. A workspace can have at most 5 imports queued or running at once. Poll imports_get until status is complete or failed. Needs the sites.manage permission.","tags":["Imports"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Import id"},"site_id":{"type":"string"},"source":{"type":"string","description":"ga4, universal_analytics, fathom, simple_analytics, plausible, matomo, umami or clicky"},"status":{"type":"string","description":"queued, running, complete or failed"},"date_from":{"anyOf":[{"type":"string","format":"date","description":"First imported day"},{"type":"null"}]},"date_to":{"anyOf":[{"type":"string","format":"date","description":"Last imported day"},{"type":"null"}]},"rows_imported":{"type":"integer","description":"Daily rows stored"},"error":{"anyOf":[{"type":"string","description":"Why the import failed"},{"type":"null"}]},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"imports_create","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"string","description":"Where the data comes from. ga4 reads the Google Analytics 4 API through your Google connection. The others take an uploaded CSV export of that tool: universal_analytics, fathom, simple_analytics, plausible, matomo, umami or clicky","enum":["ga4","universal_analytics","fathom","simple_analytics","plausible","matomo","umami","clicky"]},"property_id":{"type":"string","description":"GA4 property, like properties/123456789 or just 123456789 (from imports_google_properties). Required for ga4, ignored for CSV sources","examples":["properties/123456789"]},"date_from":{"type":"string","format":"date","description":"First day to import, YYYY-MM-DD. Required for ga4. For CSV files with no date column every row gets this date"},"date_to":{"type":"string","format":"date","description":"Last day to import, YYYY-MM-DD, on or after date_from. For ga4 it defaults to the day before the site's first tracked event, or yesterday when there is none"},"file":{"type":"string","format":"binary","description":"CSV file sent as a multipart upload, up to 50 MB. Required for every source except ga4"},"dimension":{"type":"string","description":"Override what the CSV rows break down: total, page, source, country, device, browser or os. Only needed when it cannot be detected, such as Matomo Label exports","enum":["total","page","source","country","device","browser","os"]}},"required":["source"]}}}}},"get":{"operationId":"imports_list","summary":"List imports for a site","description":"Lists the imports of a site, newest first. Use it to find an import id or check whether one is still running. Optionally filter by status (queued, running, complete or failed). Paginated with page and per_page (up to 100). Each item has id, site_id, source, status, date_from, date_to, rows_imported, error, completed_at and created_at. See imports_get for details and imports_create to start one.","tags":["Imports"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Only imports with this status","enum":["queued","running","complete","failed"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Import id"},"site_id":{"type":"string"},"source":{"type":"string","description":"ga4, universal_analytics, fathom, simple_analytics, plausible, matomo, umami or clicky"},"status":{"type":"string","description":"queued, running, complete or failed"},"date_from":{"anyOf":[{"type":"string","format":"date","description":"First imported day"},{"type":"null"}]},"date_to":{"anyOf":[{"type":"string","format":"date","description":"Last imported day"},{"type":"null"}]},"rows_imported":{"type":"integer","description":"Daily rows stored"},"error":{"anyOf":[{"type":"string","description":"Why the import failed"},{"type":"null"}]},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"imports_list","x-permission":"analytics.read"}},"/sites/{site_id}/imports/{id}.json":{"delete":{"operationId":"imports_delete","summary":"Delete an import and all its imported data","description":"Permanently deletes an import together with every row it brought in and its uploaded file. Stats that included the imported data change right away when include_imported is on, and this cannot be undone, although you can import again. The id comes from imports_list and needs the site_id. Returns the deleted import. Needs the sites.manage permission. Data collected by the tracker is not touched.","tags":["Imports"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by imports_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Import id"},"site_id":{"type":"string"},"source":{"type":"string","description":"ga4, universal_analytics, fathom, simple_analytics, plausible, matomo, umami or clicky"},"status":{"type":"string","description":"queued, running, complete or failed"},"date_from":{"anyOf":[{"type":"string","format":"date","description":"First imported day"},{"type":"null"}]},"date_to":{"anyOf":[{"type":"string","format":"date","description":"Last imported day"},{"type":"null"}]},"rows_imported":{"type":"integer","description":"Daily rows stored"},"error":{"anyOf":[{"type":"string","description":"Why the import failed"},{"type":"null"}]},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"imports_get","summary":"Get an import and its status","description":"Returns one import of a site, used to poll an import started with imports_create. Fields are id (imp_...), site_id, source, status (queued, running, complete or failed), date_from and date_to (YYYY-MM-DD, null when unknown), rows_imported (count of imported daily rows), error (set when failed), completed_at and created_at. The id comes from imports_create or imports_list. Imported rows only show in stats when the stats call sets include_imported true.","tags":["Imports"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by imports_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Import id"},"site_id":{"type":"string"},"source":{"type":"string","description":"ga4, universal_analytics, fathom, simple_analytics, plausible, matomo, umami or clicky"},"status":{"type":"string","description":"queued, running, complete or failed"},"date_from":{"anyOf":[{"type":"string","format":"date","description":"First imported day"},{"type":"null"}]},"date_to":{"anyOf":[{"type":"string","format":"date","description":"Last imported day"},{"type":"null"}]},"rows_imported":{"type":"integer","description":"Daily rows stored"},"error":{"anyOf":[{"type":"string","description":"Why the import failed"},{"type":"null"}]},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"imports_get","x-permission":"analytics.read"}},"/sites/{site_id}/live.json":{"get":{"operationId":"live_get","summary":"Live visitors, activity stream and what is popular right now (last 30 minutes)","description":"What is happening on the site right now. Returns live_visitors (visitors in the last 5 minutes), window_minutes (30), sparkline (visits per minute for the last 30 minutes, oldest first, each {minute, visits}), feed (the latest activity), top_pages, top_referrers, top_countries (each up to 8 rows of {value, visits}), countries (every country with a visit, same shape, for the map) and top_events (up to 8 of {value, completions}) for the last 30 minutes. feed entries have occurred_at, kind, name, path, channel, referrer_host, country, device and browser. They are anonymous, with no IP, city or visitor trail. feed shows all hits by default, or only pageviews or events, with limit entries (default 50, up to the buffer size of 100). The numbers are not cached and take no period. Pass filters (same format as stats_aggregate) to narrow every number and the feed to the matching hits. Use live_wallboard for a compact multi-site view and stats_overview for a full period.","tags":["Live"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"feed","in":"query","required":false,"schema":{"type":"string","description":"Which hits to put in the activity feed: all (default), pageviews or events","enum":["all","pageviews","events"],"default":"all"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Feed entries to return, 1 to 100. Default 50","default":50}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match, in the same format as the stats tools: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Every number and the feed then cover only the matching hits. Empty means no filter","default":[]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"live_get","x-permission":"analytics.read"}},"/sites/{site_id}/live/wallboard.json":{"get":{"operationId":"live_wallboard","summary":"Wallboard cards (live and today) for one or more sites","description":"Compact big-number cards for one or more sites, built for an office screen. Returns rotate_seconds, generated_at and sites. Each site card has id (pa_...), name, domain, live_visitors (last 5 minutes), sparkline (per minute, last 30 minutes), visitors_today, pageviews_today, bounce_rate_today (percent, 0 to 100), top_pages, top_countries and top_referrers (5 rows each). Today means the site's own time zone and the numbers are read from live data. site_ids lists the sites to include (up to 12, only sites your token can open), otherwise the site in the path is used. rotate_seconds is clamped between 5 and 300 and only tells a screen how long to show each card. For a shareable public screen use wallboard_links_create. Use live_get for the full live view of one site.","tags":["Live"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"site_ids","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Site ids (pa_...) to include, up to 12, from sites you can open. Leave empty to use the site in the path","default":[]}},{"name":"rotate_seconds","in":"query","required":false,"schema":{"type":"integer","description":"Seconds a screen should keep each site card, 5 to 300. Default 20. Only echoed back for display, values outside the range are clamped","default":20}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"live_wallboard","x-permission":"analytics.read"}},"/wallboard/{token}.json":{"get":{"operationId":"live_public_wallboard","summary":"Wallboard for a wallboard token (no login needed)","tags":["Live"],"parameters":[{"name":"token","in":"path","required":true,"description":"The token from the link's URL","schema":{"type":"string"}},{"name":"site_ids","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Site ids (pa_...) to include, up to 12, from sites you can open. Leave empty to use the site in the path","default":[]}},{"name":"rotate_seconds","in":"query","required":false,"schema":{"type":"integer","description":"Seconds a screen should keep each site card, 5 to 300. Default 20. Only echoed back for display, values outside the range are clamped","default":20}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/sites/{site_id}/live/wallboard/links.json":{"post":{"operationId":"wallboard_links_create","summary":"Create a wallboard link (read-only, revocable)","description":"Creates a read-only wallboard URL that anyone holding it can open without logging in, so share it only with people who should see these numbers. Path takes site_id and this site is always included. site_ids adds more sites to rotate through (pa_... ids you can access, up to 12 sites in total). rotate_seconds is how long each site stays on screen, from 5 to 300 (default 20, values outside are clamped). expires_at is an ISO 8601 date-time, or a plain YYYY-MM-DD date that means the end of that day in the site's timezone. The wallboard only shows live and today's aggregate numbers. Returns the link with its url. Revoke it with wallboard_links_delete.","tags":["Live"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Link id, e.g. shr_7Q2K9XH3AB"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"url":{"type":"string","description":"Open this on a TV. No login needed"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Sites shown, in rotation"},"site_verified":{"type":"boolean","description":"Whether at least one of the wallboard's sites is verified. The wallboard shows only verified sites and responds 404 with none"},"rotate_seconds":{"type":"integer"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"wallboard_links_create","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Label, e.g. Office TV"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Extra site ids (pa_..., from sites_list) to rotate through. The site in the path is always included. Up to 12 sites in total","default":[]},"rotate_seconds":{"type":"integer","description":"Seconds each site stays on screen when rotating, 5 to 300 (default 20)","default":20},"expires_at":{"type":"string","format":"date-time","description":"When the link stops working. An ISO 8601 date-time, or YYYY-MM-DD which means the end of that day in the site timezone. Leave out for no expiry"}}}}}}},"get":{"operationId":"wallboard_links_list","summary":"List wallboard links for a site","description":"Lists the wallboard links of a site (path takes site_id), newest first and including revoked ones. A wallboard link is a secret URL that shows live visitors and today's numbers on a TV without a login. Each has id (shr_...), name, url, site_ids (pa_... ids of the sites it rotates through), rotate_seconds, expires_at, revoked_at (set once revoked) and created_at. Callers limited to some sites only see links whose sites are all theirs. For the wallboard data itself use live_wallboard. Needs the sites.manage permission.","tags":["Live"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Link id, e.g. shr_7Q2K9XH3AB"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"url":{"type":"string","description":"Open this on a TV. No login needed"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Sites shown, in rotation"},"site_verified":{"type":"boolean","description":"Whether at least one of the wallboard's sites is verified. The wallboard shows only verified sites and responds 404 with none"},"rotate_seconds":{"type":"integer"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"wallboard_links_list","x-permission":"sites.manage"}},"/sites/{site_id}/live/wallboard/links/{id}.json":{"delete":{"operationId":"wallboard_links_delete","summary":"Revoke a wallboard link","description":"Revokes a wallboard link so TVs that show it stop updating and the URL stops working. This cannot be undone, create a new link instead. Revoking an already revoked link does nothing. The id (shr_...) comes from wallboard_links_list. Returns the link with revoked_at set.","tags":["Live"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by wallboard_links_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Link id, e.g. shr_7Q2K9XH3AB"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"url":{"type":"string","description":"Open this on a TV. No login needed"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Sites shown, in rotation"},"site_verified":{"type":"boolean","description":"Whether at least one of the wallboard's sites is verified. The wallboard shows only verified sites and responds 404 with none"},"rotate_seconds":{"type":"integer"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"wallboard_links_delete","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/workspaces/{workspace_id}/invitations.json":{"post":{"operationId":"invitations_create","summary":"Invite people by email","description":"Invites one or more people to a workspace by email and sends each an invitation email with a link that is valid for 14 days. emails is a list of up to 50 addresses (a comma, space or semicolon separated string also works in the app form) and addresses that are already members are skipped, but it is an error when all of them are members. Inviting an address that already has a pending invitation replaces that invitation and sends a new email. role is one of the roles in members_list (default viewer, owner cannot be invited). Use role custom together with custom_role_id (the id from roles_list, Business plan). By default access covers all sites including future ones. To limit access set all_sites to false and list site_ids as public site ids (pa_...). Pending invitations count toward the plan's member limit (Free allows 1 member, the owner) and the call fails when the limit would be exceeded. Invitation emails are rate limited. You cannot grant a role with more permissions or sites than your own. Requires members.manage. Returns the created invitations (see invitations_list for fields).","tags":["Members"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"role":{"type":"string"},"custom_role":{"anyOf":[{"type":"string"},{"type":"null"}]},"all_sites":{"type":"boolean"},"site_ids":{"type":"array","items":{"type":"string"}},"invited_by":{"anyOf":[{"type":"string"},{"type":"null"}]},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"members.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"emails":{"type":"array","items":{"type":"string"},"description":"Up to 50 email addresses to invite. Addresses that are already members are skipped."},"role":{"type":"string","description":"Role for the invited people, one of admin, editor, analyst, viewer, billing or custom. Default viewer. Use custom together with custom_role_id. Owner cannot be invited.","enum":["admin","editor","analyst","viewer","billing","custom"],"default":"viewer"},"custom_role_id":{"type":"string","description":"Id (uuid) of a custom role from roles_list. Required when role is custom (Business plan)."},"all_sites":{"type":"boolean","description":"true (default) gives access to every site including future ones. Set false to limit access to site_ids.","default":true},"site_ids":{"type":"array","items":{"type":"string"},"description":"Public site ids (pa_..., from sites_list) the invited people may access. Only used when all_sites is false.","default":[]}},"required":["emails"]}}}}},"get":{"operationId":"invitations_list","summary":"List pending invitations","description":"Lists the pending team invitations of a workspace, newest first and paginated. Accepted and revoked invitations are not listed (use members_list for people who joined), and expired ones stay until they are replaced or revoked. Requires members.manage. A caller limited to some sites only sees invitations within their reach. Each item has id (uuid, used by invitations_delete), email, role, custom_role (the custom role's name when role is custom, otherwise null), all_sites, site_ids (public site ids pa_..., empty when all_sites is true), invited_by (the inviter's email), expires_at and created_at.","tags":["Members"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"role":{"type":"string"},"custom_role":{"anyOf":[{"type":"string"},{"type":"null"}]},"all_sites":{"type":"boolean"},"site_ids":{"type":"array","items":{"type":"string"}},"invited_by":{"anyOf":[{"type":"string"},{"type":"null"}]},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"invitations_list","x-permission":"members.manage"}},"/workspaces/{workspace_id}/invitations/{id}.json":{"delete":{"operationId":"invitations_delete","summary":"Revoke a pending invitation","description":"Revokes a pending invitation so its link no longer works, and frees the seat it held. The deletion cannot be undone, invite the person again with invitations_create. Take the id (a uuid) from invitations_list. A caller limited to some sites can only revoke invitations that grant no more than their own sites. Requires members.manage. Returns the revoked invitation.","tags":["Members"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by invitations_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"role":{"type":"string"},"custom_role":{"anyOf":[{"type":"string"},{"type":"null"}]},"all_sites":{"type":"boolean"},"site_ids":{"type":"array","items":{"type":"string"}},"invited_by":{"anyOf":[{"type":"string"},{"type":"null"}]},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"members.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/workspaces/{workspace_id}/members/{id}.json":{"delete":{"operationId":"members_delete","summary":"Remove a member (or leave the workspace)","description":"Removes a member from a workspace, or lets the caller leave it when the id is their own membership. This is immediate and cannot be undone, the person loses access, their API tokens for this workspace are revoked and any SCIM link is removed. Their notes and past audit entries stay. The owner cannot be removed or leave, transfer ownership first with ownership_transfers_create. Removing someone else needs members.manage, and you cannot remove someone with more permissions or sites than you hold. Leaving needs no permission but a token that is limited in permissions or sites cannot be used to leave. The person can be invited again later with invitations_create. Take the id (the membership uuid) from members_list. Returns the removed member.","tags":["Members"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by members_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Member id (use it to update or remove the member)"},"email":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"role":{"type":"string","description":"owner, admin, editor, analyst, viewer, billing or custom"},"custom_role":{"anyOf":[{"type":"string","description":"Custom role name"},{"type":"null"}]},"custom_role_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"all_sites":{"type":"boolean","description":"Access to all sites"},"include_future_sites":{"type":"boolean"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Site ids when all_sites is false"},"two_factor":{"type":"boolean","description":"Has 2FA or a passkey"},"last_active_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"Joined at"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"patch":{"operationId":"members_update","summary":"Change a member's role or site access","description":"Changes a member's role and or site access in a workspace. Only the inputs you send change. To change the role send role (admin, editor, analyst, viewer or billing, and custom with custom_role_id from roles_list on the Business plan). The owner's role cannot be changed here, use ownership_transfers_create instead, and you cannot edit your own membership or someone who outranks you. To limit sites send all_sites false together with site_ids (public site ids pa_...), and add include_future_sites true to also grant sites created later. Send all_sites true to give access to every site. A site_ids list sent without all_sites false is an error for a member who currently has every site. You cannot grant more permissions or sites than you hold. Requires members.manage. Take the id from members_list. Returns the updated member.","tags":["Members"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by members_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Member id (use it to update or remove the member)"},"email":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"role":{"type":"string","description":"owner, admin, editor, analyst, viewer, billing or custom"},"custom_role":{"anyOf":[{"type":"string","description":"Custom role name"},{"type":"null"}]},"custom_role_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"all_sites":{"type":"boolean","description":"Access to all sites"},"include_future_sites":{"type":"boolean"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Site ids when all_sites is false"},"two_factor":{"type":"boolean","description":"Has 2FA or a passkey"},"last_active_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"Joined at"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"members.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","description":"New role, one of admin, editor, analyst, viewer, billing or custom. Use custom together with custom_role_id. The owner role cannot be set here, use ownership_transfers_create.","enum":["admin","editor","analyst","viewer","billing","custom"]},"custom_role_id":{"type":"string","description":"Id (uuid) of a custom role from roles_list. Required when role is custom (Business plan)."},"all_sites":{"type":"boolean","description":"true gives access to every site. false limits access to site_ids. Omit to leave site access as it is."},"site_ids":{"type":"array","items":{"type":"string"},"description":"Public site ids (pa_..., from sites_list) the member may access. Replaces the whole current list. Only used when the member is limited to some sites (send all_sites false)."},"include_future_sites":{"type":"boolean","description":"true also grants sites created later. Only meaningful for a member limited to some sites. Setting all_sites to false without this resets it to false."}}}}}}}},"/workspaces/{workspace_id}/members.json":{"get":{"operationId":"members_list","summary":"List workspace members","description":"Lists the members of a workspace in the order they joined, paginated. Use query to search by name or email (partial, case-insensitive) and role to filter by role. Pending invitations are not included (use invitations_list). Each member has id (the membership uuid, used by members_update, members_delete and ownership_transfers_create), email, name (nullable), role, custom_role (name, null unless role is custom), custom_role_id, all_sites, include_future_sites, site_ids (public site ids pa_..., empty when all_sites is true), two_factor (whether the member has an authenticator app or a passkey), last_active_at (nullable) and created_at. Callers limited to some sites see only members within their reach.","tags":["Members"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Partial, case-insensitive match on the member's name or email."}},{"name":"role","in":"query","required":false,"schema":{"type":"string","description":"Only members with this role, one of owner, admin, editor, analyst, viewer, billing or custom.","enum":["owner","admin","editor","analyst","viewer","billing","custom"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Member id (use it to update or remove the member)"},"email":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"role":{"type":"string","description":"owner, admin, editor, analyst, viewer, billing or custom"},"custom_role":{"anyOf":[{"type":"string","description":"Custom role name"},{"type":"null"}]},"custom_role_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"all_sites":{"type":"boolean","description":"Access to all sites"},"include_future_sites":{"type":"boolean"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Site ids when all_sites is false"},"two_factor":{"type":"boolean","description":"Has 2FA or a passkey"},"last_active_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"Joined at"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"members_list"}},"/workspaces/{workspace_id}/ownership_transfer.json":{"post":{"operationId":"ownership_transfers_create","summary":"Transfer workspace ownership to another member (owner only, you become an admin)","description":"Transfers ownership of a workspace to another member and demotes the caller to admin, which is hard to undo because only the new owner can transfer it back. Only the current owner can call it, and a token must not be limited to certain sites or permissions. membership_id is the new owner's membership uuid from members_list (not a user id or email) and the person must already be a member, invite them first if they are not. The new owner gets role owner with access to all sites, and the owner role cannot be given through members_update. A Free workspace cannot be given to someone who already owns another Free workspace. Billing stays with the workspace. A token calling this needs members.manage. Returns the new owner's member record.","tags":["Members"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Member id (use it to update or remove the member)"},"email":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"role":{"type":"string","description":"owner, admin, editor, analyst, viewer, billing or custom"},"custom_role":{"anyOf":[{"type":"string","description":"Custom role name"},{"type":"null"}]},"custom_role_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"all_sites":{"type":"boolean","description":"Access to all sites"},"include_future_sites":{"type":"boolean"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Site ids when all_sites is false"},"two_factor":{"type":"boolean","description":"Has 2FA or a passkey"},"last_active_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"Joined at"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-token-permission":"members.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"membership_id":{"type":"string","description":"Membership id (uuid) of the member who becomes owner, from members_list. It is not a user id or an email."}},"required":["membership_id"]}}}}}},"/workspaces/{workspace_id}/app.json":{"get":{"operationId":"mobile_bootstraps_get","summary":"Get what the mobile app needs to open a workspace","description":"Returns, for one workspace (path takes workspace_id), the caller's role and permissions there, features (which gated reports the plan includes: traffic_quality, bot_detection, external_experiments, campaign_costs, status_pages, traffic_rules, experiment_advanced (the advanced settings of an experiment) and survey_ai_themes (themes for the written answers of a survey) as true or false, and retention_months as a number of months or null for no limit), testimonial_moderation (true when the member's role lets the mobile app approve, reject and return a testimonial to pending), sites_count (the sites the caller can open) and min_app_version (the oldest version of the mobile app the API still serves). The mobile app reads it once when it opens a workspace, so it can show a report the plan lacks as not included instead of asking for it. Needs analytics.read.","tags":["Mobile app"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"workspace_id":{"type":"string","description":"Workspace id (ws_...)"},"name":{"type":"string"},"timezone":{"type":"string"},"currency":{"type":"string"},"role":{"type":"string","description":"The caller's role in the workspace"},"permissions":{"type":"array","items":{"type":"string"},"description":"The permissions this token has in the workspace"},"features":{"type":"object","description":"Which gated reports the plan includes: traffic_quality, bot_detection, external_experiments, campaign_costs, status_pages, traffic_rules, experiment_advanced, survey_ai_themes (true or false) and retention_months (months of history, or null for no limit)"},"testimonial_moderation":{"type":"boolean","description":"Whether the member's role lets the mobile app approve, reject and return a testimonial to pending (the role holds content.write)"},"sites_count":{"type":"integer","description":"Sites the caller can open"},"min_app_version":{"type":"string","description":"The oldest version of the mobile app the API still serves"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"analytics.read"}},"/account/device.json":{"delete":{"operationId":"mobile_devices_delete","summary":"Stop push notifications to the mobile app","description":"Removes the push registration of the calling mobile app login, so the device gets no more pushes. The login itself stays, and the app can register again. Logging out (POST /oauth/revoke with the refresh token) removes it too. Only a token of the mobile app can call it.","tags":["Mobile app"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"registered":{"type":"boolean","description":"False until the app registered a push token"},"platform":{"anyOf":[{"type":"string","description":"ios or android"},{"type":"null"}]},"locale":{"type":"string","description":"The language pushes are written in"},"timezone":{"anyOf":[{"type":"string","description":"The device's time zone"},{"type":"null"}]},"app_version":{"anyOf":[{"type":"string","description":"The app's version at its last registration"},{"type":"null"}]},"kinds":{"type":"array","items":{"type":"string"},"description":"Every kind of push there is"},"muted_kinds":{"type":"array","items":{"type":"string"},"description":"Kinds the person switched off"},"muted_site_ids":{"type":"array","items":{"type":"string"},"description":"Sites (pa_...) the person switched off"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"mobile_devices_get","summary":"Get the mobile app's push registration","description":"Returns the device of the mobile app login that is calling: registered (false until the app registered a push token), platform, locale, timezone, app_version, kinds (every kind of push there is), muted_kinds and muted_site_ids (what the person switched off). Only a token of the mobile app can call it.","tags":["Mobile app"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"registered":{"type":"boolean","description":"False until the app registered a push token"},"platform":{"anyOf":[{"type":"string","description":"ios or android"},{"type":"null"}]},"locale":{"type":"string","description":"The language pushes are written in"},"timezone":{"anyOf":[{"type":"string","description":"The device's time zone"},{"type":"null"}]},"app_version":{"anyOf":[{"type":"string","description":"The app's version at its last registration"},{"type":"null"}]},"kinds":{"type":"array","items":{"type":"string"},"description":"Every kind of push there is"},"muted_kinds":{"type":"array","items":{"type":"string"},"description":"Kinds the person switched off"},"muted_site_ids":{"type":"array","items":{"type":"string"},"description":"Sites (pa_...) the person switched off"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"mobile_devices_update","summary":"Register the mobile app for push notifications","description":"Registers the device of the calling mobile app login for push notifications, or changes what it gets. Only the inputs you send change. The first call needs platform and push_token. A device gets a push for uptime (a check went down or came back), alert (an alert triggered or resolved), site_audit (a site audit finished), experiment (an experiment has a result or ended) and usage (the monthly allowance is nearly or fully used), for every site its member can open, on every plan. muted_kinds and muted_site_ids switch kinds and sites off, and each replaces its whole list. Registering a push token that another login of the app holds moves it to this one. Only a token of the mobile app can call it. It is one of the two writes such a token may make.","tags":["Mobile app"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"registered":{"type":"boolean","description":"False until the app registered a push token"},"platform":{"anyOf":[{"type":"string","description":"ios or android"},{"type":"null"}]},"locale":{"type":"string","description":"The language pushes are written in"},"timezone":{"anyOf":[{"type":"string","description":"The device's time zone"},{"type":"null"}]},"app_version":{"anyOf":[{"type":"string","description":"The app's version at its last registration"},{"type":"null"}]},"kinds":{"type":"array","items":{"type":"string"},"description":"Every kind of push there is"},"muted_kinds":{"type":"array","items":{"type":"string"},"description":"Kinds the person switched off"},"muted_site_ids":{"type":"array","items":{"type":"string"},"description":"Sites (pa_...) the person switched off"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"platform":{"type":"string","description":"ios or android. Needed the first time."},"push_token":{"type":"string","description":"The push token the operating system gave the app: the APNs device token (hex) on ios, the FCM registration token on android. Needed the first time, and again whenever it changes."},"apns_environment":{"type":"string","description":"ios only: production or sandbox (a development build). Default production."},"locale":{"type":"string","description":"The app's language, for the text of a push, such as en, de or pt-BR. A language we have no translation for gets English."},"timezone":{"type":"string","description":"The device's time zone, such as Europe/Berlin."},"app_version":{"type":"string","description":"The app's version, such as 1.2.0."},"muted_kinds":{"type":"array","items":{"type":"string"},"description":"Kinds of push to switch off, any of uptime, alert, site_audit, experiment and usage. Replaces the current list. Send an empty list to switch every kind on."},"muted_site_ids":{"type":"array","items":{"type":"string"},"description":"Sites (pa_...) to get no push for. Replaces the current list. Each must be a site of a workspace you belong to."}}}}}}}},"/sites/{site_id}/notes.json":{"post":{"operationId":"notes_create","summary":"Add a note to a site (use source \"deploy\" for release webhooks)","description":"Adds an annotation to one site's charts, for example a launch, a campaign or a release. Use workspace_notes_create instead for a note that shows on every site. date defaults to today in the site's timezone, and end_date marks a range (YYYY-MM-DD). title is shown on the chart, body is plain text and url can point to a PR or changelog. color is one of neutral, brand, blue, amber, red or violet, default neutral. source is manual by default. Deploy integrations send source deploy, and then title defaults to a text built from version (a release version or commit) and color defaults to blue. Requires content.write. Returns the created note (see notes_list for fields).","tags":["Notes"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Note id, e.g. note_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site, or null for workspace-wide notes"},{"type":"null"}]},"date":{"type":"string","format":"date"},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"title":{"type":"string"},"body":{"anyOf":[{"type":"string","description":"Markdown"},{"type":"null"}]},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"color":{"type":"string","description":"neutral, brand, blue, amber, red, violet"},"source":{"type":"string","description":"manual, deploy, system, import, incident"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"notes_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"date":{"type":"string","format":"date","description":"Day of the note, YYYY-MM-DD in the site's timezone. Defaults to today."},"end_date":{"type":"string","format":"date","description":"Last day when the note covers a range, YYYY-MM-DD. Omit for a single day."},"title":{"type":"string","description":"Short title shown on the chart. Defaults to a generated text for deploy notes.","examples":["Launched new pricing"]},"body":{"type":"string","description":"Longer details as plain text."},"url":{"type":"string","description":"A link such as a pull request or changelog page."},"color":{"type":"string","description":"Pin color, one of neutral, brand, blue, amber, red or violet. Defaults to neutral (blue for deploy notes).","enum":["neutral","brand","blue","amber","red","violet"]},"source":{"type":"string","description":"manual (default) for notes written by a person, or deploy for release notifications. system, import and incident are reserved for notes the app writes itself.","enum":["manual","deploy","system","import","incident"],"default":"manual"},"version":{"type":"string","description":"Only used when source is deploy and title is empty. A release version or commit, used to build the default title."}}}}}}},"get":{"operationId":"notes_list","summary":"List notes for a site (including workspace-wide notes)","description":"Lists the annotations (notes) shown on a site's charts, newest date first and paginated. It returns the site's own notes plus workspace-wide notes that apply to every site. Filter with from and to (YYYY-MM-DD, a note matches when its date falls in the range), source (manual, deploy, system, import or incident) and query (a case-insensitive search of title, body and url). Use workspace_notes_list for the workspace view across all sites. Each note has id (note_...), site_id (the public site id pa_..., null for a workspace-wide note), date, end_date (null for a single day), title, body (nullable plain text), url (nullable), color (neutral, brand, blue, amber, red or violet), source and created_at. Requires analytics.read.","tags":["Notes"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Only notes whose date is on or after this day, YYYY-MM-DD."}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Only notes whose date is on or before this day, YYYY-MM-DD."}},{"name":"source","in":"query","required":false,"schema":{"type":"string","description":"Only notes from this source, one of manual, deploy, system, import or incident.","enum":["manual","deploy","system","import","incident"]}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Case-insensitive text search across title, body and link."}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Note id, e.g. note_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site, or null for workspace-wide notes"},{"type":"null"}]},"date":{"type":"string","format":"date"},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"title":{"type":"string"},"body":{"anyOf":[{"type":"string","description":"Markdown"},{"type":"null"}]},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"color":{"type":"string","description":"neutral, brand, blue, amber, red, violet"},"source":{"type":"string","description":"manual, deploy, system, import, incident"},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"notes_list","x-permission":"analytics.read"}},"/sites/{site_id}/notes/{id}.json":{"delete":{"operationId":"notes_delete","summary":"Delete a note","description":"Permanently deletes a site note, which disappears from the charts and cannot be restored. The note must belong to this site, workspace-wide notes are deleted with workspace_notes_delete. Take the id (note_...) from notes_list. Requires content.write. Returns the deleted note.","tags":["Notes"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by notes_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Note id, e.g. note_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site, or null for workspace-wide notes"},{"type":"null"}]},"date":{"type":"string","format":"date"},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"title":{"type":"string"},"body":{"anyOf":[{"type":"string","description":"Markdown"},{"type":"null"}]},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"color":{"type":"string","description":"neutral, brand, blue, amber, red, violet"},"source":{"type":"string","description":"manual, deploy, system, import, incident"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"notes_delete","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"notes_get","summary":"Get a note","description":"Returns one note by its id (note_..., from notes_list) for a site, including workspace-wide notes that apply to the site. A note is a dated annotation shown on charts, for example a launch, a campaign or a deploy. Fields are id, site_id (null when workspace-wide), date and end_date (YYYY-MM-DD, end_date null for a single day), title, body (nullable), url (nullable), color (neutral, brand, blue, amber, red or violet), source (manual, deploy, system, import or incident) and created_at. Requires analytics.read.","tags":["Notes"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by notes_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Note id, e.g. note_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site, or null for workspace-wide notes"},{"type":"null"}]},"date":{"type":"string","format":"date"},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"title":{"type":"string"},"body":{"anyOf":[{"type":"string","description":"Markdown"},{"type":"null"}]},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"color":{"type":"string","description":"neutral, brand, blue, amber, red, violet"},"source":{"type":"string","description":"manual, deploy, system, import, incident"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"notes_get","x-permission":"analytics.read"},"patch":{"operationId":"notes_update","summary":"Edit a note","description":"Edits a site note, changing only the fields you send (date, end_date, title, body, url, color). The source cannot be changed. Sending an empty url removes the link, and a date of null is ignored. The note must belong to this site, workspace-wide notes are edited with workspace_notes_update. Take the id (note_...) from notes_list. Requires content.write. Returns the updated note.","tags":["Notes"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by notes_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Note id, e.g. note_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site, or null for workspace-wide notes"},{"type":"null"}]},"date":{"type":"string","format":"date"},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"title":{"type":"string"},"body":{"anyOf":[{"type":"string","description":"Markdown"},{"type":"null"}]},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"color":{"type":"string","description":"neutral, brand, blue, amber, red, violet"},"source":{"type":"string","description":"manual, deploy, system, import, incident"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"notes_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"date":{"type":"string","format":"date","description":"New day of the note, YYYY-MM-DD. Null is ignored."},"end_date":{"type":"string","format":"date","description":"New last day for a range, YYYY-MM-DD."},"title":{"type":"string","description":"Short title shown on charts"},"body":{"type":"string","description":"Details (plain text)"},"url":{"type":"string","description":"New link. An empty string removes it."},"color":{"type":"string","description":"New pin color, one of neutral, brand, blue, amber, red or violet.","enum":["neutral","brand","blue","amber","red","violet"]}}}}}}}},"/workspaces/{workspace_id}/notes.json":{"post":{"operationId":"workspace_notes_create","summary":"Add a workspace-wide note (shown on every site)","description":"Adds a workspace-wide annotation that appears on the charts of every site in the workspace, for example a company-wide launch or an outage. It is created without a site (site_id is null). Use notes_create for a note on a single site. date defaults to today in the workspace's timezone, end_date marks a range (YYYY-MM-DD), color is one of neutral, brand, blue, amber, red or violet. Requires content.write, and a caller limited to some sites cannot create workspace-wide notes. Returns the created note.","tags":["Notes"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Note id, e.g. note_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site, or null for workspace-wide notes"},{"type":"null"}]},"date":{"type":"string","format":"date"},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"title":{"type":"string"},"body":{"anyOf":[{"type":"string","description":"Markdown"},{"type":"null"}]},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"color":{"type":"string","description":"neutral, brand, blue, amber, red, violet"},"source":{"type":"string","description":"manual, deploy, system, import, incident"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"workspace_notes_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"date":{"type":"string","format":"date","description":"Day of the note, YYYY-MM-DD in the site's timezone. Defaults to today."},"end_date":{"type":"string","format":"date","description":"Last day when the note covers a range, YYYY-MM-DD. Omit for a single day."},"title":{"type":"string","description":"Short title shown on the chart. Defaults to a generated text for deploy notes.","examples":["Launched new pricing"]},"body":{"type":"string","description":"Longer details as plain text."},"url":{"type":"string","description":"A link such as a pull request or changelog page."},"color":{"type":"string","description":"Pin color, one of neutral, brand, blue, amber, red or violet. Defaults to neutral (blue for deploy notes).","enum":["neutral","brand","blue","amber","red","violet"]},"source":{"type":"string","description":"manual (default) for notes written by a person, or deploy for release notifications. system, import and incident are reserved for notes the app writes itself.","enum":["manual","deploy","system","import","incident"],"default":"manual"},"version":{"type":"string","description":"Only used when source is deploy and title is empty. A release version or commit, used to build the default title."}}}}}}},"get":{"operationId":"workspace_notes_list","summary":"List notes across a workspace","description":"Lists the annotations across a workspace, newest date first and paginated. It returns workspace-wide notes (which show on every site) plus the notes of every site the caller can access, so check site_id on each item (null means workspace-wide). Use notes_list for one site. Filter with from and to (YYYY-MM-DD), source (manual, deploy, system, import or incident) and query (searches title, body and url). Fields are id (note_...), site_id, date, end_date, title, body, url, color (neutral, brand, blue, amber, red or violet), source and created_at. Requires analytics.read.","tags":["Notes"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Only notes whose date is on or after this day, YYYY-MM-DD."}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Only notes whose date is on or before this day, YYYY-MM-DD."}},{"name":"source","in":"query","required":false,"schema":{"type":"string","description":"Only notes from this source, one of manual, deploy, system, import or incident.","enum":["manual","deploy","system","import","incident"]}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Case-insensitive text search across title, body and link."}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Note id, e.g. note_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site, or null for workspace-wide notes"},{"type":"null"}]},"date":{"type":"string","format":"date"},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"title":{"type":"string"},"body":{"anyOf":[{"type":"string","description":"Markdown"},{"type":"null"}]},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"color":{"type":"string","description":"neutral, brand, blue, amber, red, violet"},"source":{"type":"string","description":"manual, deploy, system, import, incident"},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"workspace_notes_list","x-permission":"analytics.read"}},"/workspaces/{workspace_id}/notes/{id}.json":{"delete":{"operationId":"workspace_notes_delete","summary":"Delete a workspace note","description":"Permanently deletes a workspace-wide note so it disappears from every site's charts, and it cannot be restored. Only notes with no site can be deleted here, use notes_delete for a site note. Take the id (note_...) from workspace_notes_list. Requires content.write, and a caller limited to some sites cannot delete workspace-wide notes. Returns the deleted note.","tags":["Notes"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by workspace_notes_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Note id, e.g. note_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site, or null for workspace-wide notes"},{"type":"null"}]},"date":{"type":"string","format":"date"},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"title":{"type":"string"},"body":{"anyOf":[{"type":"string","description":"Markdown"},{"type":"null"}]},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"color":{"type":"string","description":"neutral, brand, blue, amber, red, violet"},"source":{"type":"string","description":"manual, deploy, system, import, incident"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"workspace_notes_delete","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"patch":{"operationId":"workspace_notes_update","summary":"Edit a workspace note","description":"Edits a workspace-wide note, changing only the fields you send (date, end_date, title, body, url, color). Only notes with no site can be edited here, use notes_update for a site note. Take the id (note_...) from workspace_notes_list. Requires content.write, and a caller limited to some sites cannot edit workspace-wide notes. Returns the updated note.","tags":["Notes"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by workspace_notes_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Note id, e.g. note_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site, or null for workspace-wide notes"},{"type":"null"}]},"date":{"type":"string","format":"date"},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"title":{"type":"string"},"body":{"anyOf":[{"type":"string","description":"Markdown"},{"type":"null"}]},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"color":{"type":"string","description":"neutral, brand, blue, amber, red, violet"},"source":{"type":"string","description":"manual, deploy, system, import, incident"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"workspace_notes_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"date":{"type":"string","format":"date","description":"New day of the note, YYYY-MM-DD. Null is ignored."},"end_date":{"type":"string","format":"date","description":"New last day for a range, YYYY-MM-DD."},"title":{"type":"string","description":"Short title shown on charts"},"body":{"type":"string","description":"Details (plain text)"},"url":{"type":"string","description":"New link. An empty string removes it."},"color":{"type":"string","description":"New pin color, one of neutral, brand, blue, amber, red or violet.","enum":["neutral","brand","blue","amber","red","violet"]}}}}}}}},"/channels/{id}.json":{"delete":{"operationId":"notification_channels_delete","summary":"Delete a notification channel","description":"Deletes a notification channel and removes it from every alert that used it, so those alerts stop notifying there. This cannot be undone and the alerts themselves are kept. The id (nch_...) comes from notification_channels_list. Returns the deleted channel.","tags":["Notification channels"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by notification_channels_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Channel id, e.g. nch_7Q2K9XH3AB"},"kind":{"type":"string","description":"email, slack, teams, discord, webhook, pagerduty, opsgenie or push"},"name":{"type":"string"},"target":{"type":"string","description":"Masked destination"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"notification_channels_delete","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"notification_channels_get","summary":"Get a notification channel","description":"Returns one notification channel by id (nch_..., from notification_channels_list). The response has kind, name, target (a masked summary, secrets such as webhook URLs and keys are never returned), last_used_at and created_at. Use notification_channels_send_test to check that it delivers.","tags":["Notification channels"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by notification_channels_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Channel id, e.g. nch_7Q2K9XH3AB"},"kind":{"type":"string","description":"email, slack, teams, discord, webhook, pagerduty, opsgenie or push"},"name":{"type":"string"},"target":{"type":"string","description":"Masked destination"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"notification_channels_get","x-permission":"analytics.read"}},"/workspaces/{workspace_id}/channels.json":{"get":{"operationId":"notification_channels_list","summary":"List notification channels","description":"Lists the notification channels of a workspace (path takes workspace_id), sorted by name and paginated. A channel is a place alerts are delivered to. Each has id (nch_...), kind (email, slack, teams, discord, webhook, pagerduty, opsgenie or push), name, target (a masked summary such as the email addresses or the end of a webhook URL, secrets are never returned), last_used_at and created_at. Filter by kind. Use the ids as channel_ids in alerts_create and alerts_update. Callers limited to some sites only see channels used by alerts on their sites.","tags":["Notification channels"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","description":"Only channels of this kind: email, slack, teams, discord, webhook, pagerduty, opsgenie or push","enum":["email","slack","teams","discord","webhook","pagerduty","opsgenie","push"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Channel id, e.g. nch_7Q2K9XH3AB"},"kind":{"type":"string","description":"email, slack, teams, discord, webhook, pagerduty, opsgenie or push"},"name":{"type":"string"},"target":{"type":"string","description":"Masked destination"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"notification_channels_list","x-permission":"analytics.read"}},"/channels/{id}/send_test.json":{"post":{"operationId":"notification_channels_send_test","summary":"Send a test message through a channel","description":"Sends a real test message through the channel (an email, a chat post, a webhook call and so on), so only use it when the user wants that. The call fails with an error naming the cause if delivery does not work, otherwise it returns the channel. Test sends are rate limited per workspace, and email channels also per outside address. Use it after notification_channels_create or notification_channels_update to confirm a URL or key is right.","tags":["Notification channels"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by notification_channels_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Channel id, e.g. nch_7Q2K9XH3AB"},"kind":{"type":"string","description":"email, slack, teams, discord, webhook, pagerduty, opsgenie or push"},"name":{"type":"string"},"target":{"type":"string","description":"Masked destination"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"notification_channels_send_test","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/notifications/unsubscribe/{token}.json":{"post":{"operationId":"notification_unsubscribes_create","summary":"Unsubscribe an address from one alert channel or uptime check with the token from an email","tags":["Notification channels"],"parameters":[{"name":"token","in":"path","required":true,"description":"The token from the unsubscribe link of an alert or uptime email","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"The token from the unsubscribe link of an alert or uptime email"}},"required":["token"]}}}},"security":[]}},"/push_subscription.json":{"post":{"operationId":"push_subscriptions_create","summary":"Register a browser for push notifications","description":"Registers the current browser for web push alerts, using the three values from the browser's PushSubscription (endpoint, p256dh and auth). A subscription receives alerts from every workspace the member belongs to, for every site, which is why an API token may only use this when it can read all of its workspace and the member has no other workspace. Calling it again with the same endpoint updates the keys and moves the subscription to the caller. The endpoint must be a public https push service URL. This only registers the browser, so alerts still need a notification channel of kind push (notification_channels_create). Returns endpoint_host (the push service's host name, not the full endpoint) and created_at. Sessions opened through a workspace identity provider cannot use it.","tags":["Notification channels"],"parameters":[],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"endpoint_host":{"type":"string","description":"Push service host"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"push_subscriptions_create","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"endpoint":{"type":"string","description":"PushSubscription.endpoint from the browser, a public https URL of the push service. Registering the same endpoint again updates its keys."},"p256dh":{"type":"string","description":"PushSubscription keys.p256dh (base64url)"},"auth":{"type":"string","description":"PushSubscription keys.auth (base64url)"}},"required":["endpoint","p256dh","auth"]}}}}},"delete":{"operationId":"push_subscriptions_delete","summary":"Remove a browser push registration","description":"Removes one of the signed-in member's browser push registrations so that browser stops receiving alert notifications. Pass the same endpoint that was used with push_subscriptions_create. Fails with not found when no such subscription exists for the member. Returns the removed subscription as endpoint_host and created_at. It does not delete any notification channel. Subject to the same token restrictions as push_subscriptions_create.","tags":["Notification channels"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"endpoint_host":{"type":"string","description":"Push service host"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"push_subscriptions_delete","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"endpoint":{"type":"string","description":"The same PushSubscription.endpoint that was registered. Not found if it was never registered for you."}},"required":["endpoint"]}}}}}},"/sites/{site_id}/performance.json":{"get":{"operationId":"performance_report","summary":"Web Vitals: p75 scorecard, daily trend and breakdowns by page, device, browser and country","description":"Web Vitals report from real visitors. Returns period, metric, sample_rate, scorecard, trend and breakdowns. scorecard has one row for each of LCP, INP, CLS, FCP and TTFB with p75 (the 75th percentile, in milliseconds except CLS, which is a unitless score), samples, rating (good, needs_improvement or poor, null with no data), good, needs_improvement and poor (percent of samples), previous_p75, change (percent against the earlier period, null when unknown), thresholds [good limit, poor limit] and benchmark ({low, median, high, sites}: the 25th, 50th and 75th percentile of the p75 of all sites on Privatus Analytics over 28 days, null when there is none or the workspace switched benchmarks off). trend is the daily p75 of the chosen metric as {date, p75, samples}. breakdowns has page, device, browser and country, each with up to limit rows (default 10, max 100) of the chosen metric as {value, p75, samples, rating, slow_share, poor}, worst and busiest first. Choose metric with exactly one of LCP, INP, CLS, FCP or TTFB in capital letters (default LCP). sample_rate is the share of visits that report vitals, so counts are samples and not all visits. Takes the shared period, compare, filters and segment inputs. For one page's vitals use pages_detail.","tags":["Performance"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"metric","in":"query","required":false,"schema":{"type":"string","description":"Web Vital for the trend and the breakdowns, in capital letters: LCP (default), INP, CLS, FCP or TTFB. The scorecard always lists all five","enum":["LCP","INP","CLS","FCP","TTFB"],"default":"LCP"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Rows per breakdown (page, device, browser, country), 1 to 100. Default 10","default":10}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"performance_report","x-permission":"analytics.read"}},"/plans.json":{"get":{"operationId":"plans_list","summary":"List plans, prices and limits","description":"Lists the public plans (free, pro, business and enterprise) with their limits and price tiers, so you can pick valid values for billing_checkout, billing_preview and billing_change_plan. Each plan has name, events (events a month included, null for tiered or custom plans), badge_bonus (extra monthly events from the badge, Free only, otherwise null), limits (an object of plan limits such as sites, member seats, history retention in months, goals per site, AI questions and API requests per hour), tiers (each with events a month and the monthly and yearly price in whole USD, including VAT or sales tax) and contact_sales (true for custom plans). The meta object adds currency, a note on yearly pricing, counted (what counts as a billable event) and not_counted. For one workspace's own plan use billing_get. Public, no authentication needed.","tags":["Plans"],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"free, pro, business or enterprise"},"events":{"anyOf":[{"type":"integer","description":"Included events a month (free plan only)"},{"type":"null"}]},"badge_bonus":{"anyOf":[{"type":"integer","description":"Extra events a month for showing the badge (free plan)"},{"type":"null"}]},"limits":{"type":"object","description":"Plan limits. Null means unlimited"},"tiers":{"type":"array","items":{"type":"object","properties":{"events":{"type":"integer","description":"Events a month included"},"monthly":{"type":"integer","description":"USD a month, billed monthly"},"yearly":{"type":"integer","description":"USD a year, billed yearly (2 months free)"},"monthly_price_id":{"anyOf":[{"type":"string","description":"Paddle price id (monthly)"},{"type":"null"}]},"yearly_price_id":{"anyOf":[{"type":"string","description":"Paddle price id (yearly)"},{"type":"null"}]}}},"description":"Price ladder by events a month"},"contact_sales":{"type":"boolean","description":"Priced per contract"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"plans_list","security":[]}},"/sites/{site_id}/testimonials/forms/{form_id}/feedback.json":{"get":{"operationId":"testimonial_feedback_list","summary":"List the private feedback of a form, newest first","description":"Private feedback is an answer with a rating of 1 to 3 on a form with low-rating routing on (Business and up). It is never a testimonial, never public and never counted.","tags":["Private feedback"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"form_id","in":"path","required":true,"description":"Form id (frm_...), from testimonial_forms_list","schema":{"type":"string"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","description":"all (the default), unread or read","enum":["all","unread","read"],"default":"all"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Feedback id, e.g. fb_7Q2K9XH3AB"},"form_id":{"type":"string","description":"The form it came through"},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"body":{"anyOf":[{"type":"string","description":"The words"},{"type":"null"}]},"name":{"anyOf":[{"type":"string","description":"The giver's name, if given"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"The giver's email, if given. null unless the caller holds content.write"},{"type":"null"}]},"read":{"type":"boolean","description":"Whether a member has marked it read"},"read_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was marked read"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it arrived"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_feedback_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/forms/{form_id}/feedback/{id}/mark_read.json":{"post":{"operationId":"testimonial_feedback_mark_read","summary":"Mark a private feedback answer as read, or as unread again","description":"Sets read_at on one private feedback answer, or clears it with read false. Marking an answer that is already read keeps the time it was first read. Nothing is sent to the person who wrote it.","tags":["Private feedback"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"form_id","in":"path","required":true,"description":"Form id (frm_...), from testimonial_forms_list","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_feedback_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Feedback id, e.g. fb_7Q2K9XH3AB"},"form_id":{"type":"string","description":"The form it came through"},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"body":{"anyOf":[{"type":"string","description":"The words"},{"type":"null"}]},"name":{"anyOf":[{"type":"string","description":"The giver's name, if given"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"The giver's email, if given. null unless the caller holds content.write"},{"type":"null"}]},"read":{"type":"boolean","description":"Whether a member has marked it read"},"read_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was marked read"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it arrived"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_feedback_mark_read","x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"read":{"type":"boolean","description":"false marks it as unread again","default":true}}}}}}}},"/sites/{site_id}/testimonials/forms/{form_id}/feedback/{id}.json":{"get":{"operationId":"testimonial_feedback_get","summary":"Get one private feedback answer","description":"Returns the rating, the text, the name the person gave and when it was read. Private feedback is an answer with a low rating on a form with low-rating routing on. It is never a testimonial and never public.","tags":["Private feedback"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"form_id","in":"path","required":true,"description":"Form id (frm_...), from testimonial_forms_list","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_feedback_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Feedback id, e.g. fb_7Q2K9XH3AB"},"form_id":{"type":"string","description":"The form it came through"},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"body":{"anyOf":[{"type":"string","description":"The words"},{"type":"null"}]},"name":{"anyOf":[{"type":"string","description":"The giver's name, if given"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"The giver's email, if given. null unless the caller holds content.write"},{"type":"null"}]},"read":{"type":"boolean","description":"Whether a member has marked it read"},"read_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was marked read"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it arrived"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_feedback_get","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/removal_requests/{id}/dismiss.json":{"post":{"operationId":"testimonial_removal_requests_dismiss","summary":"Dismiss a removal request","description":"Closes the request with a note and leaves the testimonial where it is shown. Nothing is deleted and no email is sent to the person who asked. The note is required. A request that is already decided responds with 422.","tags":["Removal requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_removal_requests_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Request id, e.g. rmv_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"testimonial_id":{"type":"string","description":"The testimonial it is about"},"person_name":{"anyOf":[{"type":"string","description":"The name of the person who gave the testimonial"},{"type":"null"}]},"excerpt":{"anyOf":[{"type":"string","description":"The start of the testimonial"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"The email the sender typed. null unless the caller may change content"},{"type":"null"}]},"email_matches":{"type":"boolean","description":"The typed address is the same as the giver's stored email. Nobody confirmed it, so it proves nothing about who sent the request"},"note":{"anyOf":[{"type":"string","description":"What the sender added"},{"type":"null"}]},"status":{"type":"string","description":"open, removed or dismissed"},"requests_count":{"type":"integer","description":"How many times this address asked"},"resolution_note":{"anyOf":[{"type":"string","description":"The member's note"},{"type":"null"}]},"resolved_by":{"anyOf":[{"type":"string","description":"Who decided"},{"type":"null"}]},"resolved_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was decided"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it arrived"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_removal_requests_dismiss","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","description":"Why the request is dismissed, up to 500 characters. Required"}}}}}}}},"/sites/{site_id}/testimonials/removal_requests.json":{"get":{"operationId":"testimonial_removal_requests_list","summary":"List the removal requests of a site","description":"Open requests unless another status is asked for. The email the giver typed is returned only to a caller who may change content.","tags":["Removal requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"open (the default), removed, dismissed or all","enum":["open","removed","dismissed","all"],"default":"open"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Request id, e.g. rmv_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"testimonial_id":{"type":"string","description":"The testimonial it is about"},"person_name":{"anyOf":[{"type":"string","description":"The name of the person who gave the testimonial"},{"type":"null"}]},"excerpt":{"anyOf":[{"type":"string","description":"The start of the testimonial"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"The email the sender typed. null unless the caller may change content"},{"type":"null"}]},"email_matches":{"type":"boolean","description":"The typed address is the same as the giver's stored email. Nobody confirmed it, so it proves nothing about who sent the request"},"note":{"anyOf":[{"type":"string","description":"What the sender added"},{"type":"null"}]},"status":{"type":"string","description":"open, removed or dismissed"},"requests_count":{"type":"integer","description":"How many times this address asked"},"resolution_note":{"anyOf":[{"type":"string","description":"The member's note"},{"type":"null"}]},"resolved_by":{"anyOf":[{"type":"string","description":"Who decided"},{"type":"null"}]},"resolved_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was decided"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it arrived"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_removal_requests_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/removal_requests/{id}/resolve.json":{"post":{"operationId":"testimonial_removal_requests_resolve","summary":"Decide a removal request","description":"trash moves the testimonial to the trash, which takes it off every widget, wall and public page at once and can be undone for 30 days. dismiss leaves it showing and needs a note.","tags":["Removal requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_removal_requests_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Request id, e.g. rmv_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"testimonial_id":{"type":"string","description":"The testimonial it is about"},"person_name":{"anyOf":[{"type":"string","description":"The name of the person who gave the testimonial"},{"type":"null"}]},"excerpt":{"anyOf":[{"type":"string","description":"The start of the testimonial"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"The email the sender typed. null unless the caller may change content"},{"type":"null"}]},"email_matches":{"type":"boolean","description":"The typed address is the same as the giver's stored email. Nobody confirmed it, so it proves nothing about who sent the request"},"note":{"anyOf":[{"type":"string","description":"What the sender added"},{"type":"null"}]},"status":{"type":"string","description":"open, removed or dismissed"},"requests_count":{"type":"integer","description":"How many times this address asked"},"resolution_note":{"anyOf":[{"type":"string","description":"The member's note"},{"type":"null"}]},"resolved_by":{"anyOf":[{"type":"string","description":"Who decided"},{"type":"null"}]},"resolved_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was decided"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it arrived"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"resolution":{"type":"string","description":"trash moves the testimonial to the trash. dismiss leaves it showing","enum":["trash","dismiss"]},"note":{"type":"string","description":"Why, up to 500 characters. Required for dismiss. Kept with the request and sent to nobody"}},"required":["resolution"]}}}}}},"/sites/{site_id}/testimonials/removal_requests/{id}.json":{"get":{"operationId":"testimonial_removal_requests_get","summary":"Get one removal request","description":"One request with the testimonial it is about, the note the person left, whether the email they typed matches the email on the testimonial, how many times they asked, and the decision once there is one. The email itself is returned only to a caller with content.write.","tags":["Removal requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_removal_requests_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Request id, e.g. rmv_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"testimonial_id":{"type":"string","description":"The testimonial it is about"},"person_name":{"anyOf":[{"type":"string","description":"The name of the person who gave the testimonial"},{"type":"null"}]},"excerpt":{"anyOf":[{"type":"string","description":"The start of the testimonial"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"The email the sender typed. null unless the caller may change content"},{"type":"null"}]},"email_matches":{"type":"boolean","description":"The typed address is the same as the giver's stored email. Nobody confirmed it, so it proves nothing about who sent the request"},"note":{"anyOf":[{"type":"string","description":"What the sender added"},{"type":"null"}]},"status":{"type":"string","description":"open, removed or dismissed"},"requests_count":{"type":"integer","description":"How many times this address asked"},"resolution_note":{"anyOf":[{"type":"string","description":"The member's note"},{"type":"null"}]},"resolved_by":{"anyOf":[{"type":"string","description":"Who decided"},{"type":"null"}]},"resolved_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was decided"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it arrived"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_removal_requests_get","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/settings/rewards/{id}/copy.json":{"post":{"operationId":"testimonial_rewards_copy","summary":"Copy a form's reward to other forms of the same site","description":"Copies the title, the text, the code and the on or off state of this form's reward to each form in form_ids (1 to 100 forms of the same site, not in the trash). A reward the target form already has is replaced. The server responds with 422 and the code unknown_ids when an id is not a form of the site, and then nothing is copied.","tags":["Rewards"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_rewards_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"anyOf":[{"type":"string","description":"Reward id, e.g. rwd_7Q2K9XH3AB, or null when the form has none yet"},{"type":"null"}]},"form_id":{"type":"string","description":"The form it belongs to"},"form_name":{"type":"string","description":"The form's name"},"enabled":{"type":"boolean","description":"Whether it is shown on the thank-you step"},"title":{"anyOf":[{"type":"string","description":"Title"},{"type":"null"}]},"text":{"anyOf":[{"type":"string","description":"The reward in words"},{"type":"null"}]},"code":{"anyOf":[{"type":"string","description":"The shared code"},{"type":"null"}]},"updated_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it last changed"},{"type":"null"}]}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_rewards_copy","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"form_ids":{"type":"array","items":{"type":"string"},"description":"The forms (frm_...) to copy this reward to"}},"required":["form_ids"]}}}}}},"/sites/{site_id}/testimonials/settings/rewards.json":{"get":{"operationId":"testimonial_rewards_list","summary":"List the reward of every form of a site","description":"One row per form. A form with no reward set has enabled false.","tags":["Rewards"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"anyOf":[{"type":"string","description":"Reward id, e.g. rwd_7Q2K9XH3AB, or null when the form has none yet"},{"type":"null"}]},"form_id":{"type":"string","description":"The form it belongs to"},"form_name":{"type":"string","description":"The form's name"},"enabled":{"type":"boolean","description":"Whether it is shown on the thank-you step"},"title":{"anyOf":[{"type":"string","description":"Title"},{"type":"null"}]},"text":{"anyOf":[{"type":"string","description":"The reward in words"},{"type":"null"}]},"code":{"anyOf":[{"type":"string","description":"The shared code"},{"type":"null"}]},"updated_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it last changed"},{"type":"null"}]}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_rewards_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/settings/rewards/{id}.json":{"patch":{"operationId":"testimonial_rewards_update","summary":"Set the reward a form shows on its thank-you step","description":"The id is the form's id. The code is text you supply. Privatus Analytics does not create, check or expire it.","tags":["Rewards"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_rewards_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"anyOf":[{"type":"string","description":"Reward id, e.g. rwd_7Q2K9XH3AB, or null when the form has none yet"},{"type":"null"}]},"form_id":{"type":"string","description":"The form it belongs to"},"form_name":{"type":"string","description":"The form's name"},"enabled":{"type":"boolean","description":"Whether it is shown on the thank-you step"},"title":{"anyOf":[{"type":"string","description":"Title"},{"type":"null"}]},"text":{"anyOf":[{"type":"string","description":"The reward in words"},{"type":"null"}]},"code":{"anyOf":[{"type":"string","description":"The shared code"},{"type":"null"}]},"updated_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it last changed"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_rewards_update","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether the reward is shown. It needs a text"},"title":{"type":"string","description":"Title, up to 80 characters"},"text":{"type":"string","description":"The reward in words, up to 280 characters, for example: 20% off your next order"},"code":{"type":"string","description":"One shared code, up to 64 characters, shown with a Copy button"}}}}}}}},"/workspaces/{workspace_id}/roles.json":{"post":{"operationId":"roles_create","summary":"Create a custom role","description":"Creates a custom role, a named set of permissions you can give to members through invitations_create or members_update with role custom and the role's id as custom_role_id. It needs the Business plan and members.manage. permissions must list at least one name from the allowed values (analytics.read, analytics.export, content.write, sites.manage, uptime.manage, members.manage, tokens.manage, billing.manage, workspace.manage) and you cannot include a permission you do not hold yourself. Returns the role (see roles_list for fields).","tags":["Roles"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Custom role id (custom_role_id on members)"},"name":{"type":"string"},"permissions":{"type":"array","items":{"type":"string"},"description":"Granted permissions"},"members":{"type":"integer","description":"Members with this role"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"members.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Role name, for example Client reviewer.","examples":["Client reviewer"]},"permissions":{"type":"array","items":{"type":"string","enum":["analytics.read","analytics.export","content.write","sites.manage","uptime.manage","members.manage","tokens.manage","billing.manage","workspace.manage"]},"description":"Permission names the role grants, from analytics.read, analytics.export, content.write, sites.manage, uptime.manage, members.manage, tokens.manage, billing.manage and workspace.manage. At least one is needed and you can only include permissions you hold."}},"required":["name","permissions"]}}}}},"get":{"operationId":"roles_list","summary":"List custom roles","description":"Lists the custom roles of a workspace, ordered by name. Custom roles are a Business plan feature that bundle permissions under your own name, and the built-in roles (owner, admin, editor, analyst, viewer, billing) are not listed in data: the response meta has built_in, an object with the permissions of each built-in role by its name. Each role has id (uuid, used as custom_role_id in invitations_create and members_update), name, permissions (names such as analytics.read, content.write, members.manage), members (the number of members who hold it) and created_at. Callers limited to some sites see only roles within their reach.","tags":["Roles"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Custom role id (custom_role_id on members)"},"name":{"type":"string"},"permissions":{"type":"array","items":{"type":"string"},"description":"Granted permissions"},"members":{"type":"integer","description":"Members with this role"},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"roles_list"}},"/workspaces/{workspace_id}/roles/{id}.json":{"delete":{"operationId":"roles_delete","summary":"Delete a custom role (must be unused)","description":"Deletes a custom role. This cannot be undone and it fails while any member or pending invitation still uses the role, so move those people to another role first with members_update (find them with members_list). The built-in roles cannot be deleted. Take the id (uuid) from roles_list. Requires members.manage. Returns the deleted role.","tags":["Roles"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by roles_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Custom role id (custom_role_id on members)"},"name":{"type":"string"},"permissions":{"type":"array","items":{"type":"string"},"description":"Granted permissions"},"members":{"type":"integer","description":"Members with this role"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"members.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"patch":{"operationId":"roles_update","summary":"Update a custom role","description":"Renames a custom role and or replaces its whole permission list. Only the inputs you send change, and permissions replaces the existing list rather than adding to it. The change applies at once to every member and pending invitation that holds the role. You can only edit a role whose permissions you fully hold, and a caller limited to some sites needs reach over every site of its holders. Requires members.manage. Take the id (uuid) from roles_list. Returns the updated role.","tags":["Roles"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by roles_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Custom role id (custom_role_id on members)"},"name":{"type":"string"},"permissions":{"type":"array","items":{"type":"string"},"description":"Granted permissions"},"members":{"type":"integer","description":"Members with this role"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"members.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New role name. Omit to keep it."},"permissions":{"type":"array","items":{"type":"string","enum":["analytics.read","analytics.export","content.write","sites.manage","uptime.manage","members.manage","tokens.manage","billing.manage","workspace.manage"]},"description":"New permission names. Replaces the whole current list, so send every permission the role should have. Omit to keep it."}}}}}}}},"/scim/v2/Users.json":{"post":{"operationId":"scim_users_create","summary":"Provision a user","tags":["SCIM"],"parameters":[],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userName":{"type":"string","description":"Email address"},"name":{"type":"object","additionalProperties":true,"description":"givenName, familyName, formatted","default":{}},"active":{"type":"boolean","description":"Member of the workspace","default":true}},"required":["userName"]}}}},"security":[]},"get":{"operationId":"scim_users_list","summary":"List provisioned users","tags":["SCIM"],"parameters":[{"name":"scim_filter","in":"query","required":false,"schema":{"type":"string","description":"SCIM filter (query param `filter`), e.g. userName eq \"a@b.com\""}},{"name":"startIndex","in":"query","required":false,"schema":{"type":"integer","description":"1-based index of the first result","default":1}},{"name":"count","in":"query","required":false,"schema":{"type":"integer","description":"Page size (max 200)","default":100}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/scim/v2/Users/{id}.json":{"delete":{"operationId":"scim_users_delete","summary":"Deprovision a user","tags":["SCIM"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by scim_users_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"security":[]},"get":{"operationId":"scim_users_get","summary":"Get a provisioned user","tags":["SCIM"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by scim_users_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]},"patch":{"operationId":"scim_users_update","summary":"Update a user (PATCH active, name)","tags":["SCIM"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by scim_users_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"Operations":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"SCIM PatchOp operations"}},"required":["Operations"]}}}},"security":[]}},"/workspaces/{workspace_id}/sso/activate.json":{"post":{"operationId":"sso_activate","summary":"Activate a tested SSO configuration","description":"Turns SSO on for the workspace. The configuration must already have status tested, which happens after a successful trial login (started from the workspace SSO settings page in the app, it needs a browser sign-in and cannot be run from here), or already be active. Business plan only. After activation members can sign in with SSO, and setting enforced through sso_update then requires SSO for every login. It fails when the config is untested or the plan has no SSO. Requires workspace.manage. Returns the configuration with status active (see sso_get).","tags":["SSO"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"protocol":{"type":"string","description":"saml or oidc"},"status":{"type":"string","description":"draft, testing, tested or active"},"enforced":{"type":"boolean","description":"SSO is the only way in (owner excepted)"},"domains":{"type":"array","items":{"type":"string"},"description":"Verified email domains"},"idp_sso_url":{"anyOf":[{"type":"string"},{"type":"null"}]},"idp_entity_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"idp_cert_present":{"type":"boolean"},"oidc_issuer":{"anyOf":[{"type":"string"},{"type":"null"}]},"oidc_client_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"oidc_client_secret_present":{"type":"boolean"},"default_role":{"type":"string"},"jit_provisioning":{"type":"boolean"},"scim_enabled":{"type":"boolean"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/workspaces/{workspace_id}/sso/deactivate.json":{"post":{"operationId":"sso_deactivate","summary":"Turn SSO off (back to draft)","description":"Turns SSO off by returning the configuration to draft and clearing enforced, so members go back to the workspace's other login methods. Provider details are kept. Reactivating requires a new trial login and sso_activate. Make sure members have another way to sign in first. This works on any plan. Requires workspace.manage. Returns the configuration with status draft (see sso_get).","tags":["SSO"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"protocol":{"type":"string","description":"saml or oidc"},"status":{"type":"string","description":"draft, testing, tested or active"},"enforced":{"type":"boolean","description":"SSO is the only way in (owner excepted)"},"domains":{"type":"array","items":{"type":"string"},"description":"Verified email domains"},"idp_sso_url":{"anyOf":[{"type":"string"},{"type":"null"}]},"idp_entity_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"idp_cert_present":{"type":"boolean"},"oidc_issuer":{"anyOf":[{"type":"string"},{"type":"null"}]},"oidc_client_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"oidc_client_secret_present":{"type":"boolean"},"default_role":{"type":"string"},"jit_provisioning":{"type":"boolean"},"scim_enabled":{"type":"boolean"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/workspaces/{workspace_id}/sso/scim_token.json":{"post":{"operationId":"sso_scim_token","summary":"Generate a new SCIM token (shown once)","tags":["SSO"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/workspaces/{workspace_id}/sso.json":{"get":{"operationId":"sso_get","summary":"Get SSO settings","description":"Returns the workspace's single sign-on (SSO) configuration, or an empty draft when none exists. Fields are protocol (saml or oidc), status (draft, testing, tested or active), enforced (members must sign in through SSO), domains (email domains that use this SSO), idp_sso_url and idp_entity_id for SAML, oidc_issuer and oidc_client_id for OIDC, default_role and jit_provisioning (create members on first SSO login), and scim_enabled. Secrets are never returned, only idp_cert_present and oidc_client_secret_present booleans. SSO is a Business plan feature. Requires workspace.manage.","tags":["SSO"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"protocol":{"type":"string","description":"saml or oidc"},"status":{"type":"string","description":"draft, testing, tested or active"},"enforced":{"type":"boolean","description":"SSO is the only way in (owner excepted)"},"domains":{"type":"array","items":{"type":"string"},"description":"Verified email domains"},"idp_sso_url":{"anyOf":[{"type":"string"},{"type":"null"}]},"idp_entity_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"idp_cert_present":{"type":"boolean"},"oidc_issuer":{"anyOf":[{"type":"string"},{"type":"null"}]},"oidc_client_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"oidc_client_secret_present":{"type":"boolean"},"default_role":{"type":"string"},"jit_provisioning":{"type":"boolean"},"scim_enabled":{"type":"boolean"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"sso_get","x-permission":"workspace.manage"},"patch":{"operationId":"sso_update","summary":"Create or update SSO settings","description":"Creates or edits the workspace's SSO settings. Business plan only. Only the inputs you send change. For SAML send protocol saml with idp_sso_url, idp_entity_id and idp_cert (PEM text). For OIDC send protocol oidc with oidc_issuer, oidc_client_id and oidc_client_secret, which is write-only and an empty value keeps the existing secret. domains lists the email domains that use this SSO. default_role is the role given to members created by first-login provisioning or SCIM (not owner or custom) and you can only set a role you could grant yourself. Changing any identity provider detail sends an active or tested config back to draft and turns off enforced, so it must be tested again before sso_activate works. enforced true is only accepted while status is active. Requires workspace.manage. Returns the configuration (see sso_get).","tags":["SSO"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"protocol":{"type":"string","description":"saml or oidc"},"status":{"type":"string","description":"draft, testing, tested or active"},"enforced":{"type":"boolean","description":"SSO is the only way in (owner excepted)"},"domains":{"type":"array","items":{"type":"string"},"description":"Verified email domains"},"idp_sso_url":{"anyOf":[{"type":"string"},{"type":"null"}]},"idp_entity_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"idp_cert_present":{"type":"boolean"},"oidc_issuer":{"anyOf":[{"type":"string"},{"type":"null"}]},"oidc_client_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"oidc_client_secret_present":{"type":"boolean"},"default_role":{"type":"string"},"jit_provisioning":{"type":"boolean"},"scim_enabled":{"type":"boolean"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"protocol":{"type":"string","description":"saml or oidc.","enum":["saml","oidc"]},"idp_sso_url":{"type":"string","description":"SAML: IdP single sign-on URL"},"idp_entity_id":{"type":"string","description":"SAML: IdP entity id (issuer)"},"idp_cert":{"type":"string","description":"SAML only. The identity provider's X.509 signing certificate as PEM text."},"oidc_issuer":{"type":"string","description":"OIDC: issuer URL (discovery)"},"oidc_client_id":{"type":"string","description":"OIDC: client id"},"oidc_client_secret":{"type":"string","description":"OIDC only. The client secret. Write-only, never returned, and an empty value keeps the existing one."},"domains":{"type":"array","items":{"type":"string"},"description":"Email domains that use this SSO, for example [example.com]. Replaces the current list."},"default_role":{"type":"string","description":"Role given to members created by first-login provisioning or SCIM, one of admin, editor, analyst, viewer or billing. You can only set a role you could grant yourself.","enum":["admin","editor","analyst","viewer","billing"]},"jit_provisioning":{"type":"boolean","description":"Create members on first SSO login"},"enforced":{"type":"boolean","description":"true requires SSO for every sign-in. Only accepted while status is active, and reset to false when identity provider details change."}}}}}}}},"/sites/{site_id}/search.json":{"get":{"operationId":"search_report","summary":"Search report: clicks, impressions, CTR, position, top queries/pages, landing pages and opportunities","description":"Search performance from Google Search Console and Bing Webmaster, joined to the site's own landing page metrics. Choose provider: all (the default) adds every connected engine together, with position weighted by impressions and countries and devices from Google only, or google or bing alone and the usual period or custom from and to. limit (1 to 100, default 25) caps the rows in each table. The result has period, provider, connection (property, status, last_synced_at of the chosen engine, or null when it is not connected or provider is all), connections (each connected engine with provider, property, status and last_synced_at), latest_date (newest day with data), delayed (true when the range extends past latest_date), totals and series (per day) each with clicks, impressions, ctr (a percentage, not a fraction, 2 decimals) and position (average rank, 1 is best, null if unknown), breakdowns for query, page, country and device (rows of value plus the same four metrics), landing_pages (top pages with visits, bounce_rate and conversion_rate as percentages, and conversions), and opportunities (low_ctr_queries with at least 100 impressions and a CTR under 2 percent, and striking_distance pages averaging position 8 to 20). Country values are as the provider reports them. Use stats_breakdown for visitor data and this tool for what happens before the click. Needs analytics.read.","tags":["Search"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset, in the site's timezone: today, yesterday, 24h (last 24 hours), 7d, 14d, 28d, 30d, 90d (the last N days), mtd (month to date), last_month, qtd (quarter to date), last_quarter, ytd (year to date), 12mo, last_year, all (all time), or custom (then the range is from to to)","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the range as YYYY-MM-DD, in the site's timezone. Only used when period is custom. Without it the range starts 29 days before to"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the range as YYYY-MM-DD, inclusive. Only used when period is custom. Without it the range ends today"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Also compute a comparison range: previous_period (the same length right before), previous_year (the same dates a year earlier), custom (needs both compare_from and compare_to) or none. Adds the comparison values and the percent change to the result","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"compare_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day of the comparison range as YYYY-MM-DD. Only used when compare is custom"}},{"name":"compare_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day of the comparison range as YYYY-MM-DD, inclusive. Only used when compare is custom"}},{"name":"match_weekday","in":"query","required":false,"schema":{"type":"boolean","description":"Shift the comparison range so days of the week line up (Monday against Monday)","default":false}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Filters that must all match: a list of [dimension, operator, value] conditions, e.g. [[\"country\",\"is\",\"US\"],[\"page\",\"starts_with\",\"/blog\"]]. Dimensions: channel, referrer, referrer_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term, ref, hostname, country, language, device, browser, browser_version, os, os_version, screen, entry_page, exit_page, interaction, bot_score, page, event, goal, prop:<key>. Use the exact singular names (country, not countries). Values are as stored: country is a two-letter code such as US, channel is a name such as organic_search, a page is a path such as /pricing. Operators taking one value: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (the value uses * as a wildcard, e.g. /blog/*), regex and not_regex (a Postgres regular expression of up to 200 characters), gt and lt (a number). any_of and none_of take a list: [\"country\",\"any_of\",[\"US\",\"DE\"]]. between takes two numbers: [\"prop:price\",\"between\",[10,50]]. For OR, wrap conditions in an object: {\"any\":[[\"channel\",\"is\",\"email\"],[\"utm_medium\",\"is\",\"email\"]]}. Up to 20 conditions.","default":[]}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"string","description":"Apply a saved segment by its id (seg_…, from segments_list). Its filters are added to filters"}},{"name":"include_imported","in":"query","required":false,"schema":{"type":"boolean","description":"Add imported historical data (dates before the first native event, ignored when filters or a segment are applied)","default":false}},{"name":"provider","in":"query","required":false,"schema":{"type":"string","description":"all (the default: every connected engine added together), google (Search Console) or bing","enum":["all","google","bing"],"default":"all"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Rows in each breakdown table, 1 to 100 (default 25)","default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"search_report","x-permission":"analytics.read"}},"/sites/{site_id}/search/connections/{provider}.json":{"delete":{"operationId":"search_disconnect","summary":"Disconnect Search Console or Bing and delete its data","description":"Disconnects a search provider (google or bing) from a site and permanently deletes its imported search data for that provider. This cannot be undone. The Google authorization is removed too once no site uses it. Fails if that provider is not connected. Returns the removed connection. Needs sites.manage.","tags":["Search"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"provider","in":"path","required":true,"description":"Search engine connection to remove: google or bing","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"provider":{"type":"string","description":"google or bing"},"property":{"type":"string","description":"Search Console property or Bing site URL"},"status":{"type":"string","description":"active or error"},"last_synced_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/search/sync.json":{"post":{"operationId":"search_sync","summary":"Import search data now","description":"Queues an immediate import of search data for a connected provider (google, the default, or bing) instead of waiting for the regular schedule. It returns right away (HTTP 202) with the connection and the import runs in the background. Poll search_report and watch connection.last_synced_at. Search engines report with a delay of a couple of days, so the newest days stay empty even after a sync. Fails if the provider is not connected. Needs sites.manage.","tags":["Search"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"provider":{"type":"string","description":"google or bing"},"property":{"type":"string","description":"Search Console property or Bing site URL"},"status":{"type":"string","description":"active or error"},"last_synced_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"search_sync","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"provider":{"type":"string","description":"Which connected provider to sync now, google (default) or bing","enum":["google","bing"],"default":"google"}}}}}}}},"/sites/{site_id}/segments.json":{"post":{"operationId":"segments_create","summary":"Save filters as a segment","description":"Saves a set of filters as a named segment that can be reused on any stats tool through segment_id. Pass name and filters (all conditions must match, and an {any: [...]} group matches when one of several does, see the filters input for the dimension names and operators). The filters are checked, so an unknown dimension or a bad value returns a 422 with a message per row. Use segments_preview first to check what a filter set matches. shared is true by default and makes the segment visible to everyone with access to the site, false keeps it private to you. Returns the segment with id (seg_...), site_id, name, description, filters, summary (a plain English description), shared, mine and timestamps. Needs the content.write permission.","tags":["Segments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Segment id, e.g. seg_7Q2K9XH3AB"},"site_id":{"type":"string"},"name":{"type":"string"},"description":{"anyOf":[{"type":"string","description":"What the segment is for, or null"},{"type":"null"}]},"filters":{"type":"array","description":"Filters in the stats filter format: conditions [\"dimension\", \"operator\", \"value\"] that must all match, and {\"any\": [conditions]} groups"},"summary":{"type":"string","description":"The filters in plain English, e.g. \"Visitors from the United States on mobile who viewed /pricing\""},"shared":{"type":"boolean","description":"Visible to everyone with access to the site"},"mine":{"type":"boolean","description":"Created by you"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"segments_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Segment name, up to 100 characters, for example Mobile visitors from ads","examples":["Mobile visitors from ads"]},"description":{"type":"string","description":"Optional note on what the segment is for (300 characters at most)","examples":["People who might buy the Pro plan"]},"filters":{"type":"array","items":{},"description":"Filters, all of which must match. Each item is a condition [\"dimension\", \"operator\", \"value\"], or {\"any\": [conditions]} when any one of several may match. Dimensions: page, entry_page, exit_page, hostname, channel, referrer, referrer_url, ref, utm_source, utm_medium, utm_campaign, utm_content, utm_term, country (ISO code, e.g. US), language, device (desktop, mobile, tablet, tv, other), browser, browser_version, os, os_version, screen, interaction (seen, none or unknown), bot_score (likely_human, unsure, likely_bot or not_scored), goal (goal id), event (custom event name) and prop:<key> (custom event property). Operators: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (* matches anything), regex, not_regex, any_of and none_of (value is a list), gt and lt (a number), between (a list of two numbers). Rows from the segment form are accepted too: {\"dimension\", \"operator\", \"value\", \"property\" (for dimension prop), \"join\": \"and\" or \"or\" (or combines the row with the one before it)}. Example: [[\"country\", \"is\", \"US\"], [\"device\", \"is\", \"mobile\"], {\"any\": [[\"page\", \"starts_with\", \"/pricing\"], [\"goal\", \"is\", \"goal_7Q2K9XH3AB\"]]}]","examples":[[["country","is","US"],["device","is","mobile"],{"any":[["page","starts_with","/pricing"],["goal","is","goal_7Q2K9XH3AB"]]}]]},"shared":{"type":"boolean","description":"Visible to everyone with access to the site (false: only you)","default":true}},"required":["name","filters"]}}}}},"get":{"operationId":"segments_list","summary":"List segments you can use on a site","description":"Lists the saved segments of a site, ordered by name: the shared ones plus your own private ones. Each segment has id (seg_...), site_id, name, description, filters, summary, shared, mine and timestamps. Pass an id as segment_id to any stats tool (stats_aggregate, stats_breakdown, funnels_get and others) to apply the segment's filters. Paginated through the standard page parameters. Use segments_create to add one.","tags":["Segments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Segment id, e.g. seg_7Q2K9XH3AB"},"site_id":{"type":"string"},"name":{"type":"string"},"description":{"anyOf":[{"type":"string","description":"What the segment is for, or null"},{"type":"null"}]},"filters":{"type":"array","description":"Filters in the stats filter format: conditions [\"dimension\", \"operator\", \"value\"] that must all match, and {\"any\": [conditions]} groups"},"summary":{"type":"string","description":"The filters in plain English, e.g. \"Visitors from the United States on mobile who viewed /pricing\""},"shared":{"type":"boolean","description":"Visible to everyone with access to the site"},"mine":{"type":"boolean","description":"Created by you"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"segments_list","x-permission":"analytics.read"}},"/sites/{site_id}/segments/{id}.json":{"delete":{"operationId":"segments_delete","summary":"Delete a segment","description":"Permanently deletes a saved segment. Dashboards and links that use it fall back to all traffic. No analytics data is touched and there is no undo. Returns the deleted segment. Ids (seg_...) come from segments_list. Needs the content.write permission.","tags":["Segments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by segments_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Segment id, e.g. seg_7Q2K9XH3AB"},"site_id":{"type":"string"},"name":{"type":"string"},"description":{"anyOf":[{"type":"string","description":"What the segment is for, or null"},{"type":"null"}]},"filters":{"type":"array","description":"Filters in the stats filter format: conditions [\"dimension\", \"operator\", \"value\"] that must all match, and {\"any\": [conditions]} groups"},"summary":{"type":"string","description":"The filters in plain English, e.g. \"Visitors from the United States on mobile who viewed /pricing\""},"shared":{"type":"boolean","description":"Visible to everyone with access to the site"},"mine":{"type":"boolean","description":"Created by you"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"segments_delete","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"segments_get","summary":"Get a segment","description":"Returns one saved segment: id (seg_...), site_id, name, description, filters (the stored conditions), summary (a plain English description such as Visitors from the United States on mobile), shared (visible to everyone with site access), mine (true when you created it) and timestamps. You can read shared segments and your own private ones. Ids come from segments_list. To count how many visitors a set of filters matches, use segments_preview.","tags":["Segments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by segments_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Segment id, e.g. seg_7Q2K9XH3AB"},"site_id":{"type":"string"},"name":{"type":"string"},"description":{"anyOf":[{"type":"string","description":"What the segment is for, or null"},{"type":"null"}]},"filters":{"type":"array","description":"Filters in the stats filter format: conditions [\"dimension\", \"operator\", \"value\"] that must all match, and {\"any\": [conditions]} groups"},"summary":{"type":"string","description":"The filters in plain English, e.g. \"Visitors from the United States on mobile who viewed /pricing\""},"shared":{"type":"boolean","description":"Visible to everyone with access to the site"},"mine":{"type":"boolean","description":"Created by you"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"segments_get","x-permission":"analytics.read"},"patch":{"operationId":"segments_update","summary":"Rename a segment or change its filters or sharing","description":"Renames a segment, replaces its filters or changes who can see it. Only the inputs you send change. Sending filters replaces all existing filters, in the same format and with the same checks as segments_create. shared false makes it private to its creator. description can be cleared by sending it empty. Everything that uses the segment, such as stats calls with its segment_id, changes straight away. Returns the segment. Ids come from segments_list. Needs the content.write permission.","tags":["Segments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by segments_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Segment id, e.g. seg_7Q2K9XH3AB"},"site_id":{"type":"string"},"name":{"type":"string"},"description":{"anyOf":[{"type":"string","description":"What the segment is for, or null"},{"type":"null"}]},"filters":{"type":"array","description":"Filters in the stats filter format: conditions [\"dimension\", \"operator\", \"value\"] that must all match, and {\"any\": [conditions]} groups"},"summary":{"type":"string","description":"The filters in plain English, e.g. \"Visitors from the United States on mobile who viewed /pricing\""},"shared":{"type":"boolean","description":"Visible to everyone with access to the site"},"mine":{"type":"boolean","description":"Created by you"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"segments_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Segment name"},"description":{"type":"string","description":"Optional note on what the segment is for (300 characters at most, empty to clear)"},"filters":{"type":"array","items":{},"description":"Replacement filters, in the same format as when creating. Filters, all of which must match. Each item is a condition [\"dimension\", \"operator\", \"value\"], or {\"any\": [conditions]} when any one of several may match. Dimensions: page, entry_page, exit_page, hostname, channel, referrer, referrer_url, ref, utm_source, utm_medium, utm_campaign, utm_content, utm_term, country (ISO code, e.g. US), language, device (desktop, mobile, tablet, tv, other), browser, browser_version, os, os_version, screen, interaction (seen, none or unknown), bot_score (likely_human, unsure, likely_bot or not_scored), goal (goal id), event (custom event name) and prop:<key> (custom event property). Operators: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (* matches anything), regex, not_regex, any_of and none_of (value is a list), gt and lt (a number), between (a list of two numbers). Rows from the segment form are accepted too: {\"dimension\", \"operator\", \"value\", \"property\" (for dimension prop), \"join\": \"and\" or \"or\" (or combines the row with the one before it)}. Example: [[\"country\", \"is\", \"US\"], [\"device\", \"is\", \"mobile\"], {\"any\": [[\"page\", \"starts_with\", \"/pricing\"], [\"goal\", \"is\", \"goal_7Q2K9XH3AB\"]]}]","examples":[[["country","is","US"],["device","is","mobile"],{"any":[["page","starts_with","/pricing"],["goal","is","goal_7Q2K9XH3AB"]]}]]},"shared":{"type":"boolean","description":"Visible to everyone on the site"}}}}}}}},"/sites/{site_id}/segments/preview.json":{"post":{"operationId":"segments_preview","summary":"Describe filters in plain English and count the visitors they matched in the last 30 days","description":"Checks a set of filters without saving anything. Returns summary (the filters in plain English), visitors (how many visitors matched in the last 30 days, null when the filters are invalid), period (always 30d) and filters (the cleaned, canonical form that would be stored). Filters use the same format as segments_create, including {any: [...]} groups and optional spelled-out names for countries, channels and goals, which are converted to codes and ids. Invalid filters return a 422 that names the row. Use it to try filters before segments_create, and stats_aggregate with filters for numbers over another period.","tags":["Segments"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"segments_preview","x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"filters":{"type":"array","items":{},"description":"Filters, all of which must match. Each item is a condition [\"dimension\", \"operator\", \"value\"], or {\"any\": [conditions]} when any one of several may match. Dimensions: page, entry_page, exit_page, hostname, channel, referrer, referrer_url, ref, utm_source, utm_medium, utm_campaign, utm_content, utm_term, country (ISO code, e.g. US), language, device (desktop, mobile, tablet, tv, other), browser, browser_version, os, os_version, screen, interaction (seen, none or unknown), bot_score (likely_human, unsure, likely_bot or not_scored), goal (goal id), event (custom event name) and prop:<key> (custom event property). Operators: is, is_not, contains, not_contains, starts_with, wildcard and not_wildcard (* matches anything), regex, not_regex, any_of and none_of (value is a list), gt and lt (a number), between (a list of two numbers). Rows from the segment form are accepted too: {\"dimension\", \"operator\", \"value\", \"property\" (for dimension prop), \"join\": \"and\" or \"or\" (or combines the row with the one before it)}. Example: [[\"country\", \"is\", \"US\"], [\"device\", \"is\", \"mobile\"], {\"any\": [[\"page\", \"starts_with\", \"/pricing\"], [\"goal\", \"is\", \"goal_7Q2K9XH3AB\"]]}]","examples":[[["country","is","US"],["device","is","mobile"],{"any":[["page","starts_with","/pricing"],["goal","is","goal_7Q2K9XH3AB"]]}]],"default":[]}}}}}}}},"/badge/{site_id}.json":{"get":{"operationId":"badges_get","summary":"Visitor counter badge (SVG) for a public site","tags":["Sharing"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/sites/{site_id}/shared_links/{id}.json":{"delete":{"operationId":"shared_links_delete","summary":"Revoke a share link","description":"Revokes a share link right away, so its URL and embed code stop working for everyone. This cannot be undone and a revoked link cannot be restored, create a new one instead. The record stays internally but disappears from shared_links_list. The id (shr_...) comes from shared_links_list. Returns the revoked link. Revocation is written to the security log.","tags":["Sharing"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by shared_links_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Share link id, e.g. shr_7Q2K9XH3AB"},"kind":{"type":"string","description":"public, password, sso or embed"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"url":{"type":"string","description":"Share URL (the password never goes in it)"},"embed_url":{"type":"string","description":"URL for an iframe embed"},"sections":{"type":"array","items":{"type":"string"},"description":"Shared sections besides the overview"},"locked_filters":{"type":"array","description":"Filters viewers cannot remove"},"locked_period":{"anyOf":[{"type":"string","description":"Fixed date range"},{"type":"null"}]},"options":{"type":"object","description":"theme and allow_filters"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"usable":{"type":"boolean","description":"Not expired or revoked"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the link responds 404"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"shared_links_delete","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/shared_links.json":{"get":{"operationId":"shared_links_list","summary":"List share links","description":"Lists the active (not revoked) share links of one site (path takes site_id), newest first, as a plain list with no pagination. Each link has id (shr_...), kind (public, password, sso or embed), name, url (the page to share), embed_url (for iframes), sections, locked_filters, locked_period, options (theme and allow_filters), expires_at and usable (false once expired). Filter by kind. Wallboard links are separate, use wallboard_links_list for those. Needs the sites.manage permission.","tags":["Sharing"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","description":"Only links of this kind: public, password, sso or embed","enum":["public","password","sso","embed"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Share link id, e.g. shr_7Q2K9XH3AB"},"kind":{"type":"string","description":"public, password, sso or embed"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"url":{"type":"string","description":"Share URL (the password never goes in it)"},"embed_url":{"type":"string","description":"URL for an iframe embed"},"sections":{"type":"array","items":{"type":"string"},"description":"Shared sections besides the overview"},"locked_filters":{"type":"array","description":"Filters viewers cannot remove"},"locked_period":{"anyOf":[{"type":"string","description":"Fixed date range"},{"type":"null"}]},"options":{"type":"object","description":"theme and allow_filters"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"usable":{"type":"boolean","description":"Not expired or revoked"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the link responds 404"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"shared_links_list","x-permission":"sites.manage"}},"/share/{token}/breakdown/{dimension}.json":{"get":{"operationId":"shares_breakdown","summary":"Top values of a shared dimension","description":"Top values of one dimension behind a share link, the shared equivalent of stats_breakdown. Path takes token (the last part of the share URL) and dimension, which must belong to a section the link shares, for example sources shares channel, referrer and referrer_url, pages shares page, entry_page, exit_page and hostname, campaigns shares the utm_ dimensions, locations shares country and language, technology shares device, browser, os and screen, conversions shares goal and events shares event. A dimension outside the link's sections is refused with a validation error. limit is 1 to 100 rows (default 10). Rows have the same fields and units as stats_breakdown for that dimension. The link's locked period and filters win over period, from, to and filters, and filters from the caller are ignored when the link does not allow them. A password link needs the X-Share-Password header.","tags":["Sharing"],"parameters":[{"name":"token","in":"path","required":true,"description":"Share link token, the last part of the share URL (/share/<token>)","schema":{"type":"string"}},{"name":"dimension","in":"path","required":true,"description":"A dimension the link shares, as named in stats_breakdown, e.g. page, channel, country, browser. A dimension outside the link's sections is refused","schema":{"type":"string","enum":["channel","referrer","referrer_url","page","entry_page","exit_page","hostname","utm_campaign","utm_source","utm_medium","utm_content","utm_term","country","language","device","browser","os","screen","goal","event"]}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset such as today, 7d (default), 30d, 90d, mtd, last_month, ytd, 12mo, all or custom (then from and to are required). Ignored when the link locks its period","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Start date for period custom, YYYY-MM-DD"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"End date for period custom, YYYY-MM-DD, inclusive"}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Extra filters as a list of [dimension, operator, value] triples. Ignored when the link does not allow filters","default":[]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Rows to return, 1 to 100 (default 10)","default":10}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/share/{token}.json":{"get":{"operationId":"shares_overview","summary":"Shared dashboard overview for a share token","description":"Reads the dashboard behind a share link for people who have no account. The path token is the last part of a share URL (/share/<token>) and is the only credential, a password link also needs the X-Share-Password header, and an sso link needs a signed in member. It also accepts a site id (pa_...) when the site has its public dashboard turned on. Returns the same data as stats_overview, limited to what the link shares. That is period, metrics (visitors, visits, pageviews, views_per_visit, bounce_rate as a percent, visit_duration in milliseconds, revenue in minor units), the chart series for interval, comparison data when compare is set, and panels of top values only for the shared sections. It adds site (id, name, domain, timezone), sections and locked_period. live_visitors appears only when the link shares live. A locked period and locked filters on the link override period, from, to and filters. Use shares_breakdown for more rows of one dimension. For your own sites use stats_overview.","tags":["Sharing"],"parameters":[{"name":"token","in":"path","required":true,"description":"Share link token, the last part of the share URL (/share/<token>)","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Date range preset such as today, 7d (default), 30d, 90d, mtd, last_month, ytd, 12mo, all or custom (then from and to are required). Ignored when the link locks its period","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"7d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Start date for period custom, YYYY-MM-DD"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"End date for period custom, YYYY-MM-DD, inclusive"}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Comparison range: none (default), previous_period or previous_year","enum":["none","previous_period","previous_year","custom"],"default":"none"}},{"name":"filters","in":"query","required":false,"schema":{"type":"array","items":{},"description":"Extra filters as a list of [dimension, operator, value] triples, e.g. [[\"country\",\"is\",\"US\"]]. Ignored when the link does not allow filters. Locked filters of the link always apply","default":[]}},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Chart bucket size: auto (default), minute, hour, day, week, month, quarter or year","enum":["auto","minute","hour","day","week","month","quarter","year"],"default":"auto"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/sites/{site_id}/audit/issues.json":{"get":{"operationId":"site_audit_issues_list","summary":"List the issues of a site audit, one row per check","description":"Lists the issues of one audit, one row per check that flagged something, worst first (errors, then warnings, then notices, each by URLs affected). Each row has check_key (use it with site_audit_issues_get and the mute tools), title, category, severity (error, warning or notice), affected (URLs flagged, muted ones excluded), added and fixed (changes since the previous audit), and pageviews (visits to affected pages in the 30 days before the audit). Defaults to the latest finished audit, or pass audit_id. Filter with severity, category and new_only (only checks with URLs that are new since the previous audit). Paginated with page and per_page (max 100, default 50). The response meta has the pagination plus audit (id, finished_at and created_at of the audit listed, null when the site has none). To see which URLs a check flagged use site_audit_issues_get. Needs analytics.read.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"audit_id","in":"query","required":false,"schema":{"type":"string","description":"Audit id (aud_…). Default: the latest finished audit"}},{"name":"severity","in":"query","required":false,"schema":{"type":"string","description":"Only checks of this severity: error, warning or notice","enum":["error","warning","notice"]}},{"name":"category","in":"query","required":false,"schema":{"type":"string","description":"Only checks in this category, e.g. content, redirects, internal_links, performance or security","enum":["crawlability","redirects","sitemaps","internal_links","external_links","content","images","structured_data","international","mobile","performance","security","urls","pagination","ai_search","traffic"]}},{"name":"new_only","in":"query","required":false,"schema":{"type":"boolean","description":"true to list only checks that have URLs that are new since the audit before. Default false","default":false}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","description":"Page number, starting at 1","default":1}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","description":"Checks per page, 1 to 100 (default 50)","default":50}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"check_key":{"type":"string","description":"The check's key, used in site_audit_issues_get"},"title":{"type":"string"},"category":{"anyOf":[{"type":"string","description":"The check's category. Null for a check that was retired"},{"type":"null"}]},"severity":{"type":"string","description":"error, warning or notice"},"affected":{"type":"integer","description":"URLs the check flagged, without muted ones"},"added":{"type":"integer","description":"URLs that are new since the audit before"},"fixed":{"type":"integer","description":"URLs fixed since the audit before"},"pageviews":{"type":"integer","description":"Pageviews of the affected pages in the 30 days before the audit"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_issues_list","x-permission":"analytics.read"}},"/sites/{site_id}/audit/issues/{check_key}.json":{"get":{"operationId":"site_audit_issues_get","summary":"Get one site audit check: why it matters, how to fix it and the affected URLs","description":"Details of one check in an audit, by check_key from site_audit_issues_list (for example title_missing). Returns audit_id, issue (the same row as in the list), why (what the problem means), fix (how to fix it), muted (true if the whole check is muted for the site) and urls, the flagged URLs with page_id (use it with site_audit_pages_get), url, pageviews, detail (extra facts about the finding, may be empty), is_new and muted. sort is pageviews (default, busiest first) or url. Paginated with page and per_page (max 100, default 25). Defaults to the latest finished audit, or pass audit_id. Muted URLs sort last. Needs analytics.read.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"check_key","in":"path","required":true,"description":"Check key, e.g. title_missing","schema":{"type":"string"}},{"name":"audit_id","in":"query","required":false,"schema":{"type":"string","description":"Audit id (aud_…). Default: the latest finished audit"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"Order of the flagged URLs: pageviews (most visited first, default) or url (alphabetical)","enum":["pageviews","url"],"default":"pageviews"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","description":"Page number of the affected URLs","default":1}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","description":"Flagged URLs per page, 1 to 100 (default 25)","default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"audit_id":{"type":"string"},"issue":{"type":"object","properties":{"check_key":{"type":"string","description":"The check's key, used in site_audit_issues_get"},"title":{"type":"string"},"category":{"anyOf":[{"type":"string","description":"The check's category. Null for a check that was retired"},{"type":"null"}]},"severity":{"type":"string","description":"error, warning or notice"},"affected":{"type":"integer","description":"URLs the check flagged, without muted ones"},"added":{"type":"integer","description":"URLs that are new since the audit before"},"fixed":{"type":"integer","description":"URLs fixed since the audit before"},"pageviews":{"type":"integer","description":"Pageviews of the affected pages in the 30 days before the audit"}}},"why":{"anyOf":[{"type":"string","description":"Why the check matters. Null for a check that was retired"},{"type":"null"}]},"fix":{"anyOf":[{"type":"string","description":"How to fix it"},{"type":"null"}]},"muted":{"type":"boolean","description":"true when the whole check is muted on this site"},"urls":{"type":"array","items":{"type":"object"},"description":"One page of affected URLs: [{page_id, url, pageviews, detail, is_new, muted}]"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_issues_get","x-permission":"analytics.read"}},"/sites/{site_id}/audit/mutes/bulk.json":{"post":{"operationId":"site_audit_mutes_bulk","summary":"Mute a site audit check on several URLs, or several whole checks, in one call","description":"Mutes many findings in one request, all or nothing. Use one of two shapes. Either send check_key plus urls (up to 100 URLs) to mute one check on several pages, or send check_keys (up to 100) to mute whole checks for the site. Do not mix urls with check_keys. An unknown check or an invalid URL fails the whole request and mutes nothing. Already muted items are returned as they are. The latest audit's counts and score are refreshed once at the end. Returns the list of mutes. Undo each with site_audit_mutes_delete. Needs content.write.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Mute id (mute_…)"},"site_id":{"type":"string"},"check_key":{"type":"string"},"title":{"type":"string"},"url":{"anyOf":[{"type":"string","description":"The one URL the mute applies to. Null for the whole site"},{"type":"null"}]},"muted_by":{"anyOf":[{"type":"string","description":"Name of the member who muted it"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_mutes_bulk","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"check_key":{"type":"string","description":"The check to mute on the listed urls, e.g. title_too_long. Required with urls, leave out when sending check_keys"},"urls":{"type":"array","items":{"type":"string"},"description":"Full URLs to mute check_key on (max 100). All are muted, or none if one is invalid. Do not combine with check_keys","default":[]},"check_keys":{"type":"array","items":{"type":"string"},"description":"Whole checks to mute for the site (max 100), instead of check_key and urls","default":[]}}}}}}}},"/sites/{site_id}/audit/mutes.json":{"post":{"operationId":"site_audit_mutes_create","summary":"Mute a site audit check, for the whole site or one URL","description":"Mutes one check for the site, or for one URL only. check_key comes from site_audit_issues_list. Leave url out to mute the check everywhere, or pass a full URL (such as https://example.com/old) to mute it on that page only, where the URL is normalized the way the crawler does. The latest audit's counts and score update at once. Muting the same thing twice returns the existing mute instead of an error. To mute many at once use site_audit_mutes_bulk, and to undo use site_audit_mutes_delete. Needs content.write.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Mute id (mute_…)"},"site_id":{"type":"string"},"check_key":{"type":"string"},"title":{"type":"string"},"url":{"anyOf":[{"type":"string","description":"The one URL the mute applies to. Null for the whole site"},{"type":"null"}]},"muted_by":{"anyOf":[{"type":"string","description":"Name of the member who muted it"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_mutes_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"check_key":{"type":"string","description":"Check key from site_audit_issues_list, e.g. title_too_long. Lowercase letters, digits and underscores"},"url":{"type":"string","description":"Full URL (https://...) to mute the check on that page only. Leave out to mute the check for the whole site"}},"required":["check_key"]}}}}},"get":{"operationId":"site_audit_mutes_list","summary":"List the checks a site has muted","description":"Lists the checks muted for the site, newest first. A mute hides a check either for the whole site (url is null) or for one URL, so those findings stay out of counts and the score though audits still record them. Each row has id (a mute id, use it with site_audit_mutes_delete), site_id, check_key, title, url (null for a site-wide mute), muted_by (the member name, null if unknown) and created_at. Filter with check_key. Paginated with page and per_page (max 100). Needs analytics.read.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"check_key","in":"query","required":false,"schema":{"type":"string","description":"Only mutes of this check key"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Mute id (mute_…)"},"site_id":{"type":"string"},"check_key":{"type":"string"},"title":{"type":"string"},"url":{"anyOf":[{"type":"string","description":"The one URL the mute applies to. Null for the whole site"},{"type":"null"}]},"muted_by":{"anyOf":[{"type":"string","description":"Name of the member who muted it"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_mutes_list","x-permission":"analytics.read"}},"/sites/{site_id}/audit/mutes/{id}.json":{"delete":{"operationId":"site_audit_mutes_delete","summary":"Unmute a site audit check","description":"Removes a mute, found by its id from site_audit_mutes_list, so the check or URL counts in the audit score again. The latest audit is recounted immediately. This only removes the mute and does not delete audit data. Returns the removed mute. Needs content.write.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by site_audit_mutes_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Mute id (mute_…)"},"site_id":{"type":"string"},"check_key":{"type":"string"},"title":{"type":"string"},"url":{"anyOf":[{"type":"string","description":"The one URL the mute applies to. Null for the whole site"},{"type":"null"}]},"muted_by":{"anyOf":[{"type":"string","description":"Name of the member who muted it"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_mutes_delete","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/audit/notifications.json":{"patch":{"operationId":"site_audit_notifications_update","summary":"Turn your audit summary email for a site on or off","description":"Turns the weekly audit summary email on or off for the calling member on one site. It is a personal preference and does not affect other members. enabled true sends the member the summary after audits of this site, false stops it. Returns site_id, enabled and all_sites_enabled (false when the member switched off audit emails for every site in their account settings, which overrides this). Any member with analytics.read can change their own setting.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string"},"enabled":{"type":"boolean","description":"Whether you get the summary email for this site"},"all_sites_enabled":{"type":"boolean","description":"false when you turned the email off for every site on your account page"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_notifications_update","x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","description":"true to receive the audit summary email for this site, false to stop it. Applies to the calling member only"}},"required":["enabled"]}}}}}},"/sites/{site_id}/audit/pages.json":{"get":{"operationId":"site_audit_pages_list","summary":"List and filter the pages of a site audit","description":"The page explorer, listing the URLs of one audit (the latest finished one by default, or audit_id). kind is page (default, HTML documents), resource (images, scripts, stylesheets) or external (links to other sites). Filter by state (queued, fetched, skipped, blocked, failed), status_class (2xx, 3xx, 4xx or 5xx), indexable, in_sitemap, has_issues (counting unmuted issues only), depth (clicks from the start page) and query (text in the URL or title). sort is pageviews (default), inlinks, depth, response_ms (slowest first) or word_count (fewest first). Each row has id (a UUID for site_audit_pages_get), url, path, kind, state, status, depth, indexable, indexability_reason, title, word_count, response_ms, cache_status, inlinks, pageviews, in_sitemap and issues (count). Paginated with page and per_page (max 100). The response meta has the pagination plus audit (id, finished_at and created_at of the audit listed, null when the site has none). Needs analytics.read.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"audit_id","in":"query","required":false,"schema":{"type":"string","description":"Audit id (aud_…). Default: the latest finished audit"}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","description":"page (HTML documents, default), resource (images, scripts, stylesheets) or external (links to other sites)","enum":["page","resource","external"],"default":"page"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","description":"Only URLs in this crawl state: queued, fetched, skipped, blocked or failed","enum":["queued","fetched","skipped","blocked","failed"]}},{"name":"status_class","in":"query","required":false,"schema":{"type":"string","description":"Only URLs whose HTTP status was in this class: 2xx, 3xx, 4xx or 5xx","enum":["2xx","3xx","4xx","5xx"]}},{"name":"indexable","in":"query","required":false,"schema":{"type":"boolean","description":"true for indexable pages, false for the rest"}},{"name":"in_sitemap","in":"query","required":false,"schema":{"type":"boolean","description":"true for pages listed in a sitemap, false for the rest"}},{"name":"has_issues","in":"query","required":false,"schema":{"type":"boolean","description":"true for pages with at least one issue that is not muted, false for pages with none"}},{"name":"depth","in":"query","required":false,"schema":{"type":"integer","description":"Only pages exactly this many clicks from the start page (0 is the start page)"}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Case-insensitive text the URL or the title contains"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"pageviews (most first, default), inlinks (most first), depth (shallowest first), response_ms (slowest first) or word_count (fewest first)","enum":["pageviews","inlinks","depth","response_ms","word_count"],"default":"pageviews"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Page id (a UUID), used in site_audit_pages_get"},"url":{"type":"string"},"path":{"anyOf":[{"type":"string","description":"The path as analytics records it"},{"type":"null"}]},"kind":{"type":"string","description":"page, resource or external"},"state":{"type":"string","description":"queued, fetched, skipped, blocked or failed"},"status":{"anyOf":[{"type":"integer"},{"type":"null"}]},"depth":{"anyOf":[{"type":"integer","description":"Clicks from the start page"},{"type":"null"}]},"indexable":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"indexability_reason":{"anyOf":[{"type":"string","description":"Why the page can't be indexed"},{"type":"null"}]},"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"word_count":{"anyOf":[{"type":"integer"},{"type":"null"}]},"response_ms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"cache_status":{"anyOf":[{"type":"string","description":"hit when a CDN or server cache served the page, miss when one responded without it, null when no cache header came back"},{"type":"null"}]},"inlinks":{"type":"integer","description":"Internal links that point to the page"},"pageviews":{"anyOf":[{"type":"integer","description":"Pageviews in the 30 days before the audit"},{"type":"null"}]},"in_sitemap":{"type":"boolean"},"issues":{"type":"integer","description":"Issues on the page that are not muted"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_pages_list","x-permission":"analytics.read"}},"/sites/{site_id}/audit/pages/{id}.json":{"get":{"operationId":"site_audit_pages_get","summary":"Get one audited page: its metadata, issues, links in and links out","description":"Everything the audit stored about one URL, by id (a UUID from site_audit_pages_list or from the urls of site_audit_issues_get). Returns id, audit_id, audited_at (when that audit finished), page (url, status, redirect_to, content_type, bytes, response_ms, title, meta_description, h1, canonical, robots_meta, indexable and indexability_reason, word_count, lang, hreflang, schema_types, social tags, images_count, images_missing_alt, link counts, link_score, in_sitemap, has_tracker, pageviews and search_clicks, fetched_at and more), redirect_target_id (the page it redirects to within the audit, or null), issues (check_key, title, category, severity, detail, is_new, muted), and inlinks and outlinks (up to 100 each with page_id, url, status, kind, anchor, nofollow, count). Needs analytics.read.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by site_audit_pages_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"audit_id":{"type":"string"},"audited_at":{"type":"string","format":"date-time","description":"When the audit that crawled the page finished"},"page":{"type":"object","description":"Every stored field of the page. Metadata only, never the page text"},"redirect_target_id":{"anyOf":[{"type":"string","format":"uuid","description":"The audited page it redirects to, if that was crawled"},{"type":"null"}]},"issues":{"type":"array","items":{"type":"object"},"description":"[{check_key, title, category, severity, detail, is_new, muted}]"},"inlinks":{"type":"array","items":{"type":"object"},"description":"The first 100 links to the page: [{page_id, url, status, kind, anchor, nofollow, count}]"},"outlinks":{"type":"array","items":{"type":"object"},"description":"The first 100 links on the page: [{page_id, url, status, kind, anchor, nofollow, count}]"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_pages_get","x-permission":"analytics.read"}},"/sites/{site_id}/audit/settings.json":{"get":{"operationId":"site_audit_settings_get","summary":"Get a site's audit settings","description":"Returns the site's audit settings. Fields are site_id, enabled (scheduled audits on or off, on by default), include_subdomains, check_external_links, exclude_paths, ignored_params, extra_start_urls, next_run_at (when the next scheduled audit is due, null if none), page_limit (pages per audit on the current plan, null when unlimited) and interval_days (days between scheduled audits on the plan). A site that never changed its settings returns the defaults. Change them with site_audit_settings_update. Needs sites.manage.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string"},"enabled":{"type":"boolean"},"include_subdomains":{"type":"boolean"},"check_external_links":{"type":"boolean"},"exclude_paths":{"type":"array","items":{"type":"string"}},"ignored_params":{"type":"array","items":{"type":"string"}},"extra_start_urls":{"type":"array","items":{"type":"string"}},"next_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"page_limit":{"anyOf":[{"type":"integer","description":"Pages per audit on the workspace's plan. Null for a custom limit"},{"type":"null"}]},"interval_days":{"type":"integer","description":"Days between scheduled audits on the workspace's plan"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_settings_get","x-permission":"sites.manage"},"patch":{"operationId":"site_audit_settings_update","summary":"Change a site's audit settings","description":"Changes how the site is audited. Only inputs you send change. enabled turns scheduled and manual audits on or off (turning it on schedules the next audit one plan interval away). include_subdomains and check_external_links are booleans. The three lists replace the stored list, they are not merged, so send the full list. exclude_paths are path prefixes the crawler skips and each must start with a slash (up to 50). ignored_params are query parameter names that never make a different page, such as utm_source or sessionid (up to 50, letters, digits, dot, dash, underscore). extra_start_urls are full http or https URLs to crawl in addition to the home page (up to 20). A list can also be sent as text with one entry per line. Returns the updated settings. Needs sites.manage.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string"},"enabled":{"type":"boolean"},"include_subdomains":{"type":"boolean"},"check_external_links":{"type":"boolean"},"exclude_paths":{"type":"array","items":{"type":"string"}},"ignored_params":{"type":"array","items":{"type":"string"}},"extra_start_urls":{"type":"array","items":{"type":"string"}},"next_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"page_limit":{"anyOf":[{"type":"integer","description":"Pages per audit on the workspace's plan. Null for a custom limit"},{"type":"null"}]},"interval_days":{"type":"integer","description":"Days between scheduled audits on the workspace's plan"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_settings_update","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","description":"true to audit the site on its schedule and allow manual runs, false to turn the audit off"},"include_subdomains":{"type":"boolean","description":"true to follow links to subdomains of the site's domain"},"check_external_links":{"type":"boolean","description":"true to check that links to other sites still work"},"exclude_paths":{"type":"array","items":{"type":"string"},"description":"Replaces the list of path prefixes the crawler skips. Each must start with a slash, e.g. /admin (max 50, 512 characters each). Also accepts text with one entry per line"},"ignored_params":{"type":"array","items":{"type":"string"},"description":"Replaces the list of query parameter names that never make a different page, e.g. utm_source, sessionid (max 50, letters, digits, dot, dash, underscore, brackets)"},"extra_start_urls":{"type":"array","items":{"type":"string"},"description":"Replaces the list of full http or https URLs to crawl in addition to the home page (max 20, 2048 characters each)"}}}}}}}},"/audit/unsubscribe/{token}.json":{"post":{"operationId":"site_audit_unsubscribes_create","summary":"Unsubscribe from site audit summary emails with the token from an email","tags":["Site audit"],"parameters":[{"name":"token","in":"path","required":true,"description":"The token from the unsubscribe link of a site audit summary email","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"The token from the unsubscribe link of a site audit summary email"},"scope":{"type":"string","description":"`site` turns the email off for the one site, `all` for every site","enum":["site","all"],"default":"site"}},"required":["token"]}}}},"security":[]}},"/sites/{site_id}/audit/cancel.json":{"post":{"operationId":"site_audit_cancel","summary":"Cancel the site audit that is running","description":"Stops the audit that is running or queued for the site. The audit is marked canceled and nothing from the unfinished crawl is reported. A canceled audit does not use up the Free plan's monthly allowance. Fails with a validation error if no audit is live. Returns the canceled audit. Needs content.write.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Audit id (aud_…)"},"site_id":{"type":"string"},"status":{"type":"string","description":"queued, running, analyzing, complete, partial, failed or canceled"},"trigger":{"type":"string","description":"What started it: first, scheduled or manual"},"score":{"anyOf":[{"type":"integer","description":"0 to 100. Null until the audit finishes"},{"type":"null"}]},"score_band":{"anyOf":[{"type":"string","description":"good (90 and up), needs_improvement (70 to 89) or poor"},{"type":"null"}]},"page_limit":{"type":"integer","description":"Pages the plan allowed for this audit"},"pages_crawled":{"type":"integer","description":"HTML pages fetched"},"urls_discovered":{"type":"integer","description":"In-scope pages found, crawled or not"},"errors":{"type":"integer","description":"Findings of severity error, without muted ones"},"warnings":{"type":"integer","description":"Findings of severity warning, without muted ones"},"notices":{"type":"integer","description":"Findings of severity notice, without muted ones"},"new_issues":{"type":"integer","description":"Findings that are new since the audit before"},"fixed_issues":{"type":"integer","description":"Findings of the audit before that are gone"},"failure":{"anyOf":[{"type":"string","description":"Why a failed or partial audit stopped: unreachable, out_of_scope, robots_unreachable, robots_disallowed, blocked, timed_out or not_html"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_cancel","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/audit/compare.json":{"get":{"operationId":"site_audit_compare","summary":"Compare two site audits: URLs added and fixed per check","description":"Compares two audits of the site, check by check. audit_id is the newer audit and base_id the older one. Both default sensibly (the latest finished audit against the finished audit before it), and the tool swaps them if you pass them in the wrong order. Returns audit and base (each an audit summary, base null if there is nothing earlier) and checks, one object per check whose URLs changed, with check_key, title, category, severity, base_affected, affected, added and fixed (URL counts), sorted errors first. Checks with no change are left out. For two consecutive audits added and fixed are exact, for audits further apart they are the net change. Needs analytics.read.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"audit_id","in":"query","required":false,"schema":{"type":"string","description":"The newer audit (aud_…). Default: the latest finished audit"}},{"name":"base_id","in":"query","required":false,"schema":{"type":"string","description":"The older audit (aud_…). Default: the finished audit before it"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"audit":{"type":"object","properties":{"id":{"type":"string","description":"Audit id (aud_…)"},"site_id":{"type":"string"},"status":{"type":"string","description":"queued, running, analyzing, complete, partial, failed or canceled"},"trigger":{"type":"string","description":"What started it: first, scheduled or manual"},"score":{"anyOf":[{"type":"integer","description":"0 to 100. Null until the audit finishes"},{"type":"null"}]},"score_band":{"anyOf":[{"type":"string","description":"good (90 and up), needs_improvement (70 to 89) or poor"},{"type":"null"}]},"page_limit":{"type":"integer","description":"Pages the plan allowed for this audit"},"pages_crawled":{"type":"integer","description":"HTML pages fetched"},"urls_discovered":{"type":"integer","description":"In-scope pages found, crawled or not"},"errors":{"type":"integer","description":"Findings of severity error, without muted ones"},"warnings":{"type":"integer","description":"Findings of severity warning, without muted ones"},"notices":{"type":"integer","description":"Findings of severity notice, without muted ones"},"new_issues":{"type":"integer","description":"Findings that are new since the audit before"},"fixed_issues":{"type":"integer","description":"Findings of the audit before that are gone"},"failure":{"anyOf":[{"type":"string","description":"Why a failed or partial audit stopped: unreachable, out_of_scope, robots_unreachable, robots_disallowed, blocked, timed_out or not_html"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}},"description":"The newer audit"},"base":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Audit id (aud_…)"},"site_id":{"type":"string"},"status":{"type":"string","description":"queued, running, analyzing, complete, partial, failed or canceled"},"trigger":{"type":"string","description":"What started it: first, scheduled or manual"},"score":{"anyOf":[{"type":"integer","description":"0 to 100. Null until the audit finishes"},{"type":"null"}]},"score_band":{"anyOf":[{"type":"string","description":"good (90 and up), needs_improvement (70 to 89) or poor"},{"type":"null"}]},"page_limit":{"type":"integer","description":"Pages the plan allowed for this audit"},"pages_crawled":{"type":"integer","description":"HTML pages fetched"},"urls_discovered":{"type":"integer","description":"In-scope pages found, crawled or not"},"errors":{"type":"integer","description":"Findings of severity error, without muted ones"},"warnings":{"type":"integer","description":"Findings of severity warning, without muted ones"},"notices":{"type":"integer","description":"Findings of severity notice, without muted ones"},"new_issues":{"type":"integer","description":"Findings that are new since the audit before"},"fixed_issues":{"type":"integer","description":"Findings of the audit before that are gone"},"failure":{"anyOf":[{"type":"string","description":"Why a failed or partial audit stopped: unreachable, out_of_scope, robots_unreachable, robots_disallowed, blocked, timed_out or not_html"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}},"description":"The older audit. Null when there is none to compare with"},{"type":"null"}]},"checks":{"type":"array","items":{"type":"object"},"description":"[{check_key, title, category, severity, base_affected, affected, added, fixed}] for checks that changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_compare","x-permission":"analytics.read"}},"/sites/{site_id}/audit.json":{"post":{"operationId":"site_audit_run","summary":"Start a site audit now","description":"Starts a new crawl and SEO audit of the site now. It crawls the site's public pages in the background, so this returns immediately with the new audit in status queued. Poll site_audit_get (live field) or site_audit_history until the status is complete. Refused with a validation error when the audit is turned off in site_audit_settings_update, when another audit is already queued or running, when a manual audit was started in the last 24 hours, and on the Free plan when any audit ran in the last 30 days (failed and canceled ones do not count). Unverified sites with no events are also limited to one audit a day per domain. Pages crawled are capped by the plan (Free 100, Pro 1,000, Business 10,000). Check can_run in site_audit_get first. Needs content.write.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Audit id (aud_…)"},"site_id":{"type":"string"},"status":{"type":"string","description":"queued, running, analyzing, complete, partial, failed or canceled"},"trigger":{"type":"string","description":"What started it: first, scheduled or manual"},"score":{"anyOf":[{"type":"integer","description":"0 to 100. Null until the audit finishes"},{"type":"null"}]},"score_band":{"anyOf":[{"type":"string","description":"good (90 and up), needs_improvement (70 to 89) or poor"},{"type":"null"}]},"page_limit":{"type":"integer","description":"Pages the plan allowed for this audit"},"pages_crawled":{"type":"integer","description":"HTML pages fetched"},"urls_discovered":{"type":"integer","description":"In-scope pages found, crawled or not"},"errors":{"type":"integer","description":"Findings of severity error, without muted ones"},"warnings":{"type":"integer","description":"Findings of severity warning, without muted ones"},"notices":{"type":"integer","description":"Findings of severity notice, without muted ones"},"new_issues":{"type":"integer","description":"Findings that are new since the audit before"},"fixed_issues":{"type":"integer","description":"Findings of the audit before that are gone"},"failure":{"anyOf":[{"type":"string","description":"Why a failed or partial audit stopped: unreachable, out_of_scope, robots_unreachable, robots_disallowed, blocked, timed_out or not_html"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_run","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"site_audit_get","summary":"Get the site audit overview: score, counts, top issues by traffic and the audit running now","description":"The SEO site audit overview, the best first call for audit questions. By default it describes the latest finished audit, or pass audit_id (aud_..., from site_audit_history) for an older one. The result has audit (the finished audit with score 0 to 100, score_band, score_delta, counts of errors, warnings and notices, pages_crawled, page_limit, capped, summary and robots details, or null if none has finished), live (the audit running now, or null), last (the newest audit whatever its status, as id, status, failure, finished_at and created_at, or null), enabled and next_run_at (the schedule), can_run with run_blocked (live, disabled or too_soon) and run_allowed_at (when site_audit_run is allowed again), changes (added and fixed URL counts per severity), trend (up to 30 recent scores as id, finished_at, score), top_issues (up to 10 checks ranked by severity then pageviews of affected pages) and email_enabled (your own summary email preference). Follow with site_audit_issues_list for every issue and site_audit_pages_list for URLs. Needs analytics.read.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"audit_id","in":"query","required":false,"schema":{"type":"string","description":"Audit id (aud_..., from site_audit_history). Default is the latest finished audit"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"audit":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Audit id (aud_…)"},"site_id":{"type":"string"},"status":{"type":"string","description":"queued, running, analyzing, complete, partial, failed or canceled"},"trigger":{"type":"string","description":"What started it: first, scheduled or manual"},"score":{"anyOf":[{"type":"integer","description":"0 to 100. Null until the audit finishes"},{"type":"null"}]},"score_band":{"anyOf":[{"type":"string","description":"good (90 and up), needs_improvement (70 to 89) or poor"},{"type":"null"}]},"page_limit":{"type":"integer","description":"Pages the plan allowed for this audit"},"pages_crawled":{"type":"integer","description":"HTML pages fetched"},"urls_discovered":{"type":"integer","description":"In-scope pages found, crawled or not"},"errors":{"type":"integer","description":"Findings of severity error, without muted ones"},"warnings":{"type":"integer","description":"Findings of severity warning, without muted ones"},"notices":{"type":"integer","description":"Findings of severity notice, without muted ones"},"new_issues":{"type":"integer","description":"Findings that are new since the audit before"},"fixed_issues":{"type":"integer","description":"Findings of the audit before that are gone"},"failure":{"anyOf":[{"type":"string","description":"Why a failed or partial audit stopped: unreachable, out_of_scope, robots_unreachable, robots_disallowed, blocked, timed_out or not_html"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"score_delta":{"anyOf":[{"type":"integer","description":"Score change against the finished audit before"},{"type":"null"}]},"capped":{"type":"boolean","description":"true when the crawl stopped at the page allowance with pages left"},"start_url":{"anyOf":[{"type":"string"},{"type":"null"}]},"scope_host":{"anyOf":[{"type":"string","description":"The host the crawl stayed on"},{"type":"null"}]},"include_subdomains":{"type":"boolean"},"resources_checked":{"type":"integer","description":"Images, scripts and stylesheets checked"},"external_checked":{"type":"integer","description":"Links to other sites checked"},"summary":{"type":"object","description":"Distributions and scores: {statuses, depths, response_times, speed: {median_ms, fast_percent} (median response time and the percent of pages under 500 ms), cache: {hit, miss, unknown, percent, median_ms: {hit, miss, unknown}} (pages by whether a cache served them, and the median response time of each in milliseconds), pages, categories, indexable, host, sitemaps}. Keys can be missing"},"robots":{"type":"object","description":"robots.txt as the crawler read it: {status, valid, crawl_delay, sitemaps, blocked_ai_bots}"},"upgrade_prompt":{"anyOf":[{"type":"object","description":"Null, or {kind, plan, next_plan, pages_crawled, pages_found, next_page_limit, interval_days, message}"},{"type":"null"}]}},"description":"The latest finished audit (or the one asked for). Null before the first one finishes"},{"type":"null"}]},"live":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Audit id (aud_…)"},"site_id":{"type":"string"},"status":{"type":"string","description":"queued, running, analyzing, complete, partial, failed or canceled"},"trigger":{"type":"string","description":"What started it: first, scheduled or manual"},"score":{"anyOf":[{"type":"integer","description":"0 to 100. Null until the audit finishes"},{"type":"null"}]},"score_band":{"anyOf":[{"type":"string","description":"good (90 and up), needs_improvement (70 to 89) or poor"},{"type":"null"}]},"page_limit":{"type":"integer","description":"Pages the plan allowed for this audit"},"pages_crawled":{"type":"integer","description":"HTML pages fetched"},"urls_discovered":{"type":"integer","description":"In-scope pages found, crawled or not"},"errors":{"type":"integer","description":"Findings of severity error, without muted ones"},"warnings":{"type":"integer","description":"Findings of severity warning, without muted ones"},"notices":{"type":"integer","description":"Findings of severity notice, without muted ones"},"new_issues":{"type":"integer","description":"Findings that are new since the audit before"},"fixed_issues":{"type":"integer","description":"Findings of the audit before that are gone"},"failure":{"anyOf":[{"type":"string","description":"Why a failed or partial audit stopped: unreachable, out_of_scope, robots_unreachable, robots_disallowed, blocked, timed_out or not_html"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}},"description":"The audit that is queued or running now, with its progress"},{"type":"null"}]},"last":{"anyOf":[{"type":"object","description":"The newest audit of the site whatever its status: {id, status, failure, finished_at, created_at}. Null before the first audit"},{"type":"null"}]},"enabled":{"type":"boolean","description":"Whether the site is audited on a schedule"},"next_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the next scheduled audit is due"},{"type":"null"}]},"can_run":{"type":"boolean","description":"Whether an audit can be started now"},"run_blocked":{"anyOf":[{"type":"string","description":"Why not: live, disabled or too_soon"},{"type":"null"}]},"run_allowed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the plan allows the next manual audit"},{"type":"null"}]},"changes":{"type":"object","description":"New and fixed URLs per severity: {error: {added, fixed}, …}"},"trend":{"type":"array","items":{"type":"object"},"description":"Scores of the finished audits, oldest first: [{id, finished_at, score}]"},"top_issues":{"type":"array","items":{"type":"object","properties":{"check_key":{"type":"string","description":"The check's key, used in site_audit_issues_get"},"title":{"type":"string"},"category":{"anyOf":[{"type":"string","description":"The check's category. Null for a check that was retired"},{"type":"null"}]},"severity":{"type":"string","description":"error, warning or notice"},"affected":{"type":"integer","description":"URLs the check flagged, without muted ones"},"added":{"type":"integer","description":"URLs that are new since the audit before"},"fixed":{"type":"integer","description":"URLs fixed since the audit before"},"pageviews":{"type":"integer","description":"Pageviews of the affected pages in the 30 days before the audit"}}},"description":"Up to ten checks, by severity and then by the pageviews of their pages"},"email_enabled":{"anyOf":[{"type":"boolean","description":"Whether you get the summary email for this site"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_get","x-permission":"analytics.read"}},"/sites/{site_id}/audit/history.json":{"get":{"operationId":"site_audit_history","summary":"List a site's audits, newest first","description":"Lists the site's audits, newest first, each with id (aud_...), status (queued, running, analyzing, complete, partial, failed or canceled), trigger (first, scheduled or manual), score (0 to 100, null until finished), score_band, page_limit, pages_crawled, urls_discovered, errors, warnings, notices, new_issues, fixed_issues, failure (reason when failed, else null) and the timestamps. Filter with status. Paginated with page and per_page (max 100). Use the ids with site_audit_get, site_audit_compare and the issues and pages tools. For the current state of one audit use site_audit_get. Needs analytics.read.","tags":["Site audit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Only audits in this state: queued, running, analyzing, complete, partial, failed or canceled","enum":["queued","running","analyzing","complete","partial","failed","canceled"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Audit id (aud_…)"},"site_id":{"type":"string"},"status":{"type":"string","description":"queued, running, analyzing, complete, partial, failed or canceled"},"trigger":{"type":"string","description":"What started it: first, scheduled or manual"},"score":{"anyOf":[{"type":"integer","description":"0 to 100. Null until the audit finishes"},{"type":"null"}]},"score_band":{"anyOf":[{"type":"string","description":"good (90 and up), needs_improvement (70 to 89) or poor"},{"type":"null"}]},"page_limit":{"type":"integer","description":"Pages the plan allowed for this audit"},"pages_crawled":{"type":"integer","description":"HTML pages fetched"},"urls_discovered":{"type":"integer","description":"In-scope pages found, crawled or not"},"errors":{"type":"integer","description":"Findings of severity error, without muted ones"},"warnings":{"type":"integer","description":"Findings of severity warning, without muted ones"},"notices":{"type":"integer","description":"Findings of severity notice, without muted ones"},"new_issues":{"type":"integer","description":"Findings that are new since the audit before"},"fixed_issues":{"type":"integer","description":"Findings of the audit before that are gone"},"failure":{"anyOf":[{"type":"string","description":"Why a failed or partial audit stopped: unreachable, out_of_scope, robots_unreachable, robots_disallowed, blocked, timed_out or not_html"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"site_audit_history","x-permission":"analytics.read"}},"/sites/{site_id}/data_reset.json":{"post":{"operationId":"sites_reset_data","summary":"Delete all events and visits in a date range (runs in the background, cannot be undone)","description":"Irreversibly deletes a site's pageviews, custom events and visits for a date range, and cannot be undone. Use it to clear test traffic or remove a bad period. It does not delete the site, its goals or its settings (use sites_delete for the site). from and to are YYYY-MM-DD dates, both inclusive and read in the site's timezone, and to must not be before from. confirm must be the site's domain exactly as shown by sites_get (case does not matter). The request is accepted and returns immediately with status queued, site_id, from and to. The deletion runs in the background in batches, so numbers in the stats tools may take a little while to settle, and there is no status endpoint to poll, check the stats tools until the range is empty. The action is recorded in the audit log. Requires the sites.manage permission.","tags":["Sites"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"from":{"type":"string","format":"date","description":"First day to delete, YYYY-MM-DD in the site's timezone, inclusive."},"to":{"type":"string","format":"date","description":"Last day to delete, YYYY-MM-DD in the site's timezone, inclusive. Must not be before from."},"confirm":{"type":"string","description":"The site's domain exactly as shown by sites_get, for example example.com. Case does not matter. Any other value is refused."}},"required":["from","to","confirm"]}}}}}},"/sites/{site_id}/filter_stats.json":{"get":{"operationId":"sites_filter_stats","summary":"Filtered traffic summary: bots, traffic rules or PII redactions by reason and country (counts only)","description":"Counts of hits that were dropped or cleaned before storage, over the last days. Use it to see how much bot traffic, rule-blocked traffic or redaction a site has. Choose kind with bot (hits dropped as bots), rule (hits dropped by traffic rules) or redaction (values redacted by the personal data scrubber). Returns kind, days, total, by_reason, by_country and by_day. by_reason and by_country are lists of {value, count} (up to 50, largest first, value null when unknown) and by_day is a list of {date, count}. days is clamped between 1 and 395 and defaults to 30. These are aggregate counts only. No IP addresses, user agents or redacted values are stored, so nothing can be traced to a person. These hits are not counted as events for billing. Use traffic_rules_list to see or change the rules.","tags":["Sites"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","description":"bot (hits dropped as bots), rule (hits dropped by traffic rules) or redaction (values cleaned by the personal data scrubber). Default bot","enum":["bot","rule","redaction"],"default":"bot"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","description":"Number of days to look back, from 1 to 395. Default 30. Values outside the range are clamped","default":30}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"sites_filter_stats","x-permission":"analytics.read"}},"/sites/{site_id}/access.json":{"get":{"operationId":"sites_access_list","summary":"List members and whether they can see this site","description":"Shows which workspace members can see one site. Every member of the workspace is listed in join order, not paginated. Fields are membership_id (the uuid used by sites_access_update), email, name, role, access (true when the member can see this site) and locked (true for owners and admins, who always have access and cannot be changed). Other members have access when they have all sites or an explicit grant for this site. Use members_list to see a member's full site list. Requires members.manage.","tags":["Sites"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"membership_id":{"type":"string","format":"uuid","description":"Membership id"},"email":{"type":"string"},"name":{"type":"string"},"role":{"type":"string"},"access":{"type":"boolean","description":"Can see this site"},"locked":{"type":"boolean","description":"Owners and admins always have access"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"sites_access_list","x-permission":"members.manage"},"patch":{"operationId":"sites_access_update","summary":"Grant or remove one member's access to this site","description":"Grants or removes one member's access to one site. membership_id comes from sites_access_list (or members_list) and access is true to grant or false to remove. Owners and admins always have access and cannot be changed. Removing access from a member who had all sites switches them to an explicit list of every other site in the workspace and turns off their include_future_sites, so they will not get sites created later. Granting to someone who already has all sites changes nothing. You cannot change a member who holds permissions you lack or sites beyond yours. Requires members.manage. Returns that member's row in the same shape as sites_access_list.","tags":["Sites"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"membership_id":{"type":"string","format":"uuid","description":"Membership id"},"email":{"type":"string"},"name":{"type":"string"},"role":{"type":"string"},"access":{"type":"boolean","description":"Can see this site"},"locked":{"type":"boolean","description":"Owners and admins always have access"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"members.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"membership_id":{"type":"string","description":"Membership id (uuid) from sites_access_list or members_list."},"access":{"type":"boolean","description":"true to grant access, false to remove it"}},"required":["membership_id","access"]}}}}}},"/sites/{site_id}/favorite.json":{"post":{"operationId":"sites_favorite","summary":"Star a site (pinned first on All sites)","description":"Stars a site for the calling user so it is listed first by sites_list and on the All sites page. It only affects the caller, never other members, and starring an already starred site changes nothing. The call needs no input beyond the site id. Use sites_unfavorite to remove the star. Requires analytics.read. Returns the site (see sites_get), with favorite true.","tags":["Sites"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Site id used in the tracking snippet"},"workspace_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"extra_domains":{"type":"array","items":{"type":"string"}},"multi_domain_mode":{"type":"string"},"timezone":{"type":"string"},"currency":{"type":"string"},"labels":{"type":"array","items":{"type":"string"}},"honor_dnt":{"type":"boolean"},"honor_gpc":{"type":"boolean"},"pii_scrubber":{"type":"boolean"},"redaction_rules":{"type":"array"},"allowed_params":{"type":"array","items":{"type":"string"}},"path_masks":{"type":"array"},"retention_months":{"anyOf":[{"type":"integer"},{"type":"null"}]},"bot_filtering":{"type":"boolean"},"traffic_rule_modes":{"type":"object"},"vitals_sample_rate":{"type":"integer"},"conversion_denominator":{"type":"string"},"public_dashboard":{"type":"boolean"},"public_indexable":{"type":"boolean"},"ingest_key_prefix":{"anyOf":[{"type":"string","description":"Start of the crawler log key"},{"type":"null"}]},"verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"first_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"domain_rating":{"anyOf":[{"type":"integer","description":"Domain Rating from 0 to 100, our own estimate of the strength of the domain's link profile. Null until the first check"},{"type":"null"}]},"snippet":{"type":"string","description":"HTML tracking snippet"},"favorite":{"type":"boolean","description":"Starred by you"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"sites_favorite","x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"delete":{"operationId":"sites_unfavorite","summary":"Unstar a site","description":"Removes the calling user's star from a site, so it is no longer pinned first in sites_list. It only affects the caller and does nothing if the site was not starred. Use sites_favorite to star it again. Requires analytics.read. Returns the site (see sites_get), with favorite false.","tags":["Sites"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Site id used in the tracking snippet"},"workspace_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"extra_domains":{"type":"array","items":{"type":"string"}},"multi_domain_mode":{"type":"string"},"timezone":{"type":"string"},"currency":{"type":"string"},"labels":{"type":"array","items":{"type":"string"}},"honor_dnt":{"type":"boolean"},"honor_gpc":{"type":"boolean"},"pii_scrubber":{"type":"boolean"},"redaction_rules":{"type":"array"},"allowed_params":{"type":"array","items":{"type":"string"}},"path_masks":{"type":"array"},"retention_months":{"anyOf":[{"type":"integer"},{"type":"null"}]},"bot_filtering":{"type":"boolean"},"traffic_rule_modes":{"type":"object"},"vitals_sample_rate":{"type":"integer"},"conversion_denominator":{"type":"string"},"public_dashboard":{"type":"boolean"},"public_indexable":{"type":"boolean"},"ingest_key_prefix":{"anyOf":[{"type":"string","description":"Start of the crawler log key"},{"type":"null"}]},"verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"first_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"domain_rating":{"anyOf":[{"type":"integer","description":"Domain Rating from 0 to 100, our own estimate of the strength of the domain's link profile. Null until the first check"},{"type":"null"}]},"snippet":{"type":"string","description":"HTML tracking snippet"},"favorite":{"type":"boolean","description":"Starred by you"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"sites_unfavorite","x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/setup.json":{"get":{"operationId":"sites_setup_get","summary":"Installation status and snippet for a site","description":"Returns what is needed to install tracking on a site and whether data has arrived. Fields are site_id, snippet (the ready-to-paste HTML script tag with every tracker module enabled), receiving_data (true once the first event has been received) and first_event_at (ISO 8601, null until then). Poll this after installing to see if events are coming in. Use tracking_snippet instead when you want a customized snippet (chosen modules, manual pageviews, SPA mode, masks) and tracking_verify to fetch the live page and check the script is present. Requires analytics.read.","tags":["Sites"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"sites_setup_get","x-permission":"analytics.read"}},"/transfers/{token}/accept.json":{"post":{"operationId":"site_transfers_accept","summary":"Accept a site transfer into one of your workspaces","description":"Accepts a site transfer invitation and moves the site into one of the caller's workspaces. The token path parameter is from the invitation link, and workspace_id is the destination workspace (ws_...) in which the caller has sites.manage. The caller's own email must match the address the invitation was sent to, and the destination cannot be the workspace the site came from. The site keeps its id, settings, goals and data, but per-member access grants are cleared and its shared links move to the new workspace. It fails when the invitation is no longer pending or has expired, when the destination is at its plan's site limit, or when it already has an active site with the same domain. The move cannot be undone except by transferring back. A token calling this must belong to the destination workspace and have sites.manage. Returns the transfer with status accepted.","tags":["Sites"],"parameters":[{"name":"token","in":"path","required":true,"description":"Site transfer token, from the transfer link","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string","description":"Site being transferred"},"site_domain":{"type":"string"},"from_workspace":{"type":"string","description":"Current workspace name"},"to_workspace_id":{"anyOf":[{"type":"string","description":"Receiving workspace"},{"type":"null"}]},"to_email":{"type":"string","description":"Recipient email"},"status":{"type":"string","description":"pending, accepted or canceled"},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-token-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"workspace_id":{"type":"string","description":"Public id (ws_..., from workspaces_list) of the workspace to move the site into. You need sites.manage there and it must differ from the current workspace."}},"required":["workspace_id"]}}}},"security":[]}},"/sites/{site_id}/transfer.json":{"post":{"operationId":"sites_transfer_start","summary":"Start transferring a site to another workspace (emails the recipient)","description":"Starts moving a site to another workspace by emailing the recipient an invitation link that is valid for 7 days. Nothing moves until the recipient signs in with that email and accepts (site_transfers_accept), so the site stays here until then. Starting a new transfer cancels any earlier pending one for the same site. email must be a valid address and the recipient picks the destination workspace. Transfer emails are rate limited. Use sites_transfer_cancel to withdraw it. Requires sites.manage. Returns the transfer with site_id, site_domain, from_workspace, to_email, status pending and expires_at.","tags":["Sites"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string","description":"Site being transferred"},"site_domain":{"type":"string"},"from_workspace":{"type":"string","description":"Current workspace name"},"to_workspace_id":{"anyOf":[{"type":"string","description":"Receiving workspace"},{"type":"null"}]},"to_email":{"type":"string","description":"Recipient email"},"status":{"type":"string","description":"pending, accepted or canceled"},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","description":"Email address of the recipient. They get a link valid for 7 days and choose one of their own workspaces when accepting."}},"required":["email"]}}}}},"delete":{"operationId":"sites_transfer_cancel","summary":"Cancel a pending site transfer","description":"Cancels the site's pending transfer invitation so its link stops working. It fails with a validation error when no transfer is pending. A transfer that was already accepted cannot be canceled. Requires sites.manage. Returns the transfer with status canceled.","tags":["Sites"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string","description":"Site being transferred"},"site_domain":{"type":"string"},"from_workspace":{"type":"string","description":"Current workspace name"},"to_workspace_id":{"anyOf":[{"type":"string","description":"Receiving workspace"},{"type":"null"}]},"to_email":{"type":"string","description":"Recipient email"},"status":{"type":"string","description":"pending, accepted or canceled"},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/transfers/{token}.json":{"get":{"operationId":"site_transfers_get","summary":"Get a pending transfer from its emailed token","description":"Shows a site transfer invitation from the token in its link (the token path parameter, from the invitation email sent by sites_transfer_start). The caller must be signed in or use an API token. Returns site_id, site_domain, from_workspace (the sending workspace's name), to_workspace_id (null until accepted), to_email (the invited address), status (pending, accepted or canceled) and expires_at. Invitations expire 7 days after they are sent. Use site_transfers_accept to accept it.","tags":["Sites"],"parameters":[{"name":"token","in":"path","required":true,"description":"Site transfer token, from the transfer link","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string","description":"Site being transferred"},"site_domain":{"type":"string"},"from_workspace":{"type":"string","description":"Current workspace name"},"to_workspace_id":{"anyOf":[{"type":"string","description":"Receiving workspace"},{"type":"null"}]},"to_email":{"type":"string","description":"Recipient email"},"status":{"type":"string","description":"pending, accepted or canceled"},"expires_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/workspaces/{workspace_id}/sites.json":{"post":{"operationId":"sites_create","summary":"Add a site","description":"Adds a website to a workspace and returns it, including the tracking snippet to install. The workspace's plan limits the number of sites (Free allows 3) and the call fails with a plan-limit error when it is reached. domain is required and is normalized (for example a full URL or www prefix is reduced to the hostname). name defaults to the domain, timezone defaults to the workspace's timezone (an IANA name such as Europe/Berlin) and currency to the workspace currency (a 3-letter ISO 4217 code such as USD). Side effects are a site.created notification to the workspace's notification channels, a first SEO site audit and domain rating check being queued, and an email with the tracking code to the member who created it (with reminders while no data arrives). Members limited to selected sites who opted into future sites get access to it. Requires sites.manage. Follow up with tracking_snippet or sites_setup_get to install, and tracking_verify to check.","tags":["Sites"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Site id used in the tracking snippet"},"workspace_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"extra_domains":{"type":"array","items":{"type":"string"}},"multi_domain_mode":{"type":"string"},"timezone":{"type":"string"},"currency":{"type":"string"},"labels":{"type":"array","items":{"type":"string"}},"honor_dnt":{"type":"boolean"},"honor_gpc":{"type":"boolean"},"pii_scrubber":{"type":"boolean"},"redaction_rules":{"type":"array"},"allowed_params":{"type":"array","items":{"type":"string"}},"path_masks":{"type":"array"},"retention_months":{"anyOf":[{"type":"integer"},{"type":"null"}]},"bot_filtering":{"type":"boolean"},"traffic_rule_modes":{"type":"object"},"vitals_sample_rate":{"type":"integer"},"conversion_denominator":{"type":"string"},"public_dashboard":{"type":"boolean"},"public_indexable":{"type":"boolean"},"ingest_key_prefix":{"anyOf":[{"type":"string","description":"Start of the crawler log key"},{"type":"null"}]},"verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"first_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"domain_rating":{"anyOf":[{"type":"integer","description":"Domain Rating from 0 to 100, our own estimate of the strength of the domain's link profile. Null until the first check"},{"type":"null"}]},"snippet":{"type":"string","description":"HTML tracking snippet"},"favorite":{"type":"boolean","description":"Starred by you"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"sites_create","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string","description":"Primary domain such as example.com. A URL or www prefix is reduced to the hostname.","examples":["example.com"]},"name":{"type":"string","description":"Display name. Defaults to the normalized domain."},"timezone":{"type":"string","description":"IANA timezone name such as Europe/Berlin or America/New_York. Defaults to the workspace timezone."},"currency":{"type":"string","description":"3-letter ISO 4217 code such as USD or EUR used for revenue. Defaults to the workspace currency."}},"required":["domain"]}}}}},"get":{"operationId":"sites_list","summary":"List sites in a workspace","description":"Lists the sites of a workspace that the caller can access, paginated, with the caller's starred sites first. Use query to search domain or name (partial, case-insensitive), label to keep sites that carry one label, and sort as position (the saved order, the default), name or visitors (visitors in the last 30 days, most first). The response meta has per-page pagination plus stats, an object keyed by site id with visitors (recent unique visitors), change (percent change against the previous period), sparkline (a list of daily values) and live (current visitors), totals across the page, and labels (every label of the sites the caller can access, sorted). Each item has the same fields as sites_get. This is the starting point for finding the site ids (pa_...) used by every other site tool. Requires analytics.read.","tags":["Sites"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Partial, case-insensitive match on domain or name."}},{"name":"label","in":"query","required":false,"schema":{"type":"string","description":"Only sites that carry this exact label."}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"position (your saved order, default), name (A to Z) or visitors (unique visitors in the last 30 days, most first). Starred sites always come first.","enum":["position","name","visitors"],"default":"position"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Site id used in the tracking snippet"},"workspace_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"extra_domains":{"type":"array","items":{"type":"string"}},"multi_domain_mode":{"type":"string"},"timezone":{"type":"string"},"currency":{"type":"string"},"labels":{"type":"array","items":{"type":"string"}},"honor_dnt":{"type":"boolean"},"honor_gpc":{"type":"boolean"},"pii_scrubber":{"type":"boolean"},"redaction_rules":{"type":"array"},"allowed_params":{"type":"array","items":{"type":"string"}},"path_masks":{"type":"array"},"retention_months":{"anyOf":[{"type":"integer"},{"type":"null"}]},"bot_filtering":{"type":"boolean"},"traffic_rule_modes":{"type":"object"},"vitals_sample_rate":{"type":"integer"},"conversion_denominator":{"type":"string"},"public_dashboard":{"type":"boolean"},"public_indexable":{"type":"boolean"},"ingest_key_prefix":{"anyOf":[{"type":"string","description":"Start of the crawler log key"},{"type":"null"}]},"verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"first_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"domain_rating":{"anyOf":[{"type":"integer","description":"Domain Rating from 0 to 100, our own estimate of the strength of the domain's link profile. Null until the first check"},{"type":"null"}]},"snippet":{"type":"string","description":"HTML tracking snippet"},"favorite":{"type":"boolean","description":"Starred by you"},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"sites_list","x-permission":"analytics.read"}},"/sites/{id}.json":{"delete":{"operationId":"sites_delete","summary":"Delete a site (purged after 7 days)","description":"Deletes a site. It is a soft delete, the site stops collecting and disappears from lists immediately, and its data is permanently purged after 7 days, so treat it as irreversible and contact support quickly if it was a mistake. confirm must be the site's domain (case does not matter). Pending transfers for the site are canceled and a site.deleted notification is sent to the workspace's notification channels. To clear only some traffic and keep the site use sites_reset_data. Requires sites.manage. Returns the site.","tags":["Sites"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by sites_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Site id used in the tracking snippet"},"workspace_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"extra_domains":{"type":"array","items":{"type":"string"}},"multi_domain_mode":{"type":"string"},"timezone":{"type":"string"},"currency":{"type":"string"},"labels":{"type":"array","items":{"type":"string"}},"honor_dnt":{"type":"boolean"},"honor_gpc":{"type":"boolean"},"pii_scrubber":{"type":"boolean"},"redaction_rules":{"type":"array"},"allowed_params":{"type":"array","items":{"type":"string"}},"path_masks":{"type":"array"},"retention_months":{"anyOf":[{"type":"integer"},{"type":"null"}]},"bot_filtering":{"type":"boolean"},"traffic_rule_modes":{"type":"object"},"vitals_sample_rate":{"type":"integer"},"conversion_denominator":{"type":"string"},"public_dashboard":{"type":"boolean"},"public_indexable":{"type":"boolean"},"ingest_key_prefix":{"anyOf":[{"type":"string","description":"Start of the crawler log key"},{"type":"null"}]},"verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"first_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"domain_rating":{"anyOf":[{"type":"integer","description":"Domain Rating from 0 to 100, our own estimate of the strength of the domain's link profile. Null until the first check"},{"type":"null"}]},"snippet":{"type":"string","description":"HTML tracking snippet"},"favorite":{"type":"boolean","description":"Starred by you"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"string","description":"The site's domain exactly as shown by sites_get, for example example.com. Case does not matter."}},"required":["confirm"]}}}}},"get":{"operationId":"sites_get","summary":"Get a site and all its settings","description":"Returns one site's settings and status by its public id (pa_..., from sites_list). Key fields are id, workspace_id (ws_...), domain, name, extra_domains and multi_domain_mode (combined or separate), timezone (IANA name), currency (ISO 4217), labels, privacy options (honor_dnt, honor_gpc, pii_scrubber, redaction_rules, allowed_params, path_masks), retention_months (null means keep all data), bot_filtering, traffic_rule_modes (an object mapping a rule list to block or allow), vitals_sample_rate (a percentage), conversion_denominator (visits or visitors), public_dashboard and public_indexable, ingest_key_prefix (null when the site has no crawler log key), verified_at, first_event_at and last_event_at (null until data arrives), domain_rating (nullable), snippet (the HTML tracking tag), favorite (whether the caller starred it) and created_at. Requires analytics.read.","tags":["Sites"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by sites_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Site id used in the tracking snippet"},"workspace_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"extra_domains":{"type":"array","items":{"type":"string"}},"multi_domain_mode":{"type":"string"},"timezone":{"type":"string"},"currency":{"type":"string"},"labels":{"type":"array","items":{"type":"string"}},"honor_dnt":{"type":"boolean"},"honor_gpc":{"type":"boolean"},"pii_scrubber":{"type":"boolean"},"redaction_rules":{"type":"array"},"allowed_params":{"type":"array","items":{"type":"string"}},"path_masks":{"type":"array"},"retention_months":{"anyOf":[{"type":"integer"},{"type":"null"}]},"bot_filtering":{"type":"boolean"},"traffic_rule_modes":{"type":"object"},"vitals_sample_rate":{"type":"integer"},"conversion_denominator":{"type":"string"},"public_dashboard":{"type":"boolean"},"public_indexable":{"type":"boolean"},"ingest_key_prefix":{"anyOf":[{"type":"string","description":"Start of the crawler log key"},{"type":"null"}]},"verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"first_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"domain_rating":{"anyOf":[{"type":"integer","description":"Domain Rating from 0 to 100, our own estimate of the strength of the domain's link profile. Null until the first check"},{"type":"null"}]},"snippet":{"type":"string","description":"HTML tracking snippet"},"favorite":{"type":"boolean","description":"Starred by you"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"sites_get","x-permission":"analytics.read"},"patch":{"operationId":"sites_update","summary":"Update site settings","description":"Updates settings of a site, changing only the fields you send. Name and identity fields are name, domain (changing it re-checks the domain rating), extra_domains (a list of hostnames) and multi_domain_mode (combined counts one visitor across domains, separate keeps them apart). timezone is an IANA name and currency a 3-letter ISO 4217 code. Privacy fields are honor_dnt, honor_gpc, pii_scrubber, redaction_rules (a list of objects with name and pattern, pattern a regular expression), allowed_params (query parameters to keep), path_masks (a list of objects with pattern and replacement) and bot_filtering. Lists replace the whole existing list. retention_months must not exceed the plan's retention (Free 3 months). traffic_rule_modes maps a rule list (hostnames, paths, referrers, countries, ip_ranges, user_agents or events) to block or allow. vitals_sample_rate is a percentage and the plan caps it (10 on Free, 100 on paid plans). conversion_denominator is visits or visitors. public_dashboard makes stats viewable by anyone with the link and public_indexable lets search engines index that page. Changes take effect for new events within moments. Requires sites.manage. Returns the updated site.","tags":["Sites"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by sites_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Site id used in the tracking snippet"},"workspace_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"extra_domains":{"type":"array","items":{"type":"string"}},"multi_domain_mode":{"type":"string"},"timezone":{"type":"string"},"currency":{"type":"string"},"labels":{"type":"array","items":{"type":"string"}},"honor_dnt":{"type":"boolean"},"honor_gpc":{"type":"boolean"},"pii_scrubber":{"type":"boolean"},"redaction_rules":{"type":"array"},"allowed_params":{"type":"array","items":{"type":"string"}},"path_masks":{"type":"array"},"retention_months":{"anyOf":[{"type":"integer"},{"type":"null"}]},"bot_filtering":{"type":"boolean"},"traffic_rule_modes":{"type":"object"},"vitals_sample_rate":{"type":"integer"},"conversion_denominator":{"type":"string"},"public_dashboard":{"type":"boolean"},"public_indexable":{"type":"boolean"},"ingest_key_prefix":{"anyOf":[{"type":"string","description":"Start of the crawler log key"},{"type":"null"}]},"verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"first_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"domain_rating":{"anyOf":[{"type":"integer","description":"Domain Rating from 0 to 100, our own estimate of the strength of the domain's link profile. Null until the first check"},{"type":"null"}]},"snippet":{"type":"string","description":"HTML tracking snippet"},"favorite":{"type":"boolean","description":"Starred by you"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"sites_update","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Display name."},"domain":{"type":"string","description":"Primary domain such as example.com. Changing it triggers a new domain rating check."},"extra_domains":{"type":"array","items":{"type":"string"},"description":"Additional hostnames that send data to this site, for example [blog.example.com]. Replaces the current list."},"multi_domain_mode":{"type":"string","description":"combined counts one visitor across all domains of the site, separate keeps them apart.","enum":["combined","separate"]},"timezone":{"type":"string","description":"IANA timezone name such as Europe/Berlin. Dates and day boundaries in reports use it."},"currency":{"type":"string","description":"3-letter ISO 4217 code such as USD or EUR."},"labels":{"type":"array","items":{"type":"string"},"description":"Free-form labels used to group sites in sites_list. Replaces the current list."},"honor_dnt":{"type":"boolean","description":"true skips visitors who send Do Not Track."},"honor_gpc":{"type":"boolean","description":"true skips visitors who send Global Privacy Control."},"pii_scrubber":{"type":"boolean","description":"true redacts emails, tokens and long ids from URLs before storing."},"redaction_rules":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"pattern":{"type":"string"}}},"description":"Extra redaction rules as a list of objects with name and pattern, where pattern is a regular expression. Rows with an empty pattern are dropped and an invalid regex is refused. Replaces the current list."},"allowed_params":{"type":"array","items":{"type":"string"},"description":"Query parameter names kept on stored paths, for example [page, q]. Others are dropped. Replaces the current list."},"path_masks":{"type":"array","items":{"type":"object","properties":{"pattern":{"type":"string"},"replacement":{"type":"string"}}},"description":"Path masking rules as a list of objects with pattern and replacement, for example pattern /users/* and replacement /users/:id. Replaces the current list."},"retention_months":{"type":"integer","description":"Delete raw data older than this many months. Cannot exceed the plan's retention (Free allows 3). Omit to leave it unchanged."},"bot_filtering":{"type":"boolean","description":"true drops bot and data-center traffic."},"traffic_rule_modes":{"type":"object","additionalProperties":true,"description":"Object mapping a rule list to block or allow, for example {\"countries\":\"block\"}. List names are hostnames, paths, referrers, countries, ip_ranges, user_agents and events."},"vitals_sample_rate":{"type":"integer","description":"Percentage from 0 to 100 of visits that report Web Vitals. The plan caps it (10 on Free, 100 on paid plans)."},"conversion_denominator":{"type":"string","description":"visits or visitors. Conversion rates are divided by this count.","enum":["visits","visitors"]},"public_dashboard":{"type":"boolean","description":"true lets anyone with the site's public link view its stats."},"public_indexable":{"type":"boolean","description":"true lets search engines index the public page. Only matters when public_dashboard is true."}}}}}}}},"/sponsor/{token}.json":{"get":{"operationId":"ad_reports_get","summary":"A sponsor report, by its link's token","tags":["Sponsor report"],"parameters":[{"name":"token","in":"path","required":true,"description":"The token in the link's address","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"7d, 30d (default) or 90d","enum":["7d","30d","90d"],"default":"30d"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"name":{"type":"string","description":"Who the report is for"},"placement":{"type":"string","description":"The placement's name"},"period":{"type":"string","description":"7d, 30d or 90d"},"humans_only":{"type":"boolean","description":"Whether only likely humans are counted"},"from":{"type":"string","description":"First day"},"to":{"type":"string","description":"Last day"},"expires_at":{"anyOf":[{"type":"string","description":"When the link stops working, or null"},{"type":"null"}]},"creatives":{"type":"array","items":{"type":"object"},"description":"Each creative: name, image, impressions, viewable, clicks, ctr"},"daily":{"type":"array","items":{"type":"object"},"description":"Each day: date, impressions, viewable, clicks, ctr"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/sites/{site_id}/experiments/ads/{ad_placement_id}/reports.json":{"post":{"operationId":"ad_report_links_create","summary":"Create a sponsor report link for a placement","description":"A read-only link to the placement's numbers, for all of its creatives or the ones listed in creative_ids, for someone with no account. Over MCP the member is emailed that a link was made. Pro and up. Requires content.write. Returns the link with its url.","tags":["Sponsor reports"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"ad_placement_id","in":"path","required":true,"description":"Ad placement id (adp_...), from ad_placements_list","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Link id, e.g. adr_7Q2K9XH3AB"},"placement_id":{"type":"string","description":"Its placement (adp_...)"},"name":{"type":"string","description":"Who the report is for"},"url":{"type":"string","description":"The report's address"},"creative_ids":{"type":"array","items":{"type":"string"},"description":"The creatives it shows. Empty means all"},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it stops working, or null"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"ad_report_links_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Who the report is for, such as Acme (sponsor), max 120 characters"},"creative_ids":{"type":"array","items":{"type":"string"},"description":"Only these creatives (adc_...). Empty means all of the placement's","default":[]},"expires_at":{"type":"string","format":"date-time","description":"When the link stops working, ISO 8601. Empty means never"}},"required":["name"]}}}}},"get":{"operationId":"ad_report_links_list","summary":"List a placement's sponsor report links","description":"The links, with their address and when they expire. Requires analytics.read.","tags":["Sponsor reports"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"ad_placement_id","in":"path","required":true,"description":"Ad placement id (adp_...), from ad_placements_list","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Link id, e.g. adr_7Q2K9XH3AB"},"placement_id":{"type":"string","description":"Its placement (adp_...)"},"name":{"type":"string","description":"Who the report is for"},"url":{"type":"string","description":"The report's address"},"creative_ids":{"type":"array","items":{"type":"string"},"description":"The creatives it shows. Empty means all"},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it stops working, or null"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"ad_report_links_list","x-permission":"analytics.read"}},"/sites/{site_id}/experiments/ads/{ad_placement_id}/reports/{id}.json":{"delete":{"operationId":"ad_report_links_delete","summary":"Delete a sponsor report link","description":"The address stops working at once. The MCP tool does not run it and responds with human_only and the page where a person deletes it. Requires content.write.","tags":["Sponsor reports"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"ad_placement_id","in":"path","required":true,"description":"Ad placement id (adp_...), from ad_placements_list","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by ad_report_links_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Link id, e.g. adr_7Q2K9XH3AB"},"placement_id":{"type":"string","description":"Its placement (adp_...)"},"name":{"type":"string","description":"Who the report is for"},"url":{"type":"string","description":"The report's address"},"creative_ids":{"type":"array","items":{"type":"string"},"description":"The creatives it shows. Empty means all"},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it stops working, or null"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/status/{slug}/confirm/{token}.json":{"get":{"operationId":"public_status_pages_confirm","summary":"Confirm a subscription from the emailed link","tags":["Status pages"],"parameters":[{"name":"slug","in":"path","required":true,"description":"Post slug, the last part of /blog/<slug>, from blog_list","schema":{"type":"string"}},{"name":"token","in":"path","required":true,"description":"Confirmation token from the email","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/status/{slug}.json":{"get":{"operationId":"public_status_pages_get","summary":"Public status page: current status, 90-day uptime bars, incidents and posts","tags":["Status pages"],"parameters":[{"name":"slug","in":"path","required":true,"description":"Post slug, the last part of /blog/<slug>, from blog_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"name":{"type":"string"},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}]},"brand_color":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","description":"operational, degraded or outage"},"checks":{"type":"array","description":"Each: {name, status, uptime_90d, days: [{date, uptime, downtime_seconds}]}"},"posts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Post id (spp_…)"},"title":{"type":"string"},"body":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","description":"investigating, identified, monitoring or resolved"},"posted_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"incidents":{"type":"array","description":"Recent incidents: {check, started_at, resolved_at, duration_seconds}"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/status/{slug}/subscribers.json":{"post":{"operationId":"public_status_pages_subscribe","summary":"Subscribe an email address (double opt-in)","description":"Browser clients send a Cloudflare Turnstile token as `cf-turnstile-response`. Requests with an API token need none.","tags":["Status pages"],"parameters":[{"name":"slug","in":"path","required":true,"description":"Post slug, the last part of /blog/<slug>, from blog_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","description":"Email address to notify","examples":["you@example.com"]}},"required":["email"]}}}},"security":[]}},"/status/{slug}/unsubscribe/{token}.json":{"post":{"operationId":"public_status_pages_unsubscribe","summary":"Unsubscribe with the emailed token","tags":["Status pages"],"parameters":[{"name":"slug","in":"path","required":true,"description":"Post slug, the last part of /blog/<slug>, from blog_list","schema":{"type":"string"}},{"name":"token","in":"path","required":true,"description":"Unsubscribe token from the email","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Unsubscribe token from the email"}},"required":["token"]}}}},"security":[]}},"/status_pages/{status_page_id}/posts.json":{"post":{"operationId":"status_page_posts_create","summary":"Post an incident update (emails subscribers)","description":"Publishes an incident update on a status page and, by default, emails its confirmed subscribers. Choose it to announce or update an incident, and use status_page_posts_update to move an existing incident along (for example to resolved) instead of creating a new post. Required is title (max 200 characters). status is one of investigating (default), identified, monitoring or resolved. body is plain text (max 10,000 characters), posted_at is an ISO 8601 time that defaults to now, and notify (default true) controls the email. Emails are only sent for a published page and are rate limited per page, over the limit the post is still published but nobody is emailed. The status_page_id comes from status_pages_list. Needs the uptime.manage permission. Returns the post with id (spp_...), title, body, status, posted_at and updated_at.","tags":["Status pages"],"parameters":[{"name":"status_page_id","in":"path","required":true,"description":"Status page id, from status_pages_list","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Post id (spp_…)"},"title":{"type":"string"},"body":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","description":"investigating, identified, monitoring or resolved"},"posted_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"status_page_posts_create","x-permission":"uptime.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"Headline of the update, max 200 characters"},"body":{"type":"string","description":"Update text, plain text, max 10,000 characters"},"status":{"type":"string","description":"investigating, identified, monitoring or resolved","enum":["investigating","identified","monitoring","resolved"],"default":"investigating"},"posted_at":{"type":"string","format":"date-time","description":"When it happened, ISO 8601 time like 2026-10-02T14:30:00Z. Defaults to now. Posts are sorted by this time"},"notify":{"type":"boolean","description":"Email confirmed subscribers of a published page. Default true","default":true}},"required":["title"]}}}}},"get":{"operationId":"status_page_posts_list","summary":"List posts on a status page","description":"Lists the incident posts of a status page, newest first by posted_at. Use it to find a post id or see the incident history. Optionally filter by status (investigating, identified, monitoring or resolved). Paginated with page and per_page (up to 100). Each post has id (spp_...), title, body (null when empty), status, posted_at and updated_at. The status_page_id comes from status_pages_list.","tags":["Status pages"],"parameters":[{"name":"status_page_id","in":"path","required":true,"description":"Status page id, from status_pages_list","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Only posts with this status","enum":["investigating","identified","monitoring","resolved"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Post id (spp_…)"},"title":{"type":"string"},"body":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","description":"investigating, identified, monitoring or resolved"},"posted_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"status_page_posts_list","x-permission":"analytics.read"}},"/status_pages/{status_page_id}/posts/{id}.json":{"delete":{"operationId":"status_page_posts_delete","summary":"Delete a status page post","description":"Permanently deletes an incident post from a status page. It disappears from the public page at once and this cannot be undone. No email is sent. The id comes from status_page_posts_list. Needs the uptime.manage permission. Returns the deleted post.","tags":["Status pages"],"parameters":[{"name":"status_page_id","in":"path","required":true,"description":"Status page id, from status_pages_list","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by status_page_posts_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Post id (spp_…)"},"title":{"type":"string"},"body":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","description":"investigating, identified, monitoring or resolved"},"posted_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"status_page_posts_delete","x-permission":"uptime.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"patch":{"operationId":"status_page_posts_update","summary":"Edit a status page post","description":"Edits an incident post. Only the inputs you send change, so send just status to resolve an incident. Subscribers are emailed only when the status actually changes and notify is not false (default true). Editing the title or body alone sends no email. Emails go to confirmed subscribers of a published page and are rate limited per page. Valid status values are investigating, identified, monitoring and resolved. The id comes from status_page_posts_list. Needs the uptime.manage permission. Returns the updated post.","tags":["Status pages"],"parameters":[{"name":"status_page_id","in":"path","required":true,"description":"Status page id, from status_pages_list","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by status_page_posts_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Post id (spp_…)"},"title":{"type":"string"},"body":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","description":"investigating, identified, monitoring or resolved"},"posted_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"status_page_posts_update","x-permission":"uptime.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"New headline, max 200 characters"},"body":{"type":"string","description":"New update text, plain text, max 10,000 characters"},"status":{"type":"string","description":"investigating, identified, monitoring or resolved","enum":["investigating","identified","monitoring","resolved"]},"notify":{"type":"boolean","description":"Email confirmed subscribers when the status changes. Default true. No email is sent when only the title or body changes","default":true}}}}}}}},"/status_pages/{status_page_id}/subscribers/{id}.json":{"delete":{"operationId":"status_page_subscribers_delete","summary":"Remove a subscriber","description":"Removes an email subscriber from a status page so they stop receiving incident and uptime emails. This cannot be undone, but the person can subscribe again on the public page. The id is the subscriber id from status_page_subscribers_list (a plain UUID, not a prefixed id). Needs the uptime.manage permission. Returns the removed subscriber.","tags":["Status pages"],"parameters":[{"name":"status_page_id","in":"path","required":true,"description":"Status page id, from status_pages_list","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by status_page_subscribers_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"status_page_subscribers_delete","x-permission":"uptime.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/status_pages/{status_page_id}/subscribers.json":{"get":{"operationId":"status_page_subscribers_list","summary":"List subscribers of a status page","description":"Lists the email subscribers of a status page, sorted by email. Use confirmed true to see only people who confirmed their address (only they receive emails) or confirmed false for pending ones. Paginated with page and per_page (up to 100). Each item has id (a UUID, used by status_page_subscribers_delete), email, confirmed_at (null while pending) and created_at. The status_page_id comes from status_pages_list. Needs the uptime.manage permission and returns personal data (email addresses). Needs the Business or Enterprise plan (402 plan_limit otherwise).","tags":["Status pages"],"parameters":[{"name":"status_page_id","in":"path","required":true,"description":"Status page id, from status_pages_list","schema":{"type":"string"}},{"name":"confirmed","in":"query","required":false,"schema":{"type":"boolean","description":"true returns only confirmed subscribers (the ones who receive emails), false only pending ones, omit for all"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"status_page_subscribers_list","x-permission":"uptime.manage"}},"/workspaces/{workspace_id}/status_pages.json":{"post":{"operationId":"status_pages_create","summary":"Create a status page","description":"Creates a public status page for a workspace that shows chosen uptime checks, incident posts and an email signup. Required is name (max 100 characters). slug (lowercase letters, digits and hyphens, unique across all workspaces) defaults from the name and the page is served at /status/<slug>. check_ids lists the uptime checks to show (upc_... ids from uptime_checks_list) and only checks created with public true are accepted. published defaults to true, so the page is visible to everyone immediately. Optional branding is description (max 2,000 characters), logo_url (must be https), brand_color (hex like #06755b) and custom_domain (a hostname you point a CNAME at the app, unique). Use status_page_posts_create to publish incidents afterwards. Needs the uptime.manage permission. Returns the page with id (sp_...), slug, check_ids and subscribers (count of confirmed subscribers). The plan sets how many pages a workspace has: none on Free (402 plan_limit), 1 on Pro and 10 on Business. A custom_domain and email subscribers need the Business or Enterprise plan. Pages over the plan's count are kept and offline.","tags":["Status pages"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Status page id (sp_…)"},"workspace_id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string","description":"Public URL: /status/<slug>"},"custom_domain":{"anyOf":[{"type":"string"},{"type":"null"}]},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}]},"brand_color":{"anyOf":[{"type":"string"},{"type":"null"}]},"published":{"type":"boolean"},"check_ids":{"type":"array","items":{"type":"string"},"description":"Uptime check ids shown"},"checks":{"type":"array","items":{"type":"object"},"description":"The checks shown, in the order of the page: [{id, name, status}], with status up, down, pending or paused"},"locked":{"type":"boolean","description":"True when the page is over the number of status pages the plan includes, so it is kept and offline"},"site_verified":{"type":"boolean","description":"Whether a site of the workspace is verified (its tracking script was found on its own domain). Until one is, the public page responds 404, and a custom domain works only on that site's domain or a subdomain of it"},"subscribers":{"type":"integer","description":"Confirmed subscribers"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"status_pages_create","x-permission":"uptime.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Page title, e.g. \"Acme status\""},"slug":{"type":"string","description":"Public URL slug, served at /status/<slug>. Lowercase letters, digits and hyphens, up to 63 characters, unique across all workspaces. Defaults to the name"},"description":{"type":"string","description":"Intro text under the title"},"logo_url":{"type":"string","description":"HTTPS URL of a logo image, max 2048 characters"},"brand_color":{"type":"string","description":"Accent color as a six digit hex value with a leading hash, like #06755b"},"custom_domain":{"type":"string","description":"Hostname without scheme or path, like status.example.com, pointed with a CNAME at the app. Must be unique"},"check_ids":{"type":"array","items":{"type":"string"},"description":"Ids of uptime checks to show, like upc_... (from uptime_checks_list). Only checks created with public true are accepted. Empty list shows none"},"published":{"type":"boolean","description":"Whether the page is visible to the public. Default true","default":true}},"required":["name"]}}}}},"get":{"operationId":"status_pages_list","summary":"List status pages","description":"Lists the status pages of a workspace sorted by name. Use query to match part of a name or slug. When the caller is limited to some sites, only pages whose checks are all within those sites are returned. Paginated with page and per_page (up to 100). Each item has the fields described in status_pages_get. Needs the workspace_id from workspaces_list.","tags":["Status pages"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Filter by name or slug"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Status page id (sp_…)"},"workspace_id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string","description":"Public URL: /status/<slug>"},"custom_domain":{"anyOf":[{"type":"string"},{"type":"null"}]},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}]},"brand_color":{"anyOf":[{"type":"string"},{"type":"null"}]},"published":{"type":"boolean"},"check_ids":{"type":"array","items":{"type":"string"},"description":"Uptime check ids shown"},"checks":{"type":"array","items":{"type":"object"},"description":"The checks shown, in the order of the page: [{id, name, status}], with status up, down, pending or paused"},"locked":{"type":"boolean","description":"True when the page is over the number of status pages the plan includes, so it is kept and offline"},"site_verified":{"type":"boolean","description":"Whether a site of the workspace is verified (its tracking script was found on its own domain). Until one is, the public page responds 404, and a custom domain works only on that site's domain or a subdomain of it"},"subscribers":{"type":"integer","description":"Confirmed subscribers"},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"status_pages_list","x-permission":"analytics.read"}},"/status_pages/{id}.json":{"delete":{"operationId":"status_pages_delete","summary":"Delete a status page","description":"Permanently deletes a status page together with all its incident posts and subscribers. The public page and its custom domain stop working at once and this cannot be undone. The uptime checks themselves are not deleted. The id comes from status_pages_list. Needs the uptime.manage permission. Returns the deleted page.","tags":["Status pages"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by status_pages_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Status page id (sp_…)"},"workspace_id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string","description":"Public URL: /status/<slug>"},"custom_domain":{"anyOf":[{"type":"string"},{"type":"null"}]},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}]},"brand_color":{"anyOf":[{"type":"string"},{"type":"null"}]},"published":{"type":"boolean"},"check_ids":{"type":"array","items":{"type":"string"},"description":"Uptime check ids shown"},"checks":{"type":"array","items":{"type":"object"},"description":"The checks shown, in the order of the page: [{id, name, status}], with status up, down, pending or paused"},"locked":{"type":"boolean","description":"True when the page is over the number of status pages the plan includes, so it is kept and offline"},"site_verified":{"type":"boolean","description":"Whether a site of the workspace is verified (its tracking script was found on its own domain). Until one is, the public page responds 404, and a custom domain works only on that site's domain or a subdomain of it"},"subscribers":{"type":"integer","description":"Confirmed subscribers"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"status_pages_delete","x-permission":"uptime.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"status_pages_get","summary":"Get a status page","description":"Returns one status page with its settings. Fields are id (sp_...), workspace_id, name, slug, custom_domain (null when none), description, logo_url, brand_color, published, check_ids (uptime check ids shown on the page), checks (the same checks as {id, name, status}), locked (true when the page is over the number of status pages the plan includes), subscribers (count of confirmed email subscribers) and created_at. Use status_page_posts_list for its incidents and status_page_subscribers_list for the people. The id comes from status_pages_list.","tags":["Status pages"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by status_pages_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Status page id (sp_…)"},"workspace_id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string","description":"Public URL: /status/<slug>"},"custom_domain":{"anyOf":[{"type":"string"},{"type":"null"}]},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}]},"brand_color":{"anyOf":[{"type":"string"},{"type":"null"}]},"published":{"type":"boolean"},"check_ids":{"type":"array","items":{"type":"string"},"description":"Uptime check ids shown"},"checks":{"type":"array","items":{"type":"object"},"description":"The checks shown, in the order of the page: [{id, name, status}], with status up, down, pending or paused"},"locked":{"type":"boolean","description":"True when the page is over the number of status pages the plan includes, so it is kept and offline"},"site_verified":{"type":"boolean","description":"Whether a site of the workspace is verified (its tracking script was found on its own domain). Until one is, the public page responds 404, and a custom domain works only on that site's domain or a subdomain of it"},"subscribers":{"type":"integer","description":"Confirmed subscribers"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"status_pages_get","x-permission":"analytics.read"},"patch":{"operationId":"status_pages_update","summary":"Change a status page","description":"Changes a status page. Only the inputs you send change, so send just published false to take the page offline or check_ids to replace the shown checks (the whole list is replaced, not merged). The inputs and their limits are the same as in status_pages_create. Send custom_domain as an empty string to remove the custom domain. Only checks with public true can be shown, and a caller limited to some sites can only put checks of those sites on a page. The id comes from status_pages_list. Needs the uptime.manage permission. Returns the updated page.","tags":["Status pages"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by status_pages_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Status page id (sp_…)"},"workspace_id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string","description":"Public URL: /status/<slug>"},"custom_domain":{"anyOf":[{"type":"string"},{"type":"null"}]},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}]},"brand_color":{"anyOf":[{"type":"string"},{"type":"null"}]},"published":{"type":"boolean"},"check_ids":{"type":"array","items":{"type":"string"},"description":"Uptime check ids shown"},"checks":{"type":"array","items":{"type":"object"},"description":"The checks shown, in the order of the page: [{id, name, status}], with status up, down, pending or paused"},"locked":{"type":"boolean","description":"True when the page is over the number of status pages the plan includes, so it is kept and offline"},"site_verified":{"type":"boolean","description":"Whether a site of the workspace is verified (its tracking script was found on its own domain). Until one is, the public page responds 404, and a custom domain works only on that site's domain or a subdomain of it"},"subscribers":{"type":"integer","description":"Confirmed subscribers"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"status_pages_update","x-permission":"uptime.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Page title, e.g. \"Acme status\""},"slug":{"type":"string","description":"New public URL slug, served at /status/<slug>. Lowercase letters, digits and hyphens, up to 63 characters, unique across all workspaces"},"description":{"type":"string","description":"Intro text under the title"},"logo_url":{"type":"string","description":"HTTPS URL of a logo image, max 2048 characters. Empty string removes it"},"brand_color":{"type":"string","description":"Accent color as a six digit hex value with a leading hash, like #06755b"},"custom_domain":{"type":"string","description":"Hostname without scheme or path, like status.example.com. Send an empty string to remove the custom domain"},"check_ids":{"type":"array","items":{"type":"string"},"description":"The full list of uptime check ids to show, like upc_... (from uptime_checks_list). Replaces the current list. Only checks with public true are accepted. Send an empty list to show none"},"published":{"type":"boolean","description":"Whether the page is visible to the public"}}}}}}}},"/sites/{site_id}/subscriptions/connections/{provider}.json":{"delete":{"operationId":"subscriptions_disconnect","summary":"Disconnect a payment provider and delete its key and subscription data","description":"Disconnects a payment provider (stripe, paddle, lemon_squeezy, chargebee or polar) from a site and permanently deletes the stored API key and every subscription row read from it. This cannot be undone, and MRR, churn and cohort numbers drop that provider's subscriptions immediately. Fails if that provider is not connected. Returns the removed connection. Needs sites.manage.","tags":["Subscriptions"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"provider","in":"path","required":true,"description":"Billing connection to remove: stripe, paddle, lemon_squeezy, chargebee or polar","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"provider":{"type":"string","description":"stripe, paddle, lemon_squeezy, chargebee or polar"},"account_name":{"anyOf":[{"type":"string","description":"The Lemon Squeezy store name or the Chargebee site name. Empty for Stripe, Paddle and Polar"},{"type":"null"}]},"sandbox":{"type":"boolean","description":"Whether the key is a test or sandbox key (a Chargebee test site, a Polar sandbox token)"},"status":{"type":"string","description":"active or error"},"last_error":{"anyOf":[{"type":"string","description":"Why the last sync failed: unauthorized, not_found, rate_limited, network or unexpected_response"},{"type":"null"}]},"last_synced_at":{"anyOf":[{"type":"string","format":"date-time","description":"When subscriptions were last read"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/subscriptions/sync.json":{"post":{"operationId":"subscriptions_sync","summary":"Read subscriptions from a payment provider now","description":"Queues an immediate sync of subscriptions from one connected provider (stripe, paddle, lemon_squeezy, chargebee or polar) instead of waiting for the regular schedule. It returns right away (HTTP 202) with the connection and the sync runs in the background. Poll subscriptions_report or check last_synced_at and last_error on the connection. Reports are cached for up to 15 minutes. Fails if the provider is not connected. Needs sites.manage.","tags":["Subscriptions"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"provider":{"type":"string","description":"stripe, paddle, lemon_squeezy, chargebee or polar"},"account_name":{"anyOf":[{"type":"string","description":"The Lemon Squeezy store name or the Chargebee site name. Empty for Stripe, Paddle and Polar"},{"type":"null"}]},"sandbox":{"type":"boolean","description":"Whether the key is a test or sandbox key (a Chargebee test site, a Polar sandbox token)"},"status":{"type":"string","description":"active or error"},"last_error":{"anyOf":[{"type":"string","description":"Why the last sync failed: unauthorized, not_found, rate_limited, network or unexpected_response"},{"type":"null"}]},"last_synced_at":{"anyOf":[{"type":"string","format":"date-time","description":"When subscriptions were last read"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"subscriptions_sync","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"provider":{"type":"string","description":"Connected payment provider to sync now: stripe, paddle, lemon_squeezy, chargebee or polar","enum":["stripe","paddle","lemon_squeezy","chargebee","polar"]}},"required":["provider"]}}}}}},"/sites/{site_id}/subscriptions/cohorts.json":{"get":{"operationId":"subscriptions_cohorts","summary":"Churn cohort grid: churn or retention by month of first payment","description":"The churn cohort grid for the site's subscriptions, one row per month of first payment. months is 6, 12 (default) or 24 cohorts. plan keeps only the subscriptions of one plan (see plans in subscriptions_report). metric is subscriptions (count) or mrr (money). view is churn (the share that had ended by that point, default) or retention (the share still running). Returns metric, view, months, plan (the filter, or null), currency and cohorts, each with month (YYYY-MM), size (subscriptions, or MRR in minor units of the site currency) and cells, where each cell has offset (months since the cohort month, 0 is the first), retained (same unit as size) and percent (0 to 100, null for an empty cohort). Trials that never paid are in no cohort. For headline MRR, ARR and churn use subscriptions_report. Needs analytics.read.","tags":["Subscriptions"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"months","in":"query","required":false,"schema":{"type":"integer","description":"Number of monthly cohorts to return, one of 6, 12 (default) or 24","enum":[6,12,24],"default":12}},{"name":"metric","in":"query","required":false,"schema":{"type":"string","description":"subscriptions (count of subscriptions, default) or mrr (monthly recurring revenue in minor units of the site currency)","enum":["subscriptions","mrr"],"default":"subscriptions"}},{"name":"view","in":"query","required":false,"schema":{"type":"string","description":"churn (percent of the cohort that had ended by that month, default) or retention (percent still running). The two add up to 100","enum":["churn","retention"],"default":"churn"}},{"name":"plan","in":"query","required":false,"schema":{"type":"string","description":"Only the subscriptions of this plan, named exactly as plans in subscriptions_report lists it, for example Pro monthly. Leave out for every plan"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"subscriptions_cohorts","x-permission":"analytics.read"}},"/sites/{site_id}/subscriptions.json":{"get":{"operationId":"subscriptions_report","summary":"Subscription metrics: MRR, ARR, MRR movements, churn, revenue retention, trials, plans and a forecast","description":"Subscription metrics for the site, read from its connected Stripe, Paddle, Lemon Squeezy, Chargebee or Polar account. months is 6, 12 (default) or 24. plan keeps only the subscriptions of one plan, named as plans lists it. Money fields are integers in minor units of the site currency (the response currency), with other currencies converted at today's rate. The result has currency, connected (false when no provider is connected), plan (the plan filter, or null), connections (one per connected provider with provider, account_name, sandbox, status, last_error, last_synced_at and created_at, never a key), skipped_currencies (currencies with no rate, whose money is not counted), totals, series, forecast and plans. totals has mrr_minor, arr_minor, previous_mrr_minor (MRR 30 days ago), active_subscriptions, arpa_minor (null with no subscriptions), trialing, trial_conversion_rate (percent of trials that ended in the last 90 days and paid, null when none ended), and for the last 30 days new_subscriptions, new_mrr_minor, expansion_mrr_minor, contraction_mrr_minor, churned_subscriptions, churned_mrr_minor, net_new_mrr_minor, quick_ratio (new plus expansion MRR for each unit of churned plus contraction MRR, null when nothing was lost), subscription_churn_rate and mrr_churn_rate (percent, null with no base). It also has net_revenue_retention and gross_revenue_retention (percent of what the subscriptions paying 12 months ago paid then that they pay now, with and without upgrades, null with no base) and forecast_mrr_minor (MRR in 12 months, null with no forecast). series has one row per month (month as YYYY-MM) with mrr_minor, active_subscriptions, the same movement fields and churn_rate. forecast has one row per month for the next 12 months (month, mrr_minor), projected from the last three full months, and is empty without three full months that started with MRR. plans lists up to 50 plans by MRR with plan (null for subscriptions the provider gave no plan name), mrr_minor, active_subscriptions, churned_subscriptions and subscription_churn_rate (last 30 days), always for every plan. A subscription counts from its first payment. Upgrades and downgrades are known from the first sync on, and before that past months use the price a subscription had when it was first read. For retention by month of first payment use subscriptions_cohorts. Needs analytics.read.","tags":["Subscriptions"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"months","in":"query","required":false,"schema":{"type":"integer","description":"Months in the monthly series, one of 6, 12 (default) or 24. The totals always cover now and the last 30 days","enum":[6,12,24],"default":12}},{"name":"plan","in":"query","required":false,"schema":{"type":"string","description":"Only the subscriptions of this plan, named exactly as plans in the result lists it, for example Pro monthly. Leave out for every plan. plans always lists every plan"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"subscriptions_report","x-permission":"analytics.read"}},"/sites/{site_id}/surveys.json":{"post":{"operationId":"surveys_create","summary":"Create a survey","description":"Creates a cookieless on-site survey for a site. It collects nothing until its status is active, so create it as draft first or pass status active to start at once. Required are name (internal, visitors never see it, max 120 characters) and questions (1 to 5 rows in order). Each question is an object with key (optional, a stable id of lowercase letters, digits and underscores, generated when omitted), kind (text, choice, multi, rating, nps or yes_no), prompt (required, max 200 characters), required (boolean), choices (a list of up to 10 options, only for choice and multi) and scale (3, 5, 7 or 10, only for rating, default 5). NPS always uses 0 to 10. Targeting is trigger_kind (immediate, delay, scroll, exit or manual) with delay_seconds (0 to 600, default 10, only for delay) and scroll_percent (1 to 100, default 50, only for scroll), paths (rows of match_type exact, prefix or glob and pattern, empty means every page), devices (desktop, mobile, tablet, empty means all), position (bottom_right, bottom_left or center), sample_rate (1 to 100 percent of visitors), thank_you (max 200 characters), starts_on and ends_on (YYYY-MM-DD). Surveys cannot ask for an email address and written answers are scrubbed of personal data. The Free plan allows 1 survey per workspace and a limited number of responses a month, paid plans are unlimited. Needs the content.write permission. Returns the survey with id (svy_...). Read answers with surveys_get.","tags":["Surveys"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, active or paused"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions in order, each { key, kind, prompt, required, choices, scale }"},"trigger_kind":{"type":"string","description":"immediate, delay, scroll, exit or manual"},"delay_seconds":{"type":"integer"},"scroll_percent":{"type":"integer"},"paths":{"type":"array","items":{"type":"object"},"description":"Pages it may appear on, each { match_type, pattern }. Empty means every page"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices it may appear on. Empty means all of them"},"position":{"type":"string"},"sample_rate":{"type":"integer","description":"Percentage of visitors offered the survey"},"thank_you":{"anyOf":[{"type":"string","description":"What the card says once the last question is answered"},{"type":"null"}]},"starts_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"ends_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"responses":{"type":"integer","description":"Responses in total"},"completed":{"type":"integer","description":"Responses where every question was answered"},"this_month":{"type":"integer","description":"Responses this calendar month, which is what the monthly allowance counts"}},"description":"Response counts, on list responses only"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"surveys_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Internal name shown in the app, max 120 characters. Visitors never see it","examples":["Exit survey"]},"status":{"type":"string","description":"draft (default) keeps it off, active starts collecting, paused stops it","enum":["draft","active","paused"],"default":"draft"},"questions":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Required list of 1 to 5 question objects in order. Each has prompt (required, max 200 characters), kind (text, choice, multi, rating, nps or yes_no, default text), key (optional stable id of lowercase letters, digits and underscores, generated when omitted), required (boolean), choices (list of up to 10 strings, for choice and multi) and scale (3, 5, 7 or 10, default 5, for rating). Example [{\"kind\":\"nps\",\"prompt\":\"How likely are you to recommend us?\"}]"},"trigger_kind":{"type":"string","description":"When the card appears: immediate, delay (after delay_seconds, default), scroll (after scroll_percent), exit (pointer leaves through the top) or manual (your own privatus.ask call)","enum":["immediate","delay","scroll","exit","manual"],"default":"delay"},"delay_seconds":{"type":"integer","description":"Seconds on the page before the card appears, from 0 to 600. Default 10. Only used with trigger_kind delay","default":10},"scroll_percent":{"type":"integer","description":"Percent of the page scrolled before the card appears, from 1 to 100. Default 50. Only used with trigger_kind scroll","default":50},"paths":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Pages it may appear on, a list of objects {match_type, pattern}. match_type is exact, prefix (default) or glob and pattern is matched against the page path like /pricing. Empty list means every page","default":[]},"devices":{"type":"array","items":{"type":"string","enum":["desktop","mobile","tablet"]},"description":"Devices it may appear on. Empty list means all of them","default":[]},"position":{"type":"string","description":"Where the card sits: bottom_right (default), bottom_left or center","enum":["bottom_right","bottom_left","center"],"default":"bottom_right"},"sample_rate":{"type":"integer","description":"Percent of eligible visitors offered the survey, from 1 to 100. Default 100","default":100},"thank_you":{"type":"string","description":"Message shown after the last question, max 200 characters"},"starts_on":{"type":"string","format":"date","description":"First day it may appear, YYYY-MM-DD. Empty means no start limit"},"ends_on":{"type":"string","format":"date","description":"Last day it may appear (inclusive), YYYY-MM-DD, on or after starts_on. Empty means no end limit"}},"required":["name","questions"]}}}}},"get":{"operationId":"surveys_list","summary":"List a site's surveys with their response counts","description":"Lists the surveys of a site, newest first, with their settings and response counts. Filter with status (draft, active, paused or all, default all). Paginated with page and per_page (default 25, up to 100). Each survey has id (svy_...), name, status, questions, targeting settings, starts_on, ends_on, created_at, updated_at and stats (responses, completed and this_month counts). Use surveys_get for the answers and results of one survey.","tags":["Surveys"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Only surveys with this status: draft, active, paused or all","enum":["draft","active","paused","all"],"default":"all"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","description":"Page number","default":1}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","description":"Rows per page (up to 100)","default":25}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, active or paused"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions in order, each { key, kind, prompt, required, choices, scale }"},"trigger_kind":{"type":"string","description":"immediate, delay, scroll, exit or manual"},"delay_seconds":{"type":"integer"},"scroll_percent":{"type":"integer"},"paths":{"type":"array","items":{"type":"object"},"description":"Pages it may appear on, each { match_type, pattern }. Empty means every page"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices it may appear on. Empty means all of them"},"position":{"type":"string"},"sample_rate":{"type":"integer","description":"Percentage of visitors offered the survey"},"thank_you":{"anyOf":[{"type":"string","description":"What the card says once the last question is answered"},{"type":"null"}]},"starts_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"ends_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"responses":{"type":"integer","description":"Responses in total"},"completed":{"type":"integer","description":"Responses where every question was answered"},"this_month":{"type":"integer","description":"Responses this calendar month, which is what the monthly allowance counts"}},"description":"Response counts, on list responses only"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"surveys_list","x-permission":"analytics.read"}},"/sites/{site_id}/surveys/{id}.json":{"delete":{"operationId":"surveys_delete","summary":"Delete a survey with its responses","description":"Permanently deletes a survey together with all its responses and answers. This cannot be undone and the results are lost. Use surveys_pause instead if you only want to stop collecting. The id comes from surveys_list and the site_id is required. Needs the content.write permission. Returns the deleted survey.","tags":["Surveys"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by surveys_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, active or paused"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions in order, each { key, kind, prompt, required, choices, scale }"},"trigger_kind":{"type":"string","description":"immediate, delay, scroll, exit or manual"},"delay_seconds":{"type":"integer"},"scroll_percent":{"type":"integer"},"paths":{"type":"array","items":{"type":"object"},"description":"Pages it may appear on, each { match_type, pattern }. Empty means every page"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices it may appear on. Empty means all of them"},"position":{"type":"string"},"sample_rate":{"type":"integer","description":"Percentage of visitors offered the survey"},"thank_you":{"anyOf":[{"type":"string","description":"What the card says once the last question is answered"},{"type":"null"}]},"starts_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"ends_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"responses":{"type":"integer","description":"Responses in total"},"completed":{"type":"integer","description":"Responses where every question was answered"},"this_month":{"type":"integer","description":"Responses this calendar month, which is what the monthly allowance counts"}},"description":"Response counts, on list responses only"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"surveys_get","summary":"Survey results for a period, broken down per question","description":"Returns the results report of one survey over a period, not just its settings (use surveys_list for settings and counts). Choose the period preset (default 30d) or period custom with from and to. The response has survey (its settings), period (from and to as ISO 8601 times), responses (people who answered at least one question), completed (people who answered the last question), questions (one entry per question with key, kind, prompt and answers count, plus detail by kind) and pages, devices and countries (up to 10 rows each of value and count). Detail by kind is texts (up to 100 newest written answers with text and at) for text, choices (value, count, share as percent with one decimal, offered) for choice, multi and yes_no, average (null with no answers), scale and distribution for rating, and score (NPS from -100 to 100, null with no answers), promoters (9 and 10), passives (7 and 8), detractors (0 to 6) and distribution for nps. A text question also has themes (themes as label, count, sentiment and example, plus answers and generated_at) when surveys_themes already made them for its current answers and the plan includes them. This call never generates them. Use surveys_themes to summarize written answers.","tags":["Surveys"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by surveys_list","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Period preset for the results, default 30d. Use custom together with from and to","enum":["today","yesterday","24h","7d","14d","28d","30d","90d","mtd","last_month","qtd","last_quarter","ytd","12mo","last_year","all","custom"],"default":"30d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day, YYYY-MM-DD, only with period custom"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day, YYYY-MM-DD, only with period custom"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"survey":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, active or paused"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions in order, each { key, kind, prompt, required, choices, scale }"},"trigger_kind":{"type":"string","description":"immediate, delay, scroll, exit or manual"},"delay_seconds":{"type":"integer"},"scroll_percent":{"type":"integer"},"paths":{"type":"array","items":{"type":"object"},"description":"Pages it may appear on, each { match_type, pattern }. Empty means every page"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices it may appear on. Empty means all of them"},"position":{"type":"string"},"sample_rate":{"type":"integer","description":"Percentage of visitors offered the survey"},"thank_you":{"anyOf":[{"type":"string","description":"What the card says once the last question is answered"},{"type":"null"}]},"starts_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"ends_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"responses":{"type":"integer","description":"Responses in total"},"completed":{"type":"integer","description":"Responses where every question was answered"},"this_month":{"type":"integer","description":"Responses this calendar month, which is what the monthly allowance counts"}},"description":"Response counts, on list responses only"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"period":{"type":"object"},"responses":{"type":"integer","description":"Responses in the period"},"completed":{"type":"integer","description":"Responses in the period where every question was answered"},"questions":{"type":"array","items":{"type":"object"},"description":"One result per question. Choice questions have choices, rating has average and distribution, NPS has score, promoters, passives and detractors, and text has the most recent answers"},"pages":{"type":"array","items":{"type":"object"},"description":"Pages the answers were given on, most first"},"devices":{"type":"array","items":{"type":"object"},"description":"Devices the answers came from"},"countries":{"type":"array","items":{"type":"object"},"description":"Countries the answers came from, as two-letter codes"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"surveys_get","x-permission":"analytics.read"},"patch":{"operationId":"surveys_update","summary":"Update a survey","description":"Changes a survey. Only the inputs you send change. Inputs and limits are the same as in surveys_create, with status draft, active or paused. When you send questions the whole list is replaced, so include every question you want to keep and keep each existing key to keep its collected answers (rewording a prompt with the same key does not split the results). Questions you leave out stop appearing in results. Changes to targeting take effect for visitors right away. The id comes from surveys_list and the site_id is required. Needs the content.write permission. Returns the updated survey.","tags":["Surveys"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by surveys_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, active or paused"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions in order, each { key, kind, prompt, required, choices, scale }"},"trigger_kind":{"type":"string","description":"immediate, delay, scroll, exit or manual"},"delay_seconds":{"type":"integer"},"scroll_percent":{"type":"integer"},"paths":{"type":"array","items":{"type":"object"},"description":"Pages it may appear on, each { match_type, pattern }. Empty means every page"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices it may appear on. Empty means all of them"},"position":{"type":"string"},"sample_rate":{"type":"integer","description":"Percentage of visitors offered the survey"},"thank_you":{"anyOf":[{"type":"string","description":"What the card says once the last question is answered"},{"type":"null"}]},"starts_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"ends_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"responses":{"type":"integer","description":"Responses in total"},"completed":{"type":"integer","description":"Responses where every question was answered"},"this_month":{"type":"integer","description":"Responses this calendar month, which is what the monthly allowance counts"}},"description":"Response counts, on list responses only"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"surveys_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New internal name, max 120 characters","examples":["Exit survey"]},"status":{"type":"string","description":"draft, active or paused","enum":["draft","active","paused"]},"questions":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"The complete new list of 1 to 5 questions, replacing the current ones. Same object format as surveys_create. Keep each existing key to keep its answers"},"trigger_kind":{"type":"string","description":"When the card appears: immediate, delay, scroll, exit or manual","enum":["immediate","delay","scroll","exit","manual"]},"delay_seconds":{"type":"integer","description":"Seconds on the page before the card appears, from 0 to 600. Only used with trigger_kind delay"},"scroll_percent":{"type":"integer","description":"Percent of the page scrolled before the card appears, from 1 to 100. Only used with trigger_kind scroll"},"paths":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Pages it may appear on, a list of objects {match_type, pattern} with match_type exact, prefix or glob. Replaces the current list. Empty list means every page"},"devices":{"type":"array","items":{"type":"string","enum":["desktop","mobile","tablet"]},"description":"Devices it may appear on. Replaces the current list. Empty list means all of them"},"position":{"type":"string","description":"Where the card sits: bottom_right, bottom_left or center","enum":["bottom_right","bottom_left","center"]},"sample_rate":{"type":"integer","description":"Percent of eligible visitors offered the survey, from 1 to 100"},"thank_you":{"type":"string","description":"Message shown after the last question, max 200 characters. Empty string removes it"},"starts_on":{"type":"string","format":"date","description":"First day it may appear, YYYY-MM-DD"},"ends_on":{"type":"string","format":"date","description":"Last day it may appear (inclusive), YYYY-MM-DD, on or after starts_on"}}}}}}}},"/sites/{site_id}/surveys/{id}/pause.json":{"post":{"operationId":"surveys_pause","summary":"Stop collecting answers and keep the ones already given","description":"Pauses a survey so it stops being offered to visitors at once. Responses already collected are kept and shown in surveys_get, and surveys_start resumes it. Use it instead of surveys_delete when you only want to stop collecting. The id comes from surveys_list and the site_id is required. Needs the content.write permission. Returns the survey with status paused.","tags":["Surveys"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by surveys_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, active or paused"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions in order, each { key, kind, prompt, required, choices, scale }"},"trigger_kind":{"type":"string","description":"immediate, delay, scroll, exit or manual"},"delay_seconds":{"type":"integer"},"scroll_percent":{"type":"integer"},"paths":{"type":"array","items":{"type":"object"},"description":"Pages it may appear on, each { match_type, pattern }. Empty means every page"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices it may appear on. Empty means all of them"},"position":{"type":"string"},"sample_rate":{"type":"integer","description":"Percentage of visitors offered the survey"},"thank_you":{"anyOf":[{"type":"string","description":"What the card says once the last question is answered"},{"type":"null"}]},"starts_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"ends_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"responses":{"type":"integer","description":"Responses in total"},"completed":{"type":"integer","description":"Responses where every question was answered"},"this_month":{"type":"integer","description":"Responses this calendar month, which is what the monthly allowance counts"}},"description":"Response counts, on list responses only"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"surveys_pause","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/surveys/{id}/start.json":{"post":{"operationId":"surveys_start","summary":"Start collecting answers","description":"Sets a survey to active so visitors can be offered it. It only appears when the current date is within starts_on and ends_on (when set), the page matches its paths and devices, and the plan's monthly response allowance is not used up. Use it for a draft or a paused survey. The id comes from surveys_list and the site_id is required. Needs the content.write permission. Returns the survey with status active. Stop it again with surveys_pause.","tags":["Surveys"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by surveys_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","description":"draft, active or paused"},"questions":{"type":"array","items":{"type":"object"},"description":"The questions in order, each { key, kind, prompt, required, choices, scale }"},"trigger_kind":{"type":"string","description":"immediate, delay, scroll, exit or manual"},"delay_seconds":{"type":"integer"},"scroll_percent":{"type":"integer"},"paths":{"type":"array","items":{"type":"object"},"description":"Pages it may appear on, each { match_type, pattern }. Empty means every page"},"devices":{"type":"array","items":{"type":"string"},"description":"Devices it may appear on. Empty means all of them"},"position":{"type":"string"},"sample_rate":{"type":"integer","description":"Percentage of visitors offered the survey"},"thank_you":{"anyOf":[{"type":"string","description":"What the card says once the last question is answered"},{"type":"null"}]},"starts_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"ends_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"stats":{"anyOf":[{"type":"object","properties":{"responses":{"type":"integer","description":"Responses in total"},"completed":{"type":"integer","description":"Responses where every question was answered"},"this_month":{"type":"integer","description":"Responses this calendar month, which is what the monthly allowance counts"}},"description":"Response counts, on list responses only"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"surveys_start","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/surveys/{id}/themes.json":{"post":{"operationId":"surveys_themes","summary":"Group the free-text answers to one question into themes (Business plan)","description":"Uses AI to group the written answers to one free-text question into themes. Business plan only. Choose it after surveys_get shows a text question with enough answers, and pass question_key (the key of a question of kind text from surveys_get). It needs at least 5 written answers and uses the 300 most recent. The result lists up to 12 themes, each with label, count, sentiment (positive, neutral or negative) and example (a representative answer, may be null), plus answers (how many answers were summarized) and generated_at. Each new generation uses one question from the workspace's monthly AI allowance, which is given back if it fails. The result is cached against the answers, so calling again with no new answers costs nothing. It fails with a validation error when the plan does not include it, the allowance is used up, the AI is not configured or there are too few answers.","tags":["Surveys"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by surveys_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"themes":{"type":"array","items":{"type":"object"},"description":"One per theme, with its label, count, sentiment and an example answer"},"answers":{"type":"integer","description":"How many answers the summary was made from"},"generated_at":{"type":"string","format":"date-time","description":"When the summary was made"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"surveys_themes","x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"question_key":{"type":"string","description":"The key of a question of kind text, from the questions in surveys_get. Required"}},"required":["question_key"]}}}}}},"/sites/{site_id}/testimonials/analytics/breakdown.json":{"get":{"operationId":"testimonial_stats_breakdown","summary":"Split one testimonial metric by form, request, widget, wall, testimonial, channel, page, country or source","description":"Returns rows, largest first, each with key, label, value and share (a percent of the total), or numerator and denominator for a rate. A row of a record (form, request, widget, wall, testimonial) carries its id. Each dimension takes only some metrics: form and channel take the form metrics, request the request metrics, widget and wall their own views, clicks, click rate and video_plays, testimonial takes testimonial_views and video_plays, page and country take the view and click metrics, and source takes new_testimonials. A pair that does not fit responds with 422 and names the metrics that do.","tags":["Testimonial analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Period: today, yesterday, 7d, 30d, 90d, 12mo, mtd, ytd, all or custom (with from and to). Default 30d. Days are days in the site's time zone","enum":["today","yesterday","7d","30d","90d","12mo","mtd","ytd","all","custom"],"default":"30d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day (YYYY-MM-DD) when period is custom","examples":["2026-09-01"]}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day (YYYY-MM-DD) when period is custom. A day after today is read as today","examples":["2026-09-30"]}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Compare with previous_period (the same number of days just before) or previous_year (the same days a year earlier). Default none","enum":["none","previous_period","previous_year"],"default":"none"}},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Bucket size of the series: day, week or month. Blank picks day up to 92 days, week up to a year, then month","enum":["day","week","month"]}},{"name":"form_id","in":"query","required":false,"schema":{"type":"string","description":"Narrow the form metrics (form_views, form_starts, submissions, completion_rate) to one form, an id from testimonial_forms_list, e.g. frm_7Q2K9XH3AB","examples":["frm_7Q2K9XH3AB"]}},{"name":"request_id","in":"query","required":false,"schema":{"type":"string","description":"Narrow the request metrics (request_sent, request_opened, request_clicked, request_submitted, answer_rate) to one request, e.g. req_7Q2K9XH3AB","examples":["req_7Q2K9XH3AB"]}},{"name":"widget_id","in":"query","required":false,"schema":{"type":"string","description":"Narrow the widget metrics (widget_views, widget_clicks) to one widget, e.g. wdg_7Q2K9XH3AB","examples":["wdg_7Q2K9XH3AB"]}},{"name":"wall_id","in":"query","required":false,"schema":{"type":"string","description":"Narrow the wall metrics (wall_views, wall_clicks) to one wall, e.g. wal_7Q2K9XH3AB","examples":["wal_7Q2K9XH3AB"]}},{"name":"metric","in":"query","required":false,"schema":{"type":"string","description":"One of form_views, form_starts, submissions, request_sent, request_opened, request_clicked, request_submitted, widget_views, widget_clicks, wall_views, wall_clicks, testimonial_views, video_plays (counts), completion_rate, answer_rate, widget_click_rate, wall_click_rate (percents from 0 to 100) or new_testimonials","enum":["form_views","form_starts","submissions","request_sent","request_opened","request_clicked","request_submitted","widget_views","widget_clicks","wall_views","wall_clicks","testimonial_views","video_plays","completion_rate","answer_rate","widget_click_rate","wall_click_rate","new_testimonials"]}},{"name":"dimension","in":"query","required":false,"schema":{"type":"string","description":"What to split by: form, request, widget, wall or testimonial (a row per record), or channel (link, qr, inline, popup, request), page (a host and a path), country (a two-letter code) or source (how a new testimonial came in)","enum":["form","request","widget","wall","testimonial","channel","page","country","source"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Most rows, 1 to 100. Default 25","default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_stats_breakdown","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/analytics/export.json":{"post":{"operationId":"testimonial_stats_export","summary":"Queue a file of one section of the testimonial analytics","description":"Creates an export of kind testimonial_stats for the period given and returns it queued. Poll exports_get until status is complete, then exports_download. section picks the rows: days (one row per day, week or month with every metric), forms, channels, requests, widgets, walls, pages, testimonials, sources or countries. The file is kept for 7 days. Responds with 422 in_progress when too many exports are already queued.","tags":["Testimonial analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Export id, e.g. exp_7Q2K9XH3AB"},"site_id":{"anyOf":[{"type":"string","description":"Site exported (pa_…)"},{"type":"null"}]},"kind":{"type":"string","description":"aggregated, pageviews, events, imported, raw or dashboard"},"format":{"type":"string","description":"csv, json, xlsx, ndjson or zip"},"status":{"type":"string","description":"queued, running, complete, failed or expired"},"params":{"type":"object","description":"The export definition (dates, timezone, grouping, dimensions, metrics, fields, filters)"},"row_count":{"anyOf":[{"type":"integer","description":"Rows written"},{"type":"null"}]},"error":{"anyOf":[{"type":"string","description":"Why the export failed"},{"type":"null"}]},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the file is deleted"},{"type":"null"}]},"download_url":{"anyOf":[{"type":"string","description":"Path returning a short-lived signed file link (exports_download)"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_stats_export","x-permission":"analytics.export","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"period":{"type":"string","description":"Period: today, yesterday, 7d, 30d, 90d, 12mo, mtd, ytd, all or custom (with from and to). Default 30d. Days are days in the site's time zone","enum":["today","yesterday","7d","30d","90d","12mo","mtd","ytd","all","custom"],"default":"30d"},"from":{"type":"string","format":"date","description":"First day (YYYY-MM-DD) when period is custom","examples":["2026-09-01"]},"to":{"type":"string","format":"date","description":"Last day (YYYY-MM-DD) when period is custom. A day after today is read as today","examples":["2026-09-30"]},"compare":{"type":"string","description":"Compare with previous_period (the same number of days just before) or previous_year (the same days a year earlier). Default none","enum":["none","previous_period","previous_year"],"default":"none"},"interval":{"type":"string","description":"Bucket size of the series: day, week or month. Blank picks day up to 92 days, week up to a year, then month","enum":["day","week","month"]},"form_id":{"type":"string","description":"Narrow the form metrics (form_views, form_starts, submissions, completion_rate) to one form, an id from testimonial_forms_list, e.g. frm_7Q2K9XH3AB","examples":["frm_7Q2K9XH3AB"]},"request_id":{"type":"string","description":"Narrow the request metrics (request_sent, request_opened, request_clicked, request_submitted, answer_rate) to one request, e.g. req_7Q2K9XH3AB","examples":["req_7Q2K9XH3AB"]},"widget_id":{"type":"string","description":"Narrow the widget metrics (widget_views, widget_clicks) to one widget, e.g. wdg_7Q2K9XH3AB","examples":["wdg_7Q2K9XH3AB"]},"wall_id":{"type":"string","description":"Narrow the wall metrics (wall_views, wall_clicks) to one wall, e.g. wal_7Q2K9XH3AB","examples":["wal_7Q2K9XH3AB"]},"section":{"type":"string","description":"Which rows the file holds: days, forms, channels, requests, widgets, walls, pages, testimonials, sources or countries. Default days","enum":["days","forms","channels","requests","widgets","walls","pages","testimonials","sources","countries"],"default":"days"},"file_format":{"type":"string","description":"csv, json or xlsx. Default csv","enum":["csv","json","xlsx"],"default":"csv"}}}}}}}},"/sites/{site_id}/testimonials/analytics.json":{"get":{"operationId":"testimonial_stats_overview","summary":"Read the testimonial analytics of a site in one call","description":"Returns everything the Analytics tab under Testimonials shows for a period: cards (form_views, submissions, completion_rate, answer_rate, widget_views, wall_views, each with previous and change when compare is set), chart (one metric over time), a row per form, request, widget and wall, channels (how forms were opened), pages (where widgets and walls were seen), top_testimonials, new_testimonials (by source and by current status) and countries. Rates are percents from 0 to 100 and are null with nothing to divide by. blank is true while the site has never counted anything, and recorded lists the metrics it has ever counted. These are daily totals of the testimonials feature, not web analytics: use stats_overview for visitors and pageviews.","tags":["Testimonial analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Period: today, yesterday, 7d, 30d, 90d, 12mo, mtd, ytd, all or custom (with from and to). Default 30d. Days are days in the site's time zone","enum":["today","yesterday","7d","30d","90d","12mo","mtd","ytd","all","custom"],"default":"30d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day (YYYY-MM-DD) when period is custom","examples":["2026-09-01"]}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day (YYYY-MM-DD) when period is custom. A day after today is read as today","examples":["2026-09-30"]}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Compare with previous_period (the same number of days just before) or previous_year (the same days a year earlier). Default none","enum":["none","previous_period","previous_year"],"default":"none"}},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Bucket size of the series: day, week or month. Blank picks day up to 92 days, week up to a year, then month","enum":["day","week","month"]}},{"name":"form_id","in":"query","required":false,"schema":{"type":"string","description":"Narrow the form metrics (form_views, form_starts, submissions, completion_rate) to one form, an id from testimonial_forms_list, e.g. frm_7Q2K9XH3AB","examples":["frm_7Q2K9XH3AB"]}},{"name":"request_id","in":"query","required":false,"schema":{"type":"string","description":"Narrow the request metrics (request_sent, request_opened, request_clicked, request_submitted, answer_rate) to one request, e.g. req_7Q2K9XH3AB","examples":["req_7Q2K9XH3AB"]}},{"name":"widget_id","in":"query","required":false,"schema":{"type":"string","description":"Narrow the widget metrics (widget_views, widget_clicks) to one widget, e.g. wdg_7Q2K9XH3AB","examples":["wdg_7Q2K9XH3AB"]}},{"name":"wall_id","in":"query","required":false,"schema":{"type":"string","description":"Narrow the wall metrics (wall_views, wall_clicks) to one wall, e.g. wal_7Q2K9XH3AB","examples":["wal_7Q2K9XH3AB"]}},{"name":"metric","in":"query","required":false,"schema":{"type":"string","description":"The metric of the chart. One of form_views, form_starts, submissions, request_sent, request_opened, request_clicked, request_submitted, widget_views, widget_clicks, wall_views, wall_clicks, testimonial_views, video_plays (counts), completion_rate, answer_rate, widget_click_rate, wall_click_rate (percents from 0 to 100) or new_testimonials. Default form_views","enum":["form_views","form_starts","submissions","request_sent","request_opened","request_clicked","request_submitted","widget_views","widget_clicks","wall_views","wall_clicks","testimonial_views","video_plays","completion_rate","answer_rate","widget_click_rate","wall_click_rate","new_testimonials"],"default":"form_views"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Most rows per list of forms, requests, widgets and walls, 1 to 100. Default 25","default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_stats_overview","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/analytics/timeseries.json":{"get":{"operationId":"testimonial_stats_timeseries","summary":"Read one testimonial metric per day, week or month","description":"Returns points with date, to, value and, when compare is set, previous and previous_date, plus total, previous_total and change. A rate (completion_rate, answer_rate, widget_click_rate, wall_click_rate) is worked out from the totals of each bucket and is null for a bucket with nothing to divide by. new_testimonials is counted from the testimonials themselves by the day each was added.","tags":["Testimonial analytics"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Period: today, yesterday, 7d, 30d, 90d, 12mo, mtd, ytd, all or custom (with from and to). Default 30d. Days are days in the site's time zone","enum":["today","yesterday","7d","30d","90d","12mo","mtd","ytd","all","custom"],"default":"30d"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day (YYYY-MM-DD) when period is custom","examples":["2026-09-01"]}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day (YYYY-MM-DD) when period is custom. A day after today is read as today","examples":["2026-09-30"]}},{"name":"compare","in":"query","required":false,"schema":{"type":"string","description":"Compare with previous_period (the same number of days just before) or previous_year (the same days a year earlier). Default none","enum":["none","previous_period","previous_year"],"default":"none"}},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Bucket size of the series: day, week or month. Blank picks day up to 92 days, week up to a year, then month","enum":["day","week","month"]}},{"name":"form_id","in":"query","required":false,"schema":{"type":"string","description":"Narrow the form metrics (form_views, form_starts, submissions, completion_rate) to one form, an id from testimonial_forms_list, e.g. frm_7Q2K9XH3AB","examples":["frm_7Q2K9XH3AB"]}},{"name":"request_id","in":"query","required":false,"schema":{"type":"string","description":"Narrow the request metrics (request_sent, request_opened, request_clicked, request_submitted, answer_rate) to one request, e.g. req_7Q2K9XH3AB","examples":["req_7Q2K9XH3AB"]}},{"name":"widget_id","in":"query","required":false,"schema":{"type":"string","description":"Narrow the widget metrics (widget_views, widget_clicks) to one widget, e.g. wdg_7Q2K9XH3AB","examples":["wdg_7Q2K9XH3AB"]}},{"name":"wall_id","in":"query","required":false,"schema":{"type":"string","description":"Narrow the wall metrics (wall_views, wall_clicks) to one wall, e.g. wal_7Q2K9XH3AB","examples":["wal_7Q2K9XH3AB"]}},{"name":"metric","in":"query","required":false,"schema":{"type":"string","description":"One of form_views, form_starts, submissions, request_sent, request_opened, request_clicked, request_submitted, widget_views, widget_clicks, wall_views, wall_clicks, testimonial_views, video_plays (counts), completion_rate, answer_rate, widget_click_rate, wall_click_rate (percents from 0 to 100) or new_testimonials. Default form_views","enum":["form_views","form_starts","submissions","request_sent","request_opened","request_clicked","request_submitted","widget_views","widget_clicks","wall_views","wall_clicks","testimonial_views","video_plays","completion_rate","answer_rate","widget_click_rate","wall_click_rate","new_testimonials"],"default":"form_views"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_stats_timeseries","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/settings/brand_kit.json":{"delete":{"operationId":"testimonial_brand_kit_reset","summary":"Return the brand kit of a site's testimonials to the Privatus Analytics defaults","description":"Clears every color, font, the radius, the rating style, the logos and the custom CSS in one step, and every form, widget and wall changes with it. It cannot be undone, so an assistant is sent to the Brand kit page instead of running it.","tags":["Testimonial brand kit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string","description":"The site it belongs to"},"default":{"type":"boolean","description":"True until anything is changed"},"light":{"type":"object","description":"The resolved colors of the light theme: accent, accent_text, background, card, text, muted, border, rating"},"dark":{"type":"object","description":"The resolved colors of the dark theme, with the same keys"},"accent_color":{"anyOf":[{"type":"string","description":"The stored accent color for the light theme, or null for the default"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"The stored page background for the light theme, or null for the default"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"The stored card background for the light theme, or null for the default"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"The stored text color for the light theme, or null for the default"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"The stored line color for the light theme, or null for the default"},{"type":"null"}]},"accent_color_dark":{"anyOf":[{"type":"string","description":"The stored accent color for the dark theme, or null when it is derived"},{"type":"null"}]},"background_color_dark":{"anyOf":[{"type":"string","description":"The stored page background for the dark theme, or null for the default"},{"type":"null"}]},"card_color_dark":{"anyOf":[{"type":"string","description":"The stored card background for the dark theme, or null for the default"},{"type":"null"}]},"text_color_dark":{"anyOf":[{"type":"string","description":"The stored text color for the dark theme, or null for the default"},{"type":"null"}]},"border_color_dark":{"anyOf":[{"type":"string","description":"The stored line color for the dark theme, or null for the default"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"The stored color of stars or hearts, or null for the default"},{"type":"null"}]},"rating_style":{"type":"string","description":"stars or hearts"},"heading_font":{"type":"string","description":"The font of headings"},"body_font":{"type":"string","description":"The font of everything else"},"quote_font":{"type":"string","description":"The font of the customer's words"},"radius":{"type":"integer","description":"Corner radius in pixels"},"logo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"The logo, as a file"},{"type":"null"}]},"logo_dark":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"The logo for the dark theme, as a file"},{"type":"null"}]},"logo_url":{"anyOf":[{"type":"string","description":"Where to load the logo, or null"},{"type":"null"}]},"logo_dark_url":{"anyOf":[{"type":"string","description":"Where to load the dark logo, or null"},{"type":"null"}]},"show_badge":{"type":"boolean","description":"The badge is shown. Always true on a plan that cannot remove it"},"can_remove_badge":{"type":"boolean","description":"The plan allows hiding the badge"},"custom_css":{"anyOf":[{"type":"string","description":"The custom CSS as it was written, or null. Null on a plan without custom CSS"},{"type":"null"}]},"can_use_custom_css":{"type":"boolean","description":"The plan allows custom CSS"},"css_variables":{"type":"object","description":"The CSS custom properties every form, widget and wall reads, for light and dark"},"contrast":{"type":"object","description":"The measured contrast of text on its background and of the accent, in each theme, with whether it passes"},"usage":{"type":"object","description":"How many forms, widgets and walls of the site use the kit"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"testimonial_brand_kit_get","summary":"Get the brand kit of a site's testimonials, with every color resolved for light and dark","description":"Returns the colors, fonts, corner radius, rating style, logos, badge switch and custom CSS that every form, widget and wall of the site is drawn with. A setting that was never changed comes back with the Privatus Analytics default.","tags":["Testimonial brand kit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string","description":"The site it belongs to"},"default":{"type":"boolean","description":"True until anything is changed"},"light":{"type":"object","description":"The resolved colors of the light theme: accent, accent_text, background, card, text, muted, border, rating"},"dark":{"type":"object","description":"The resolved colors of the dark theme, with the same keys"},"accent_color":{"anyOf":[{"type":"string","description":"The stored accent color for the light theme, or null for the default"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"The stored page background for the light theme, or null for the default"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"The stored card background for the light theme, or null for the default"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"The stored text color for the light theme, or null for the default"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"The stored line color for the light theme, or null for the default"},{"type":"null"}]},"accent_color_dark":{"anyOf":[{"type":"string","description":"The stored accent color for the dark theme, or null when it is derived"},{"type":"null"}]},"background_color_dark":{"anyOf":[{"type":"string","description":"The stored page background for the dark theme, or null for the default"},{"type":"null"}]},"card_color_dark":{"anyOf":[{"type":"string","description":"The stored card background for the dark theme, or null for the default"},{"type":"null"}]},"text_color_dark":{"anyOf":[{"type":"string","description":"The stored text color for the dark theme, or null for the default"},{"type":"null"}]},"border_color_dark":{"anyOf":[{"type":"string","description":"The stored line color for the dark theme, or null for the default"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"The stored color of stars or hearts, or null for the default"},{"type":"null"}]},"rating_style":{"type":"string","description":"stars or hearts"},"heading_font":{"type":"string","description":"The font of headings"},"body_font":{"type":"string","description":"The font of everything else"},"quote_font":{"type":"string","description":"The font of the customer's words"},"radius":{"type":"integer","description":"Corner radius in pixels"},"logo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"The logo, as a file"},{"type":"null"}]},"logo_dark":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"The logo for the dark theme, as a file"},{"type":"null"}]},"logo_url":{"anyOf":[{"type":"string","description":"Where to load the logo, or null"},{"type":"null"}]},"logo_dark_url":{"anyOf":[{"type":"string","description":"Where to load the dark logo, or null"},{"type":"null"}]},"show_badge":{"type":"boolean","description":"The badge is shown. Always true on a plan that cannot remove it"},"can_remove_badge":{"type":"boolean","description":"The plan allows hiding the badge"},"custom_css":{"anyOf":[{"type":"string","description":"The custom CSS as it was written, or null. Null on a plan without custom CSS"},{"type":"null"}]},"can_use_custom_css":{"type":"boolean","description":"The plan allows custom CSS"},"css_variables":{"type":"object","description":"The CSS custom properties every form, widget and wall reads, for light and dark"},"contrast":{"type":"object","description":"The measured contrast of text on its background and of the accent, in each theme, with whether it passes"},"usage":{"type":"object","description":"How many forms, widgets and walls of the site use the kit"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_brand_kit_get","x-permission":"analytics.read"},"patch":{"operationId":"testimonial_brand_kit_update","summary":"Change the brand kit of a site's testimonials","description":"Only the inputs you send are changed. Send an empty string to return one setting to the Privatus Analytics default. Custom CSS is checked when it is saved, and anything that is not allowed is refused with the line it is on. Custom CSS needs the Business plan and hiding the badge needs the Business plan. Without it the server responds with 402 plan_limit.","tags":["Testimonial brand kit"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string","description":"The site it belongs to"},"default":{"type":"boolean","description":"True until anything is changed"},"light":{"type":"object","description":"The resolved colors of the light theme: accent, accent_text, background, card, text, muted, border, rating"},"dark":{"type":"object","description":"The resolved colors of the dark theme, with the same keys"},"accent_color":{"anyOf":[{"type":"string","description":"The stored accent color for the light theme, or null for the default"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"The stored page background for the light theme, or null for the default"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"The stored card background for the light theme, or null for the default"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"The stored text color for the light theme, or null for the default"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"The stored line color for the light theme, or null for the default"},{"type":"null"}]},"accent_color_dark":{"anyOf":[{"type":"string","description":"The stored accent color for the dark theme, or null when it is derived"},{"type":"null"}]},"background_color_dark":{"anyOf":[{"type":"string","description":"The stored page background for the dark theme, or null for the default"},{"type":"null"}]},"card_color_dark":{"anyOf":[{"type":"string","description":"The stored card background for the dark theme, or null for the default"},{"type":"null"}]},"text_color_dark":{"anyOf":[{"type":"string","description":"The stored text color for the dark theme, or null for the default"},{"type":"null"}]},"border_color_dark":{"anyOf":[{"type":"string","description":"The stored line color for the dark theme, or null for the default"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"The stored color of stars or hearts, or null for the default"},{"type":"null"}]},"rating_style":{"type":"string","description":"stars or hearts"},"heading_font":{"type":"string","description":"The font of headings"},"body_font":{"type":"string","description":"The font of everything else"},"quote_font":{"type":"string","description":"The font of the customer's words"},"radius":{"type":"integer","description":"Corner radius in pixels"},"logo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"The logo, as a file"},{"type":"null"}]},"logo_dark":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"The logo for the dark theme, as a file"},{"type":"null"}]},"logo_url":{"anyOf":[{"type":"string","description":"Where to load the logo, or null"},{"type":"null"}]},"logo_dark_url":{"anyOf":[{"type":"string","description":"Where to load the dark logo, or null"},{"type":"null"}]},"show_badge":{"type":"boolean","description":"The badge is shown. Always true on a plan that cannot remove it"},"can_remove_badge":{"type":"boolean","description":"The plan allows hiding the badge"},"custom_css":{"anyOf":[{"type":"string","description":"The custom CSS as it was written, or null. Null on a plan without custom CSS"},{"type":"null"}]},"can_use_custom_css":{"type":"boolean","description":"The plan allows custom CSS"},"css_variables":{"type":"object","description":"The CSS custom properties every form, widget and wall reads, for light and dark"},"contrast":{"type":"object","description":"The measured contrast of text on its background and of the accent, in each theme, with whether it passes"},"usage":{"type":"object","description":"How many forms, widgets and walls of the site use the kit"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_brand_kit_update","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"accent_color":{"type":"string","description":"The accent color for the light theme, as #rrggbb. Buttons, links and hearts use it. Empty for the default"},"background_color":{"type":"string","description":"The page background for the light theme, as #rrggbb"},"card_color":{"type":"string","description":"The background of a card for the light theme, as #rrggbb"},"text_color":{"type":"string","description":"The text color for the light theme, as #rrggbb"},"border_color":{"type":"string","description":"The line color for the light theme, as #rrggbb"},"accent_color_dark":{"type":"string","description":"The accent color for the dark theme, as #rrggbb. Empty derives it from the light one"},"background_color_dark":{"type":"string","description":"The page background for the dark theme, as #rrggbb. Empty for the default"},"card_color_dark":{"type":"string","description":"The background of a card for the dark theme, as #rrggbb. Empty for the default"},"text_color_dark":{"type":"string","description":"The text color for the dark theme, as #rrggbb. Empty for the default"},"border_color_dark":{"type":"string","description":"The line color for the dark theme, as #rrggbb. Empty for the default"},"rating_color":{"type":"string","description":"The color of stars or hearts, as #rrggbb. Empty for amber stars and hearts in the accent color"},"rating_style":{"type":"string","description":"stars (the default) or hearts"},"heading_font":{"type":"string","description":"The font of headings: inherit, system (the default), system_serif or system_mono"},"body_font":{"type":"string","description":"The font of everything else: inherit, system (the default), system_serif or system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words: the same choices"},"radius":{"type":"integer","description":"Corner radius in pixels, 0 to 24, for cards, buttons and fields"},"logo_media_id":{"type":"string","description":"The id (med_...) of an uploaded logo, or an empty string to remove it"},"logo_dark_media_id":{"type":"string","description":"The id (med_...) of an uploaded logo for the dark theme, or an empty string to remove it"},"show_badge":{"type":"boolean","description":"Show the \"Collected with Privatus Analytics\" badge by default. Always on for a plan that cannot remove it (Business and up can)"},"custom_css":{"type":"string","description":"Your own CSS for every form, widget and wall of the site, up to 20,000 characters. On Business and up. It is kept inside the embed: @import, outside files and anything that could reach the host page are refused"}}}}}}}},"/sites/{site_id}/testimonials/collections/{id}/items.json":{"post":{"operationId":"testimonial_collections_add_items","summary":"Add testimonials to a manual collection","description":"Up to 100 at once. They join at the bottom, or at the top with position top, in the order given. The response has meta.undo_id, which testimonials_bulk_undo takes for 7 days. A smart collection takes nothing by hand.","tags":["Testimonial collections"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_collections_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The collection id (col_...)"},"name":{"type":"string","description":"Its name"},"description":{"anyOf":[{"type":"string","description":"A note for your team. Null when there is none"},{"type":"null"}]},"kind":{"type":"string","description":"manual or smart"},"match":{"anyOf":[{"type":"string","description":"Smart only: all or any. Null for a manual collection"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Smart only: the rules as rows of { field, operator, value }. Empty for a manual collection"},"sort":{"anyOf":[{"type":"string","description":"Smart only: the order its testimonials are served in. A manual collection is served in the order it was put in"},{"type":"null"}]},"summary":{"anyOf":[{"type":"string","description":"Smart only: the rules in plain English. Null when a rule no longer reads, for example because it names a tag that is in the trash"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"How many testimonials it holds right now, the trash left out"},"approved_count":{"type":"integer","description":"How many of those are approved. Widgets and walls show only these"},"feeds":{"type":"array","items":{"type":"object"},"description":"The widgets and walls that take their testimonials from it, each as { type, id, name }"},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null otherwise"},{"type":"null"}]},"locked":{"type":"boolean","description":"True for a smart collection on a plan without smart collections. It is kept, holds what matched its rules when the plan changed and takes in nothing new"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_collections_add_items","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"Up to 100 testimonial ids (tm_...) of this site"},"position":{"type":"string","description":"bottom (the default) or top","enum":["top","bottom"],"default":"bottom"}},"required":["testimonial_ids"]}}}}},"delete":{"operationId":"testimonial_collections_remove_items","summary":"Take testimonials out of a manual collection","description":"Up to 100 at once. The testimonials themselves are not changed. The response has meta.undo_id, and an undo puts each one back in its place.","tags":["Testimonial collections"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_collections_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The collection id (col_...)"},"name":{"type":"string","description":"Its name"},"description":{"anyOf":[{"type":"string","description":"A note for your team. Null when there is none"},{"type":"null"}]},"kind":{"type":"string","description":"manual or smart"},"match":{"anyOf":[{"type":"string","description":"Smart only: all or any. Null for a manual collection"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Smart only: the rules as rows of { field, operator, value }. Empty for a manual collection"},"sort":{"anyOf":[{"type":"string","description":"Smart only: the order its testimonials are served in. A manual collection is served in the order it was put in"},{"type":"null"}]},"summary":{"anyOf":[{"type":"string","description":"Smart only: the rules in plain English. Null when a rule no longer reads, for example because it names a tag that is in the trash"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"How many testimonials it holds right now, the trash left out"},"approved_count":{"type":"integer","description":"How many of those are approved. Widgets and walls show only these"},"feeds":{"type":"array","items":{"type":"object"},"description":"The widgets and walls that take their testimonials from it, each as { type, id, name }"},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null otherwise"},{"type":"null"}]},"locked":{"type":"boolean","description":"True for a smart collection on a plan without smart collections. It is kept, holds what matched its rules when the plan changed and takes in nothing new"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_collections_remove_items","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"Up to 100 testimonial ids (tm_...) of this site"}},"required":["testimonial_ids"]}}}}}},"/sites/{site_id}/testimonials/collections.json":{"post":{"operationId":"testimonial_collections_create","summary":"Create a collection, manual or smart","description":"kind manual is put together by hand, and testimonial_ids starts it filled. kind smart is kept current by conditions: rows of field, operator and value joined by match. The response carries the count and the rules in plain English, so one call turns a sentence into a living collection. Try the rules first with testimonial_collections_preview. The kind never changes afterward.","tags":["Testimonial collections"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The collection id (col_...)"},"name":{"type":"string","description":"Its name"},"description":{"anyOf":[{"type":"string","description":"A note for your team. Null when there is none"},{"type":"null"}]},"kind":{"type":"string","description":"manual or smart"},"match":{"anyOf":[{"type":"string","description":"Smart only: all or any. Null for a manual collection"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Smart only: the rules as rows of { field, operator, value }. Empty for a manual collection"},"sort":{"anyOf":[{"type":"string","description":"Smart only: the order its testimonials are served in. A manual collection is served in the order it was put in"},{"type":"null"}]},"summary":{"anyOf":[{"type":"string","description":"Smart only: the rules in plain English. Null when a rule no longer reads, for example because it names a tag that is in the trash"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"How many testimonials it holds right now, the trash left out"},"approved_count":{"type":"integer","description":"How many of those are approved. Widgets and walls show only these"},"feeds":{"type":"array","items":{"type":"object"},"description":"The widgets and walls that take their testimonials from it, each as { type, id, name }"},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null otherwise"},{"type":"null"}]},"locked":{"type":"boolean","description":"True for a smart collection on a plan without smart collections. It is kept, holds what matched its rules when the plan changed and takes in nothing new"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_collections_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Required. Up to 80 characters, unique on the site without regard to case"},"description":{"type":"string","description":"Optional, up to 280 characters. For your team only"},"kind":{"type":"string","description":"manual (the default, put together by hand) or smart (kept current by conditions). Fixed afterward","enum":["manual","smart"],"default":"manual"},"match":{"type":"string","description":"Smart only. all (the default: every condition must match) or any","enum":["all","any"],"default":"all"},"conditions":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Smart only. 1 to 20 rows of { field, operator, value }, e.g. [{\"field\": \"status\", \"operator\": \"is\", \"value\": \"approved\"}, {\"field\": \"rating\", \"operator\": \"is_at_least\", \"value\": 4}, {\"field\": \"tag\", \"operator\": \"has_any_of\", \"value\": [\"onboarding\"]}]. Fields: status, kind, rating, source, source_name, form, language, tag, words, has_photo, has_video, has_highlight, verified, pinned, consent, received, person, company, usage and property.<key>. Tags and forms may be named or given by id"},"sort":{"type":"string","description":"Smart only. The order its testimonials are served in: received_desc (the default), received_asc, added_desc, added_asc, rating_desc, rating_asc, person_asc, length_desc, length_asc, used_desc or used_asc","enum":["received_desc","received_asc","added_desc","added_asc","rating_desc","rating_asc","person_asc","length_desc","length_asc","used_desc","used_asc"],"default":"received_desc"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"Manual only. Up to 100 testimonial ids (tm_...) to start it filled, in this order"}},"required":["name"]}}}}},"get":{"operationId":"testimonial_collections_list","summary":"List the collections of a site","description":"Each collection comes with how many testimonials it holds right now, how many of those are approved, its rules in plain English when it is a smart one, and the widgets and walls it feeds. Collections in the trash are left out.","tags":["Testimonial collections"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Narrow the list to collections whose name or description contains this text"}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","description":"manual or smart","enum":["manual","smart"]}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"name (the default), updated (most recently changed first) or size (most testimonials first)","enum":["name","updated","size"],"default":"name"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The collection id (col_...)"},"name":{"type":"string","description":"Its name"},"description":{"anyOf":[{"type":"string","description":"A note for your team. Null when there is none"},{"type":"null"}]},"kind":{"type":"string","description":"manual or smart"},"match":{"anyOf":[{"type":"string","description":"Smart only: all or any. Null for a manual collection"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Smart only: the rules as rows of { field, operator, value }. Empty for a manual collection"},"sort":{"anyOf":[{"type":"string","description":"Smart only: the order its testimonials are served in. A manual collection is served in the order it was put in"},{"type":"null"}]},"summary":{"anyOf":[{"type":"string","description":"Smart only: the rules in plain English. Null when a rule no longer reads, for example because it names a tag that is in the trash"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"How many testimonials it holds right now, the trash left out"},"approved_count":{"type":"integer","description":"How many of those are approved. Widgets and walls show only these"},"feeds":{"type":"array","items":{"type":"object"},"description":"The widgets and walls that take their testimonials from it, each as { type, id, name }"},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null otherwise"},{"type":"null"}]},"locked":{"type":"boolean","description":"True for a smart collection on a plan without smart collections. It is kept, holds what matched its rules when the plan changed and takes in nothing new"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_collections_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/collections/{id}.json":{"delete":{"operationId":"testimonial_collections_destroy","summary":"Move a collection to the trash for 30 days","description":"Its testimonials are not touched. A widget or wall it feeds shows nothing from it until it is restored. Restore it with testimonial_trash_restore. Over MCP the tool changes nothing and responds with the page of the app where a person does it.","tags":["Testimonial collections"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_collections_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The collection id (col_...)"},"name":{"type":"string","description":"Its name"},"description":{"anyOf":[{"type":"string","description":"A note for your team. Null when there is none"},{"type":"null"}]},"kind":{"type":"string","description":"manual or smart"},"match":{"anyOf":[{"type":"string","description":"Smart only: all or any. Null for a manual collection"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Smart only: the rules as rows of { field, operator, value }. Empty for a manual collection"},"sort":{"anyOf":[{"type":"string","description":"Smart only: the order its testimonials are served in. A manual collection is served in the order it was put in"},{"type":"null"}]},"summary":{"anyOf":[{"type":"string","description":"Smart only: the rules in plain English. Null when a rule no longer reads, for example because it names a tag that is in the trash"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"How many testimonials it holds right now, the trash left out"},"approved_count":{"type":"integer","description":"How many of those are approved. Widgets and walls show only these"},"feeds":{"type":"array","items":{"type":"object"},"description":"The widgets and walls that take their testimonials from it, each as { type, id, name }"},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null otherwise"},{"type":"null"}]},"locked":{"type":"boolean","description":"True for a smart collection on a plan without smart collections. It is kept, holds what matched its rules when the plan changed and takes in nothing new"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"testimonial_collections_get","summary":"Get one collection with its counts, its rules and what it feeds","description":"Its testimonials are testimonials_list with collection_id.","tags":["Testimonial collections"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_collections_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The collection id (col_...)"},"name":{"type":"string","description":"Its name"},"description":{"anyOf":[{"type":"string","description":"A note for your team. Null when there is none"},{"type":"null"}]},"kind":{"type":"string","description":"manual or smart"},"match":{"anyOf":[{"type":"string","description":"Smart only: all or any. Null for a manual collection"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Smart only: the rules as rows of { field, operator, value }. Empty for a manual collection"},"sort":{"anyOf":[{"type":"string","description":"Smart only: the order its testimonials are served in. A manual collection is served in the order it was put in"},{"type":"null"}]},"summary":{"anyOf":[{"type":"string","description":"Smart only: the rules in plain English. Null when a rule no longer reads, for example because it names a tag that is in the trash"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"How many testimonials it holds right now, the trash left out"},"approved_count":{"type":"integer","description":"How many of those are approved. Widgets and walls show only these"},"feeds":{"type":"array","items":{"type":"object"},"description":"The widgets and walls that take their testimonials from it, each as { type, id, name }"},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null otherwise"},{"type":"null"}]},"locked":{"type":"boolean","description":"True for a smart collection on a plan without smart collections. It is kept, holds what matched its rules when the plan changed and takes in nothing new"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_collections_get","x-permission":"analytics.read"},"patch":{"operationId":"testimonial_collections_update","summary":"Change a collection's name, description, rules or served order","description":"Only what is sent changes. Sending conditions replaces every rule of a smart collection. The kind is fixed.","tags":["Testimonial collections"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_collections_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The collection id (col_...)"},"name":{"type":"string","description":"Its name"},"description":{"anyOf":[{"type":"string","description":"A note for your team. Null when there is none"},{"type":"null"}]},"kind":{"type":"string","description":"manual or smart"},"match":{"anyOf":[{"type":"string","description":"Smart only: all or any. Null for a manual collection"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Smart only: the rules as rows of { field, operator, value }. Empty for a manual collection"},"sort":{"anyOf":[{"type":"string","description":"Smart only: the order its testimonials are served in. A manual collection is served in the order it was put in"},{"type":"null"}]},"summary":{"anyOf":[{"type":"string","description":"Smart only: the rules in plain English. Null when a rule no longer reads, for example because it names a tag that is in the trash"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"How many testimonials it holds right now, the trash left out"},"approved_count":{"type":"integer","description":"How many of those are approved. Widgets and walls show only these"},"feeds":{"type":"array","items":{"type":"object"},"description":"The widgets and walls that take their testimonials from it, each as { type, id, name }"},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null otherwise"},{"type":"null"}]},"locked":{"type":"boolean","description":"True for a smart collection on a plan without smart collections. It is kept, holds what matched its rules when the plan changed and takes in nothing new"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_collections_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Up to 80 characters, unique on the site without regard to case"},"description":{"type":"string","description":"Up to 280 characters. An empty text clears it"},"kind":{"type":"string","description":"Cannot change. Sending the other kind is an error","enum":["manual","smart"]},"match":{"type":"string","description":"Smart only. all or any","enum":["all","any"]},"conditions":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Smart only. Replaces every rule. 1 to 20 rows of { field, operator, value }, as in testimonial_collections_create"},"sort":{"type":"string","description":"Smart only. The order its testimonials are served in","enum":["received_desc","received_asc","added_desc","added_asc","rating_desc","rating_asc","person_asc","length_desc","length_asc","used_desc","used_asc"]}}}}}}}},"/sites/{site_id}/testimonials/collections/preview.json":{"get":{"operationId":"testimonial_collections_preview","summary":"Try a set of rules without saving anything","description":"Responds with how many testimonials match right now, the rules in plain English and five examples. Use it before testimonial_collections_create or testimonial_tags_update. An invalid row is a 422 that names the row.","tags":["Testimonial collections"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"match","in":"query","required":false,"schema":{"type":"string","description":"all (the default: every condition must match) or any","enum":["all","any"],"default":"all"}},{"name":"conditions","in":"query","required":false,"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Rows of { field, operator, value }, as in testimonial_collections_create. Up to 20"}},{"name":"use","in":"query","required":false,"schema":{"type":"string","description":"Whose rules these are: collection (the default) or tag. A tag rule may test words, source, source_name, form, language, rating, url_param.<name> and property.<key>","enum":["collection","tag"],"default":"collection"}},{"name":"explain","in":"query","required":false,"schema":{"type":"boolean","description":"true responds 200 even when a row does not read: nothing is counted and problems lists each row with its sentence. The default responds 422","default":false}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"count":{"type":"integer","description":"How many testimonials match right now"},"approved_count":{"type":"integer","description":"How many of those are approved"},"summary":{"anyOf":[{"type":"string","description":"The rules in plain English. Null when a row does not read"},{"type":"null"}]},"examples":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"description":"Up to five testimonials that match, newest first"},"problems":{"type":"array","items":{"type":"object"},"description":"Empty unless explain was sent and a row does not read. Then each entry is { row, message }, with row counted from 1 (null for a problem with the rule as a whole)"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_collections_preview","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/collections/{id}/reorder.json":{"post":{"operationId":"testimonial_collections_reorder","summary":"Move one testimonial to another place in a manual collection","description":"Name the place with exactly one of position (counted from 1), before_id or after_id. The order is the order served to every widget and wall the collection feeds.","tags":["Testimonial collections"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_collections_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The collection id (col_...)"},"name":{"type":"string","description":"Its name"},"description":{"anyOf":[{"type":"string","description":"A note for your team. Null when there is none"},{"type":"null"}]},"kind":{"type":"string","description":"manual or smart"},"match":{"anyOf":[{"type":"string","description":"Smart only: all or any. Null for a manual collection"},{"type":"null"}]},"conditions":{"type":"array","items":{"type":"object"},"description":"Smart only: the rules as rows of { field, operator, value }. Empty for a manual collection"},"sort":{"anyOf":[{"type":"string","description":"Smart only: the order its testimonials are served in. A manual collection is served in the order it was put in"},{"type":"null"}]},"summary":{"anyOf":[{"type":"string","description":"Smart only: the rules in plain English. Null when a rule no longer reads, for example because it names a tag that is in the trash"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"How many testimonials it holds right now, the trash left out"},"approved_count":{"type":"integer","description":"How many of those are approved. Widgets and walls show only these"},"feeds":{"type":"array","items":{"type":"object"},"description":"The widgets and walls that take their testimonials from it, each as { type, id, name }"},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null otherwise"},{"type":"null"}]},"locked":{"type":"boolean","description":"True for a smart collection on a plan without smart collections. It is kept, holds what matched its rules when the plan changed and takes in nothing new"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_collections_reorder","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"testimonial_id":{"type":"string","description":"The testimonial to move (tm_...). It must be in this collection"},"position":{"type":"integer","description":"Its new place, counted from 1 among the collection's testimonials"},"before_id":{"type":"string","description":"The testimonial (tm_...) it lands just before"},"after_id":{"type":"string","description":"The testimonial (tm_...) it lands just after"}},"required":["testimonial_id"]}}}}}},"/sites/{site_id}/testimonials/companies.json":{"get":{"operationId":"testimonial_companies_list","summary":"List the companies of a site with their people, testimonials and average rating","description":"One row per company, grouped from the company name and website of the site's people. A person with no company is in none. query matches part of a company name or of its website host. sort is name (the default), people_desc, testimonials_desc or received_desc.","tags":["Testimonial companies"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Part of a company name or website host"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"name (the default), people_desc, testimonials_desc or received_desc","enum":["name","people_desc","testimonials_desc","received_desc"],"default":"name"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The company's key, a website host or a normalized name"},"name":{"type":"string","description":"The spelling most of its people have"},"url":{"anyOf":[{"type":"string","description":"The company website most of its people have"},{"type":"null"}]},"people_count":{"type":"integer","description":"How many people work there"},"testimonials_count":{"type":"integer","description":"How many testimonials its people have given"},"average_rating":{"anyOf":[{"type":"number","description":"The average rating of those testimonials, or null"},{"type":"null"}]},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the newest of them was received"},{"type":"null"}]}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_companies_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/companies/{id}/merge.json":{"post":{"operationId":"testimonial_companies_merge","summary":"Merge a company into another one, for two spellings of one company","description":"Every person of the company in the path takes the name and URL of the company named by into.","tags":["Testimonial companies"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_companies_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The company's key, a website host or a normalized name"},"name":{"type":"string","description":"The spelling most of its people have"},"url":{"anyOf":[{"type":"string","description":"The company website most of its people have"},{"type":"null"}]},"people_count":{"type":"integer","description":"How many people work there"},"testimonials_count":{"type":"integer","description":"How many testimonials its people have given"},"average_rating":{"anyOf":[{"type":"number","description":"The average rating of those testimonials, or null"},{"type":"null"}]},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the newest of them was received"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_companies_merge","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"into":{"type":"string","description":"The id of the company to merge into, as testimonial_companies_list returns it"}},"required":["into"]}}}}}},"/sites/{site_id}/testimonials/companies/{id}.json":{"get":{"operationId":"testimonial_companies_get","summary":"Get one company with its people","description":"The id is the company's key, a website host or a normalized name, as testimonial_companies_list returns it. Its testimonials are testimonials_list with company.","tags":["Testimonial companies"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_companies_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The company's key, a website host or a normalized name"},"name":{"type":"string","description":"The spelling most of its people have"},"url":{"anyOf":[{"type":"string","description":"The company website most of its people have"},{"type":"null"}]},"people_count":{"type":"integer","description":"How many people work there"},"testimonials_count":{"type":"integer","description":"How many testimonials its people have given"},"average_rating":{"anyOf":[{"type":"number","description":"The average rating of those testimonials, or null"},{"type":"null"}]},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the newest of them was received"},{"type":"null"}]},"people":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]},"company_id":{"anyOf":[{"type":"string","description":"The id of their company for the companies operations"},{"type":"null"}]},"approved_count":{"type":"integer","description":"How many of their testimonials are approved"},"average_rating":{"anyOf":[{"type":"number","description":"The average rating of their testimonials, or null"},{"type":"null"}]},"last_asked_at":{"anyOf":[{"type":"string","format":"date-time","description":"When this site last asked them"},{"type":"null"}]},"last_ask_outcome":{"anyOf":[{"type":"string","description":"How the last ask ended: scheduled, sent, opened, submitted, bounced, unsubscribed, stopped or skipped"},{"type":"null"}]},"possible_duplicate":{"type":"boolean","description":"Another person of the site has the same name and company"},"created_at":{"type":"string","format":"date-time","description":"When the person was first stored"}}},"description":"Its people, up to 100, by name"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_companies_get","x-permission":"analytics.read"},"patch":{"operationId":"testimonial_companies_update","summary":"Correct a company's name and URL for all of its people at once","description":"The id of a company comes from its URL or name, so the response may carry a new id.","tags":["Testimonial companies"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_companies_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The company's key, a website host or a normalized name"},"name":{"type":"string","description":"The spelling most of its people have"},"url":{"anyOf":[{"type":"string","description":"The company website most of its people have"},{"type":"null"}]},"people_count":{"type":"integer","description":"How many people work there"},"testimonials_count":{"type":"integer","description":"How many testimonials its people have given"},"average_rating":{"anyOf":[{"type":"number","description":"The average rating of those testimonials, or null"},{"type":"null"}]},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the newest of them was received"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_companies_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"The company's name for all of its people, up to 120 characters"},"url":{"type":"string","description":"The company's website for all of its people (http or https). Empty clears it"}}}}}}}},"/sites/{site_id}/testimonials/settings/custom_domain.json":{"post":{"operationId":"testimonial_custom_domain_requests_create","summary":"Ask for a custom domain on a wall or on forms","description":"Custom domains for testimonials are set up by the Privatus Analytics team by hand. This stores the request and tells the team, who email the DNS record to add. The hostname does not work until the request's status is active. Business and up: other plans get 402 plan_limit.","tags":["Testimonial custom domain requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The request id (cdr_...)"},"hostname":{"type":"string","description":"The hostname asked for"},"page":{"type":"string","description":"wall or forms"},"wall_id":{"anyOf":[{"type":"string","description":"The wall to serve, or null"},{"type":"null"}]},"note":{"anyOf":[{"type":"string","description":"The note sent with the request"},{"type":"null"}]},"status":{"type":"string","description":"requested (the team has been told), in_progress (the team has emailed the DNS record), active (the hostname serves the page), declined or withdrawn"},"decline_reason":{"anyOf":[{"type":"string","description":"Why the team declined, or null"},{"type":"null"}]},"handled_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the team last moved it along"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was requested"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_custom_domain_requests_create","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"hostname":{"type":"string","description":"The full hostname to use, such as reviews.example.com. Not an IP address, and not privatusanalytics.com or anything under it","examples":["reviews.example.com"]},"page":{"type":"string","description":"What the hostname should serve: wall or forms","enum":["wall","forms"]},"wall_id":{"type":"string","description":"With page wall, the wall to serve (wal_...). Needed when the site has more than one","examples":["wal_7Q2K9XH3AB"]},"note":{"type":"string","description":"Anything the team should know, up to 500 characters"}},"required":["hostname","page"]}}}}},"delete":{"operationId":"testimonial_custom_domain_requests_delete","summary":"Withdraw a custom domain request, by its hostname","description":"Only a request the team has not started on (status requested) can be withdrawn. One that is in progress responds with wrong_state. Over MCP the tool changes nothing and responds with the page of the app where a person does it.","tags":["Testimonial custom domain requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The request id (cdr_...)"},"hostname":{"type":"string","description":"The hostname asked for"},"page":{"type":"string","description":"wall or forms"},"wall_id":{"anyOf":[{"type":"string","description":"The wall to serve, or null"},{"type":"null"}]},"note":{"anyOf":[{"type":"string","description":"The note sent with the request"},{"type":"null"}]},"status":{"type":"string","description":"requested (the team has been told), in_progress (the team has emailed the DNS record), active (the hostname serves the page), declined or withdrawn"},"decline_reason":{"anyOf":[{"type":"string","description":"Why the team declined, or null"},{"type":"null"}]},"handled_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the team last moved it along"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was requested"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"hostname":{"type":"string","description":"The hostname of the request to withdraw","examples":["reviews.example.com"]}},"required":["hostname"]}}}}},"get":{"operationId":"testimonial_custom_domain_requests_list","summary":"List the custom domain requests of a site","description":"Every request for a hostname on a wall or on forms, newest first, with its status. The hostname works only once status is active. Works on every plan, so earlier requests can still be read.","tags":["Testimonial custom domain requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Only requests in this state: requested, in_progress, active, declined or withdrawn","enum":["requested","in_progress","active","declined","withdrawn"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The request id (cdr_...)"},"hostname":{"type":"string","description":"The hostname asked for"},"page":{"type":"string","description":"wall or forms"},"wall_id":{"anyOf":[{"type":"string","description":"The wall to serve, or null"},{"type":"null"}]},"note":{"anyOf":[{"type":"string","description":"The note sent with the request"},{"type":"null"}]},"status":{"type":"string","description":"requested (the team has been told), in_progress (the team has emailed the DNS record), active (the hostname serves the page), declined or withdrawn"},"decline_reason":{"anyOf":[{"type":"string","description":"Why the team declined, or null"},{"type":"null"}]},"handled_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the team last moved it along"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was requested"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_custom_domain_requests_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/settings/properties.json":{"post":{"operationId":"testimonial_properties_create","summary":"Add a custom property to a site","description":"A site holds up to 20 active properties. The key is fixed once made, because form links, rules and the API use it. Leave it out and it is suggested from the label.","tags":["Testimonial custom properties"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"key":{"type":"string","description":"The key. Values are stored under it on each testimonial, and it is the id in the path"},"label":{"type":"string","description":"What people see"},"type":{"type":"string","description":"text, choice, number or yes_no"},"choices":{"type":"array","items":{"type":"string"},"description":"The choices of a choice property, in order"},"url_param":{"type":"string","description":"The form URL parameter that fills it. The key unless another was set"},"facet":{"type":"boolean","description":"It is shown in the filter rail of the inbox"},"column":{"type":"boolean","description":"It is offered in the Columns menu of the inbox"},"position":{"type":"integer","description":"Its place in the display order, from 1"},"archived":{"type":"boolean","description":"It is hidden from forms, facets, rules and columns. Every value is kept"},"filled":{"type":"integer","description":"How many testimonials (not in the trash) hold a value"},"type_fixed":{"type":"boolean","description":"true once a testimonial holds a value. The type can no longer change"},"used_by":{"type":"array","items":{"type":"object"},"description":"The smart collections and auto-tag rules that filter on it, each { type, id, name }. type is collection or tag_rule (then id and name are the tag's)"},"created_at":{"type":"string","format":"date-time","description":"When the property was added"},"updated_at":{"type":"string","format":"date-time","description":"When the property was last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_properties_create","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","description":"What people see. Up to 40 characters"},"key":{"type":"string","description":"Lowercase letters, digits and underscores, starting with a letter, up to 30 characters, unique on the site. Fixed once made. Left out, it is suggested from the label"},"type":{"type":"string","description":"text (the default), choice, number or yes_no","enum":["text","choice","number","yes_no"],"default":"text"},"choices":{"type":"array","items":{"type":"string"},"description":"For choice only. The list of choices, in order, up to 50"},"url_param":{"type":"string","description":"A form URL parameter that fills it on submission, as in ?plan=team. Defaults to the key"},"facet":{"type":"boolean","description":"Show it in the filter rail of the inbox. Default true","default":true},"column":{"type":"boolean","description":"Offer it in the Columns menu of the inbox. Default false","default":false},"position":{"type":"integer","description":"Its place in the display order. 1 is first. Left out, it goes last"}},"required":["label"]}}}}},"get":{"operationId":"testimonial_properties_list","summary":"List the custom properties of a site, in display order","description":"Each one says its key, type and choices, how many testimonials hold a value (filled), whether its type can still change, and which smart collections and auto-tag rules use it.","tags":["Testimonial custom properties"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"archived","in":"query","required":false,"schema":{"type":"string","description":"yes for the archived ones only, no for the active ones only. Left out, both are listed","enum":["yes","no"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The key. Values are stored under it on each testimonial, and it is the id in the path"},"label":{"type":"string","description":"What people see"},"type":{"type":"string","description":"text, choice, number or yes_no"},"choices":{"type":"array","items":{"type":"string"},"description":"The choices of a choice property, in order"},"url_param":{"type":"string","description":"The form URL parameter that fills it. The key unless another was set"},"facet":{"type":"boolean","description":"It is shown in the filter rail of the inbox"},"column":{"type":"boolean","description":"It is offered in the Columns menu of the inbox"},"position":{"type":"integer","description":"Its place in the display order, from 1"},"archived":{"type":"boolean","description":"It is hidden from forms, facets, rules and columns. Every value is kept"},"filled":{"type":"integer","description":"How many testimonials (not in the trash) hold a value"},"type_fixed":{"type":"boolean","description":"true once a testimonial holds a value. The type can no longer change"},"used_by":{"type":"array","items":{"type":"object"},"description":"The smart collections and auto-tag rules that filter on it, each { type, id, name }. type is collection or tag_rule (then id and name are the tag's)"},"created_at":{"type":"string","format":"date-time","description":"When the property was added"},"updated_at":{"type":"string","format":"date-time","description":"When the property was last changed"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_properties_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/settings/properties/{id}.json":{"delete":{"operationId":"testimonial_properties_destroy","summary":"Delete a custom property and its values for good","description":"This cannot be undone. It removes the property and its value from every testimonial. confirm is the key. A property used by a smart collection or an auto-tag rule cannot be deleted while they use it. Archive is the everyday way to retire one.","tags":["Testimonial custom properties"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_properties_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"key":{"type":"string","description":"The key of the property that was deleted"},"deleted":{"type":"boolean","description":"Always true"},"testimonials":{"type":"integer","description":"How many testimonials lost a value"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"string","description":"The key of the property"}}}}}}},"patch":{"operationId":"testimonial_properties_update","summary":"Change, reorder, archive or bring back a custom property","description":"Only the inputs you send change anything. Renaming a choice renames it on every testimonial that has it. A property used by a smart collection or an auto-tag rule cannot be archived while they use it.","tags":["Testimonial custom properties"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_properties_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"key":{"type":"string","description":"The key. Values are stored under it on each testimonial, and it is the id in the path"},"label":{"type":"string","description":"What people see"},"type":{"type":"string","description":"text, choice, number or yes_no"},"choices":{"type":"array","items":{"type":"string"},"description":"The choices of a choice property, in order"},"url_param":{"type":"string","description":"The form URL parameter that fills it. The key unless another was set"},"facet":{"type":"boolean","description":"It is shown in the filter rail of the inbox"},"column":{"type":"boolean","description":"It is offered in the Columns menu of the inbox"},"position":{"type":"integer","description":"Its place in the display order, from 1"},"archived":{"type":"boolean","description":"It is hidden from forms, facets, rules and columns. Every value is kept"},"filled":{"type":"integer","description":"How many testimonials (not in the trash) hold a value"},"type_fixed":{"type":"boolean","description":"true once a testimonial holds a value. The type can no longer change"},"used_by":{"type":"array","items":{"type":"object"},"description":"The smart collections and auto-tag rules that filter on it, each { type, id, name }. type is collection or tag_rule (then id and name are the tag's)"},"created_at":{"type":"string","format":"date-time","description":"When the property was added"},"updated_at":{"type":"string","format":"date-time","description":"When the property was last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_properties_update","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","description":"What people see. Up to 40 characters"},"type":{"type":"string","description":"text, choice, number or yes_no. Only while no testimonial holds a value","enum":["text","choice","number","yes_no"]},"choices":{"type":"array","items":{"type":"string"},"description":"For choice only. The whole list of choices in its new order"},"choices_were":{"type":"array","items":{"type":"string"},"description":"To rename choices: the earlier name of each entry of choices, in the same order, with an empty string for a new one. A renamed choice is renamed on every testimonial that has it"},"url_param":{"type":"string","description":"A form URL parameter that fills it on submission. An empty string goes back to the key"},"facet":{"type":"boolean","description":"Show it in the filter rail of the inbox"},"column":{"type":"boolean","description":"Offer it in the Columns menu of the inbox"},"position":{"type":"integer","description":"Moves it to this place in the display order. 1 is first"},"archived":{"type":"boolean","description":"true hides it from forms, facets, rules and columns and keeps every value. false brings it back"}}}}}}}},"/sites/{site_id}/testimonials/duplicates/dismiss.json":{"post":{"operationId":"testimonial_duplicates_dismiss","summary":"Say that a group is not duplicates. It never returns to the queue","description":"testimonial_ids must be every copy of one open group of the duplicates queue that is out of the trash, as testimonial_duplicates_list returns them. Nothing is merged or changed on the testimonials, and they are never grouped together again. To split a group of three, merge the two that are the same first. The server responds with 422 when the ids are not exactly one open group.","tags":["Testimonial duplicates"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"reason":{"type":"string","description":"same_review, same_words, near_words or same_words_other_person"},"confidence":{"type":"string","description":"exact or likely"},"status":{"type":"string","description":"open, merged or dismissed"},"found_at":{"type":"string","format":"date-time","description":"When the group was opened"},"keeper_id":{"anyOf":[{"type":"string","description":"The copy that would be kept (in use, then approved, then verified, then oldest)"},{"type":"null"}]},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The ids of its copies that are not in the trash"},"testimonials":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"description":"The copies in full, oldest first"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_duplicates_dismiss","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The ids (tm_...) of every copy of one group, as testimonial_duplicates_list returns them"}},"required":["testimonial_ids"]}}}}}},"/sites/{site_id}/testimonials/duplicates.json":{"get":{"operationId":"testimonial_duplicates_list","summary":"List the groups of testimonials that are probably the same one twice","description":"Exact matches come first. Each group carries its copies in full and keeper_id, the copy that would be kept. meta.exact_groups is how many groups testimonial_duplicates_merge_exact would merge.","tags":["Testimonial duplicates"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"confidence","in":"query","required":false,"schema":{"type":"string","description":"exact for copies that are certainly the same, likely for the rest","enum":["exact","likely"]}},{"name":"reason","in":"query","required":false,"schema":{"type":"string","description":"same_review (one review that arrived twice), same_words (one person, the same words), near_words (one person, nearly the same words) or same_words_other_person (the same words under two people)","enum":["same_review","same_words","near_words","same_words_other_person"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"reason":{"type":"string","description":"same_review, same_words, near_words or same_words_other_person"},"confidence":{"type":"string","description":"exact or likely"},"status":{"type":"string","description":"open, merged or dismissed"},"found_at":{"type":"string","format":"date-time","description":"When the group was opened"},"keeper_id":{"anyOf":[{"type":"string","description":"The copy that would be kept (in use, then approved, then verified, then oldest)"},{"type":"null"}]},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The ids of its copies that are not in the trash"},"testimonials":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"description":"The copies in full, oldest first"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_duplicates_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/{id}/merge.json":{"post":{"operationId":"testimonials_merge","summary":"Merge copies of a testimonial into the one in the path","description":"The keeper keeps its status and verified state, and its words unless body_from names another copy. It gains the tags, manual collections, placements and custom properties it lacks. The copies go to the trash marked as merged, and restoring one undoes the merge for that copy. A copy that arrived this month stops counting as a new testimonial. The response carries meta.undo_id.","tags":["Testimonial duplicates"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_duplicates_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_merge","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"duplicate_ids":{"type":"array","items":{"type":"string"},"description":"The ids (tm_...) of 1 to 20 copies. They go to the trash marked as merged into the keeper"},"body_from":{"type":"string","description":"The id of the copy whose words the keeper takes. Left out, the keeper keeps its own"}},"required":["duplicate_ids"]}}}}}},"/sites/{site_id}/testimonials/duplicates/merge_exact.json":{"post":{"operationId":"testimonial_duplicates_merge_exact","summary":"Merge every exact match of the queue at once","description":"Send dry_run first for the counts, then confirm_count with the total it gave. Up to 100 groups are merged per call. The response carries meta.undo_id, and one undo takes the whole run back.","tags":["Testimonial duplicates"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"anyOf":[{"type":"string","description":"The undo record id (blk_...). Null for a dry run and for delete_permanently"},{"type":"null"}]},"action":{"type":"string","description":"The action that ran"},"state":{"type":"string","description":"done, running (in the background), dry_run, undone, failed or expired"},"total":{"type":"integer","description":"How many testimonials the selection held"},"changed":{"type":"integer","description":"How many were changed"},"skipped":{"type":"integer","description":"How many were left as they were"},"skipped_reasons":{"type":"object","description":"Why, with a count each: already_in_state, waiting_for_allowance, in_trash, not_in_trash"},"undoable":{"type":"boolean","description":"It can be undone now"},"undo_until":{"anyOf":[{"type":"string","format":"date-time","description":"Until when it can be undone"},{"type":"null"}]},"reverted":{"anyOf":[{"type":"integer","description":"After an undo, how many went back"},{"type":"null"}]},"left":{"anyOf":[{"type":"object","description":"After an undo, how many were left alone and why: changed_since, deleted"},{"type":"null"}]},"created_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the run began"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_duplicates_merge_exact","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm_count":{"type":"integer","description":"The number of exact groups you expect to merge, as dry_run or meta.exact_groups gave it"},"dry_run":{"type":"boolean","description":"true responds with the counts and merges nothing","default":false}}}}}}}},"/sites/{site_id}/testimonials/images/bulk.json":{"post":{"operationId":"testimonial_images_bulk_create","summary":"Make images for every approved testimonial of a collection","description":"Up to 200 testimonials a run, one image per size each. A text too long for the picture is drawn from its highlight, or else from its opening sentences (excerpted says how many). The response lists the images started, the testimonials left out with the reason, and export_id: one zip of the PNGs appears on the Exports page when they are drawn.","tags":["Testimonial images"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"images":{"type":"array","items":{"type":"object"},"description":"The images started, each as testimonial_images_get returns it"},"skipped":{"type":"array","items":{"type":"object"},"description":"The testimonials left out, each with testimonial_id and reason: text_too_long, unsupported_text or not_video"},"excerpted":{"type":"integer","description":"How many testimonials were drawn from their opening sentences, because the whole text did not fit and they had no highlight that did"},"export_id":{"type":"string","description":"The export (exp_...) that will hold the zip of the PNGs, listed by exports_list"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_images_bulk_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"string","description":"quote_card (the words on a bordered card, the person beneath), big_quote (large words, a small attribution), photo_side (the photo on one side, the words on the other), rating_first (large stars or hearts above the words), highlight (only the highlight, on a solid block of the accent color), plain (words and person, no card) or video_still (the video's poster with a play mark, video testimonials only). Default quote_card","enum":["quote_card","big_quote","photo_side","rating_first","highlight","plain","video_still"]},"text_mode":{"type":"string","description":"Which words: full (everything), highlight (the highlighted passage, or everything when there is none) or excerpt (a run chosen with excerpt_start and excerpt_end, or with neither, the opening sentences that fit). Default full. Words are never set smaller than about 30 pixels, so a long text is refused with text_too_long","enum":["full","highlight","excerpt"]},"excerpt_start":{"type":"integer","description":"With text_mode excerpt, the character position in the testimonial where the run starts, from 0. It is widened to whole words"},"excerpt_end":{"type":"integer","description":"With text_mode excerpt, the character position where the run ends. An ellipsis is added on each side that was cut"},"show_rating":{"type":"boolean","description":"Draw the rating. Default true"},"show_photo":{"type":"boolean","description":"Draw the person's photo, or their initials when there is none. Hidden whatever this says when the giver did not agree to show a photo. Default true"},"show_name":{"type":"boolean","description":"Draw the person's name. Hidden whatever this says when the giver did not agree to show their name. Default true"},"show_company":{"type":"boolean","description":"Draw the person's job title and company. Hidden with the name. Default true"},"show_source":{"type":"boolean","description":"Draw where it came from, such as \"via Trustpilot\". Default false"},"show_verified":{"type":"boolean","description":"Draw the verified mark beside the name of a verified testimonial. Default false"},"show_date":{"type":"boolean","description":"Draw the month and year it was received. Default false"},"show_logo":{"type":"boolean","description":"Draw the site's logo. Default true"},"background":{"type":"string","description":"brand (the brand kit's light colors, the default), light (white with near-black text), dark (the brand kit's dark colors), custom (background_color) or transparent (no background, for placing on a slide)","enum":["brand","light","dark","custom","transparent"]},"background_color":{"type":"string","description":"With background custom: the background as #rrggbb. Empty falls back to the brand kit","examples":["#06755b"]},"text_color":{"type":"string","description":"The color of the words as #rrggbb. Empty follows the background","examples":["#06755b"]},"accent_color":{"type":"string","description":"The accent as #rrggbb: the quotation mark, hearts and the highlight template's block. Empty follows the brand kit","examples":["#06755b"]},"rating_style":{"type":"string","description":"inherit (the brand kit's choice, the default), stars or hearts","enum":["inherit","stars","hearts"]},"align":{"type":"string","description":"left (the default) or center","enum":["left","center"]},"scale":{"type":"integer","description":"1 (the default) or 2, which doubles the pixels for print and large screens","enum":[1,2]},"show_badge":{"type":"boolean","description":"The small \"Collected with Privatus Analytics\" badge. null follows the brand kit. false is refused with plan_limit below Business, where the badge stays"},"collection_id":{"type":"string","description":"The collection whose approved testimonials are drawn (col_...), in the collection's order","examples":["col_7Q2K9XH3AB"]},"sizes":{"type":"array","items":{"type":"string","enum":["square","portrait","story","landscape","linkedin","open_graph","pinterest","wide"]},"description":"The sizes to make, one image each: square (1080 x 1080), portrait (1080 x 1350), story (1080 x 1920), landscape (1200 x 675), linkedin (1200 x 627), open_graph (1200 x 630), pinterest (1000 x 1500), wide (1920 x 1080). Default square"}},"required":["collection_id"]}}}}}},"/sites/{site_id}/testimonials/images.json":{"post":{"operationId":"testimonial_images_create","summary":"Make images of one approved testimonial, one per size","description":"Only an approved testimonial can be drawn, because the PNG gets a public address: any other is refused with not_approved. Each image starts as rendering and is drawn in the background. The response is the list of images started. Poll testimonial_images_get for file_url. A 422 with text_too_long means the words do not fit: use text_mode highlight or excerpt, or a taller size.","tags":["Testimonial images"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The image id (img_...)"},"testimonial_id":{"type":"string","description":"The testimonial it draws (tm_...)"},"template":{"type":"string","description":"The template it is drawn with"},"size":{"type":"string","description":"The size preset"},"status":{"type":"string","description":"rendering (being drawn), ready or failed"},"error":{"anyOf":[{"type":"string","description":"Why it failed, as a sentence. null otherwise"},{"type":"null"}]},"file_url":{"anyOf":[{"type":"string","description":"The address of the PNG on the media host once it is ready, the same for everyone. null while it is being drawn. The file is deleted when its testimonial is no longer approved"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Pixels wide, scale included. null until it is ready"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Pixels high, scale included. null until it is ready"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size of the PNG in bytes. null until it is ready"},{"type":"null"}]},"text_mode":{"type":"string","description":"full, highlight or excerpt"},"excerpt_start":{"anyOf":[{"type":"integer","description":"Where the excerpt starts, as a character position"},{"type":"null"}]},"excerpt_end":{"anyOf":[{"type":"integer","description":"Where the excerpt ends, as a character position"},{"type":"null"}]},"show_rating":{"type":"boolean","description":"The rating is drawn"},"show_photo":{"type":"boolean","description":"The photo is drawn, when the giver agreed to it"},"show_name":{"type":"boolean","description":"The name is drawn, when the giver agreed to it"},"show_company":{"type":"boolean","description":"The job title and company are drawn"},"show_source":{"type":"boolean","description":"Where it came from is drawn"},"show_verified":{"type":"boolean","description":"The verified mark is drawn"},"show_date":{"type":"boolean","description":"The month and year are drawn"},"show_logo":{"type":"boolean","description":"The site's logo is drawn"},"background":{"type":"string","description":"brand, light, dark, custom or transparent"},"background_color":{"anyOf":[{"type":"string","description":"The custom background, or null"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"The color of the words, or null to follow the background"},{"type":"null"}]},"accent_color":{"anyOf":[{"type":"string","description":"The accent, or null to follow the brand kit"},{"type":"null"}]},"rating_style":{"type":"string","description":"inherit, stars or hearts"},"align":{"type":"string","description":"left or center"},"scale":{"type":"integer","description":"1 or 2"},"show_badge":{"anyOf":[{"type":"boolean","description":"The badge switch, or null to follow the brand kit"},{"type":"null"}]},"testimonial_changed":{"type":"boolean","description":"true when the testimonial's words were edited after this image was made. Render it again with testimonial_images_update"},"rendered_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the PNG was last made"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When the image was created"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_images_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"string","description":"quote_card (the words on a bordered card, the person beneath), big_quote (large words, a small attribution), photo_side (the photo on one side, the words on the other), rating_first (large stars or hearts above the words), highlight (only the highlight, on a solid block of the accent color), plain (words and person, no card) or video_still (the video's poster with a play mark, video testimonials only). Default quote_card","enum":["quote_card","big_quote","photo_side","rating_first","highlight","plain","video_still"]},"text_mode":{"type":"string","description":"Which words: full (everything), highlight (the highlighted passage, or everything when there is none) or excerpt (a run chosen with excerpt_start and excerpt_end, or with neither, the opening sentences that fit). Default full. Words are never set smaller than about 30 pixels, so a long text is refused with text_too_long","enum":["full","highlight","excerpt"]},"excerpt_start":{"type":"integer","description":"With text_mode excerpt, the character position in the testimonial where the run starts, from 0. It is widened to whole words"},"excerpt_end":{"type":"integer","description":"With text_mode excerpt, the character position where the run ends. An ellipsis is added on each side that was cut"},"show_rating":{"type":"boolean","description":"Draw the rating. Default true"},"show_photo":{"type":"boolean","description":"Draw the person's photo, or their initials when there is none. Hidden whatever this says when the giver did not agree to show a photo. Default true"},"show_name":{"type":"boolean","description":"Draw the person's name. Hidden whatever this says when the giver did not agree to show their name. Default true"},"show_company":{"type":"boolean","description":"Draw the person's job title and company. Hidden with the name. Default true"},"show_source":{"type":"boolean","description":"Draw where it came from, such as \"via Trustpilot\". Default false"},"show_verified":{"type":"boolean","description":"Draw the verified mark beside the name of a verified testimonial. Default false"},"show_date":{"type":"boolean","description":"Draw the month and year it was received. Default false"},"show_logo":{"type":"boolean","description":"Draw the site's logo. Default true"},"background":{"type":"string","description":"brand (the brand kit's light colors, the default), light (white with near-black text), dark (the brand kit's dark colors), custom (background_color) or transparent (no background, for placing on a slide)","enum":["brand","light","dark","custom","transparent"]},"background_color":{"type":"string","description":"With background custom: the background as #rrggbb. Empty falls back to the brand kit","examples":["#06755b"]},"text_color":{"type":"string","description":"The color of the words as #rrggbb. Empty follows the background","examples":["#06755b"]},"accent_color":{"type":"string","description":"The accent as #rrggbb: the quotation mark, hearts and the highlight template's block. Empty follows the brand kit","examples":["#06755b"]},"rating_style":{"type":"string","description":"inherit (the brand kit's choice, the default), stars or hearts","enum":["inherit","stars","hearts"]},"align":{"type":"string","description":"left (the default) or center","enum":["left","center"]},"scale":{"type":"integer","description":"1 (the default) or 2, which doubles the pixels for print and large screens","enum":[1,2]},"show_badge":{"type":"boolean","description":"The small \"Collected with Privatus Analytics\" badge. null follows the brand kit. false is refused with plan_limit below Business, where the badge stays"},"testimonial_id":{"type":"string","description":"The approved testimonial to draw (tm_...)","examples":["tm_7Q2K9XH3AB"]},"sizes":{"type":"array","items":{"type":"string","enum":["square","portrait","story","landscape","linkedin","open_graph","pinterest","wide"]},"description":"The sizes to make, one image each: square (1080 x 1080), portrait (1080 x 1350), story (1080 x 1920), landscape (1200 x 675), linkedin (1200 x 627), open_graph (1200 x 630), pinterest (1000 x 1500), wide (1920 x 1080). Default square"}},"required":["testimonial_id"]}}}}},"get":{"operationId":"testimonial_images_list","summary":"List the images of a site","description":"Images made from approved testimonials, newest first, 25 a page. Filter by status, template, size or testimonial_id. Each one carries file_url once it is ready.","tags":["Testimonial images"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Only images in this state: rendering, ready or failed","enum":["rendering","ready","failed"]}},{"name":"template","in":"query","required":false,"schema":{"type":"string","description":"Only images drawn with this template","enum":["quote_card","big_quote","photo_side","rating_first","highlight","plain","video_still"]}},{"name":"size","in":"query","required":false,"schema":{"type":"string","description":"Only images of this size","enum":["square","portrait","story","landscape","linkedin","open_graph","pinterest","wide"]}},{"name":"testimonial_id","in":"query","required":false,"schema":{"type":"string","description":"Only images of this testimonial (tm_...)","examples":["tm_7Q2K9XH3AB"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The image id (img_...)"},"testimonial_id":{"type":"string","description":"The testimonial it draws (tm_...)"},"template":{"type":"string","description":"The template it is drawn with"},"size":{"type":"string","description":"The size preset"},"status":{"type":"string","description":"rendering (being drawn), ready or failed"},"error":{"anyOf":[{"type":"string","description":"Why it failed, as a sentence. null otherwise"},{"type":"null"}]},"file_url":{"anyOf":[{"type":"string","description":"The address of the PNG on the media host once it is ready, the same for everyone. null while it is being drawn. The file is deleted when its testimonial is no longer approved"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Pixels wide, scale included. null until it is ready"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Pixels high, scale included. null until it is ready"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size of the PNG in bytes. null until it is ready"},{"type":"null"}]},"text_mode":{"type":"string","description":"full, highlight or excerpt"},"excerpt_start":{"anyOf":[{"type":"integer","description":"Where the excerpt starts, as a character position"},{"type":"null"}]},"excerpt_end":{"anyOf":[{"type":"integer","description":"Where the excerpt ends, as a character position"},{"type":"null"}]},"show_rating":{"type":"boolean","description":"The rating is drawn"},"show_photo":{"type":"boolean","description":"The photo is drawn, when the giver agreed to it"},"show_name":{"type":"boolean","description":"The name is drawn, when the giver agreed to it"},"show_company":{"type":"boolean","description":"The job title and company are drawn"},"show_source":{"type":"boolean","description":"Where it came from is drawn"},"show_verified":{"type":"boolean","description":"The verified mark is drawn"},"show_date":{"type":"boolean","description":"The month and year are drawn"},"show_logo":{"type":"boolean","description":"The site's logo is drawn"},"background":{"type":"string","description":"brand, light, dark, custom or transparent"},"background_color":{"anyOf":[{"type":"string","description":"The custom background, or null"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"The color of the words, or null to follow the background"},{"type":"null"}]},"accent_color":{"anyOf":[{"type":"string","description":"The accent, or null to follow the brand kit"},{"type":"null"}]},"rating_style":{"type":"string","description":"inherit, stars or hearts"},"align":{"type":"string","description":"left or center"},"scale":{"type":"integer","description":"1 or 2"},"show_badge":{"anyOf":[{"type":"boolean","description":"The badge switch, or null to follow the brand kit"},{"type":"null"}]},"testimonial_changed":{"type":"boolean","description":"true when the testimonial's words were edited after this image was made. Render it again with testimonial_images_update"},"rendered_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the PNG was last made"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When the image was created"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_images_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/images/{id}.json":{"delete":{"operationId":"testimonial_images_delete","summary":"Delete an image and its file","description":"The PNG is deleted from the media host and its address stops working. An image has no trash. It can be made again from its testimonial with testimonial_images_create. Over MCP the tool changes nothing and responds with the page of the app where a person does it.","tags":["Testimonial images"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_images_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The id of what was deleted"},"deleted":{"type":"boolean","description":"Always true"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"testimonial_images_get","summary":"Get one image, with its state and the address of its PNG","description":"status is rendering, ready or failed. file_url is set once it is ready. Poll this after testimonial_images_create until status is no longer rendering.","tags":["Testimonial images"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_images_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The image id (img_...)"},"testimonial_id":{"type":"string","description":"The testimonial it draws (tm_...)"},"template":{"type":"string","description":"The template it is drawn with"},"size":{"type":"string","description":"The size preset"},"status":{"type":"string","description":"rendering (being drawn), ready or failed"},"error":{"anyOf":[{"type":"string","description":"Why it failed, as a sentence. null otherwise"},{"type":"null"}]},"file_url":{"anyOf":[{"type":"string","description":"The address of the PNG on the media host once it is ready, the same for everyone. null while it is being drawn. The file is deleted when its testimonial is no longer approved"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Pixels wide, scale included. null until it is ready"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Pixels high, scale included. null until it is ready"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size of the PNG in bytes. null until it is ready"},{"type":"null"}]},"text_mode":{"type":"string","description":"full, highlight or excerpt"},"excerpt_start":{"anyOf":[{"type":"integer","description":"Where the excerpt starts, as a character position"},{"type":"null"}]},"excerpt_end":{"anyOf":[{"type":"integer","description":"Where the excerpt ends, as a character position"},{"type":"null"}]},"show_rating":{"type":"boolean","description":"The rating is drawn"},"show_photo":{"type":"boolean","description":"The photo is drawn, when the giver agreed to it"},"show_name":{"type":"boolean","description":"The name is drawn, when the giver agreed to it"},"show_company":{"type":"boolean","description":"The job title and company are drawn"},"show_source":{"type":"boolean","description":"Where it came from is drawn"},"show_verified":{"type":"boolean","description":"The verified mark is drawn"},"show_date":{"type":"boolean","description":"The month and year are drawn"},"show_logo":{"type":"boolean","description":"The site's logo is drawn"},"background":{"type":"string","description":"brand, light, dark, custom or transparent"},"background_color":{"anyOf":[{"type":"string","description":"The custom background, or null"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"The color of the words, or null to follow the background"},{"type":"null"}]},"accent_color":{"anyOf":[{"type":"string","description":"The accent, or null to follow the brand kit"},{"type":"null"}]},"rating_style":{"type":"string","description":"inherit, stars or hearts"},"align":{"type":"string","description":"left or center"},"scale":{"type":"integer","description":"1 or 2"},"show_badge":{"anyOf":[{"type":"boolean","description":"The badge switch, or null to follow the brand kit"},{"type":"null"}]},"testimonial_changed":{"type":"boolean","description":"true when the testimonial's words were edited after this image was made. Render it again with testimonial_images_update"},"rendered_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the PNG was last made"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When the image was created"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_images_get","x-permission":"analytics.read"},"patch":{"operationId":"testimonial_images_update","summary":"Change how an image is drawn and render it again","description":"Send only what changes. With nothing sent it renders the same image again from the testimonial as it is now, which is also how to retry one that failed. A new render has a new file_url, and the old file is deleted.","tags":["Testimonial images"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_images_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The image id (img_...)"},"testimonial_id":{"type":"string","description":"The testimonial it draws (tm_...)"},"template":{"type":"string","description":"The template it is drawn with"},"size":{"type":"string","description":"The size preset"},"status":{"type":"string","description":"rendering (being drawn), ready or failed"},"error":{"anyOf":[{"type":"string","description":"Why it failed, as a sentence. null otherwise"},{"type":"null"}]},"file_url":{"anyOf":[{"type":"string","description":"The address of the PNG on the media host once it is ready, the same for everyone. null while it is being drawn. The file is deleted when its testimonial is no longer approved"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Pixels wide, scale included. null until it is ready"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Pixels high, scale included. null until it is ready"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size of the PNG in bytes. null until it is ready"},{"type":"null"}]},"text_mode":{"type":"string","description":"full, highlight or excerpt"},"excerpt_start":{"anyOf":[{"type":"integer","description":"Where the excerpt starts, as a character position"},{"type":"null"}]},"excerpt_end":{"anyOf":[{"type":"integer","description":"Where the excerpt ends, as a character position"},{"type":"null"}]},"show_rating":{"type":"boolean","description":"The rating is drawn"},"show_photo":{"type":"boolean","description":"The photo is drawn, when the giver agreed to it"},"show_name":{"type":"boolean","description":"The name is drawn, when the giver agreed to it"},"show_company":{"type":"boolean","description":"The job title and company are drawn"},"show_source":{"type":"boolean","description":"Where it came from is drawn"},"show_verified":{"type":"boolean","description":"The verified mark is drawn"},"show_date":{"type":"boolean","description":"The month and year are drawn"},"show_logo":{"type":"boolean","description":"The site's logo is drawn"},"background":{"type":"string","description":"brand, light, dark, custom or transparent"},"background_color":{"anyOf":[{"type":"string","description":"The custom background, or null"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"The color of the words, or null to follow the background"},{"type":"null"}]},"accent_color":{"anyOf":[{"type":"string","description":"The accent, or null to follow the brand kit"},{"type":"null"}]},"rating_style":{"type":"string","description":"inherit, stars or hearts"},"align":{"type":"string","description":"left or center"},"scale":{"type":"integer","description":"1 or 2"},"show_badge":{"anyOf":[{"type":"boolean","description":"The badge switch, or null to follow the brand kit"},{"type":"null"}]},"testimonial_changed":{"type":"boolean","description":"true when the testimonial's words were edited after this image was made. Render it again with testimonial_images_update"},"rendered_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the PNG was last made"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When the image was created"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_images_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"string","description":"quote_card (the words on a bordered card, the person beneath), big_quote (large words, a small attribution), photo_side (the photo on one side, the words on the other), rating_first (large stars or hearts above the words), highlight (only the highlight, on a solid block of the accent color), plain (words and person, no card) or video_still (the video's poster with a play mark, video testimonials only). Default quote_card","enum":["quote_card","big_quote","photo_side","rating_first","highlight","plain","video_still"]},"text_mode":{"type":"string","description":"Which words: full (everything), highlight (the highlighted passage, or everything when there is none) or excerpt (a run chosen with excerpt_start and excerpt_end, or with neither, the opening sentences that fit). Default full. Words are never set smaller than about 30 pixels, so a long text is refused with text_too_long","enum":["full","highlight","excerpt"]},"excerpt_start":{"type":"integer","description":"With text_mode excerpt, the character position in the testimonial where the run starts, from 0. It is widened to whole words"},"excerpt_end":{"type":"integer","description":"With text_mode excerpt, the character position where the run ends. An ellipsis is added on each side that was cut"},"show_rating":{"type":"boolean","description":"Draw the rating. Default true"},"show_photo":{"type":"boolean","description":"Draw the person's photo, or their initials when there is none. Hidden whatever this says when the giver did not agree to show a photo. Default true"},"show_name":{"type":"boolean","description":"Draw the person's name. Hidden whatever this says when the giver did not agree to show their name. Default true"},"show_company":{"type":"boolean","description":"Draw the person's job title and company. Hidden with the name. Default true"},"show_source":{"type":"boolean","description":"Draw where it came from, such as \"via Trustpilot\". Default false"},"show_verified":{"type":"boolean","description":"Draw the verified mark beside the name of a verified testimonial. Default false"},"show_date":{"type":"boolean","description":"Draw the month and year it was received. Default false"},"show_logo":{"type":"boolean","description":"Draw the site's logo. Default true"},"background":{"type":"string","description":"brand (the brand kit's light colors, the default), light (white with near-black text), dark (the brand kit's dark colors), custom (background_color) or transparent (no background, for placing on a slide)","enum":["brand","light","dark","custom","transparent"]},"background_color":{"type":"string","description":"With background custom: the background as #rrggbb. Empty falls back to the brand kit","examples":["#06755b"]},"text_color":{"type":"string","description":"The color of the words as #rrggbb. Empty follows the background","examples":["#06755b"]},"accent_color":{"type":"string","description":"The accent as #rrggbb: the quotation mark, hearts and the highlight template's block. Empty follows the brand kit","examples":["#06755b"]},"rating_style":{"type":"string","description":"inherit (the brand kit's choice, the default), stars or hearts","enum":["inherit","stars","hearts"]},"align":{"type":"string","description":"left (the default) or center","enum":["left","center"]},"scale":{"type":"integer","description":"1 (the default) or 2, which doubles the pixels for print and large screens","enum":[1,2]},"show_badge":{"type":"boolean","description":"The small \"Collected with Privatus Analytics\" badge. null follows the brand kit. false is refused with plan_limit below Business, where the badge stays"},"size":{"type":"string","description":"Change the image to another size","enum":["square","portrait","story","landscape","linkedin","open_graph","pinterest","wide"]}}}}}}}},"/sites/{site_id}/testimonials/imports/sources/{import_source_id}/runs.json":{"get":{"operationId":"testimonial_import_runs_list","summary":"List the runs of a source, newest first","description":"Each run has its number, what started it, its status, the pages read and how many testimonials it found, how many were new, duplicates, failed and kept, with the times it started and finished.","tags":["Testimonial import runs"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"import_source_id","in":"path","required":true,"description":"Import source id (src_...), from testimonial_import_sources_list","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Run id, e.g. run_7Q2K9XH3AB"},"number":{"type":"integer","description":"The run's number within its source"},"trigger":{"type":"string","description":"first, weekly (any automatic sync, monthly ones too), manual, onboarding or migration"},"status":{"type":"string","description":"running, done, nothing_new, review, paused_allowance or failed"},"pages_read":{"type":"integer","description":"Pages fetched"},"found_count":{"type":"integer","description":"Items read from the pages"},"new_count":{"type":"integer","description":"Items that are not in the site"},"duplicate_count":{"type":"integer","description":"Items that are already here or look like one that is"},"failed_count":{"type":"integer","description":"Rows of a spreadsheet that could not be used"},"kept_count":{"type":"integer","description":"Items kept as testimonials"},"error":{"anyOf":[{"type":"string","description":"Why it failed, in plain words"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"How long it took"},{"type":"null"}]}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_import_runs_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/imports/sources.json":{"post":{"operationId":"testimonial_import_sources_create","summary":"Add an import source from a link and start its first run","description":"The platform is detected from the link. What the run finds waits in the review step (testimonial_import_sources_review) and nothing is stored until testimonial_import_sources_keep. Nothing imported counts toward the monthly testimonials. The Free plan fetches 1 import a month from a review site or a page. Past it the response is 402 plan_limit.","tags":["Testimonial import sources"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Source id, e.g. src_7Q2K9XH3AB"},"platform":{"type":"string","description":"The platform key, any_page for any page, or file for a spreadsheet"},"platform_name":{"anyOf":[{"type":"string","description":"The platform's own name, or null"},{"type":"null"}]},"name":{"type":"string","description":"The label of the source"},"url":{"anyOf":[{"type":"string","description":"The link it reads"},{"type":"null"}]},"sync":{"type":"string","description":"once, monthly or weekly: what was chosen for it"},"effective_sync":{"type":"string","description":"The pace it really runs at: the slower of sync and what the plan allows"},"sync_held":{"anyOf":[{"type":"string","description":"null, slowed (set to weekly, read monthly on this plan) or stopped (the plan has no automatic sync)"},{"type":"null"}]},"state":{"type":"string","description":"reading, review, done, weekly, monthly, paused, paused_allowance or errored"},"auto_approve_high_ratings":{"type":"boolean","description":"New 4 and 5 star reviews arrive approved"},"onboarding":{"type":"boolean","description":"True for the \"find testimonials on my website\" source. Its first run is free"},"kept_count":{"type":"integer","description":"Testimonials this source brought in that are still here"},"waiting_count":{"type":"integer","description":"Found items waiting in the review step"},"consecutive_failures":{"type":"integer","description":"Failed runs in a row. At 3 the source is errored"},"last_error":{"anyOf":[{"type":"string","description":"Why the last run failed, in plain words"},{"type":"null"}]},"last_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last read"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a synced source is read next"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_import_sources_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"The link to the reviews, or to any page with testimonials on it. A private address is refused"},"platform":{"type":"string","description":"A key from testimonial_import_platforms_list, or any_page. Leave it out and it is detected from the link"},"name":{"type":"string","description":"Optional label. Defaults to the platform and the profile's name"},"sync":{"type":"string","description":"once (the default), monthly or weekly. Monthly is on Pro and above, weekly on Business","default":"once"},"auto_approve_high_ratings":{"type":"boolean","description":"Approve new 4 and 5 star reviews automatically. It applies to automatic sync runs","default":false}},"required":["url"]}}}}}},"/sites/{site_id}/testimonials/imports/sources/{id}.json":{"delete":{"operationId":"testimonial_import_sources_delete","summary":"Delete a source. The testimonials it brought in stay","description":"Deletes the source with its run history, what waits in its review step and its uploaded file. Testimonials already kept from it stay in the site. A person does this on the source's page, so the tool runs nothing and returns that page.","tags":["Testimonial import sources"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_import_sources_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Source id, e.g. src_7Q2K9XH3AB"},"platform":{"type":"string","description":"The platform key, any_page for any page, or file for a spreadsheet"},"platform_name":{"anyOf":[{"type":"string","description":"The platform's own name, or null"},{"type":"null"}]},"name":{"type":"string","description":"The label of the source"},"url":{"anyOf":[{"type":"string","description":"The link it reads"},{"type":"null"}]},"sync":{"type":"string","description":"once, monthly or weekly: what was chosen for it"},"effective_sync":{"type":"string","description":"The pace it really runs at: the slower of sync and what the plan allows"},"sync_held":{"anyOf":[{"type":"string","description":"null, slowed (set to weekly, read monthly on this plan) or stopped (the plan has no automatic sync)"},{"type":"null"}]},"state":{"type":"string","description":"reading, review, done, weekly, monthly, paused, paused_allowance or errored"},"auto_approve_high_ratings":{"type":"boolean","description":"New 4 and 5 star reviews arrive approved"},"onboarding":{"type":"boolean","description":"True for the \"find testimonials on my website\" source. Its first run is free"},"kept_count":{"type":"integer","description":"Testimonials this source brought in that are still here"},"waiting_count":{"type":"integer","description":"Found items waiting in the review step"},"consecutive_failures":{"type":"integer","description":"Failed runs in a row. At 3 the source is errored"},"last_error":{"anyOf":[{"type":"string","description":"Why the last run failed, in plain words"},{"type":"null"}]},"last_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last read"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a synced source is read next"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"testimonial_import_sources_get","summary":"Get one import source with its state and counts","description":"Returns the platform, the name, the address read, how often it is read again, the state, how many items wait in the review step, how many were kept, the failures in a row and when it last ran and runs next.","tags":["Testimonial import sources"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_import_sources_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Source id, e.g. src_7Q2K9XH3AB"},"platform":{"type":"string","description":"The platform key, any_page for any page, or file for a spreadsheet"},"platform_name":{"anyOf":[{"type":"string","description":"The platform's own name, or null"},{"type":"null"}]},"name":{"type":"string","description":"The label of the source"},"url":{"anyOf":[{"type":"string","description":"The link it reads"},{"type":"null"}]},"sync":{"type":"string","description":"once, monthly or weekly: what was chosen for it"},"effective_sync":{"type":"string","description":"The pace it really runs at: the slower of sync and what the plan allows"},"sync_held":{"anyOf":[{"type":"string","description":"null, slowed (set to weekly, read monthly on this plan) or stopped (the plan has no automatic sync)"},{"type":"null"}]},"state":{"type":"string","description":"reading, review, done, weekly, monthly, paused, paused_allowance or errored"},"auto_approve_high_ratings":{"type":"boolean","description":"New 4 and 5 star reviews arrive approved"},"onboarding":{"type":"boolean","description":"True for the \"find testimonials on my website\" source. Its first run is free"},"kept_count":{"type":"integer","description":"Testimonials this source brought in that are still here"},"waiting_count":{"type":"integer","description":"Found items waiting in the review step"},"consecutive_failures":{"type":"integer","description":"Failed runs in a row. At 3 the source is errored"},"last_error":{"anyOf":[{"type":"string","description":"Why the last run failed, in plain words"},{"type":"null"}]},"last_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last read"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a synced source is read next"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_import_sources_get","x-permission":"analytics.read"},"patch":{"operationId":"testimonial_import_sources_update","summary":"Change a source's link, name, sync, auto-approve, or pause it","description":"A sync above the plan (any on Free, weekly on Pro) is refused with 402 plan_limit.","tags":["Testimonial import sources"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_import_sources_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Source id, e.g. src_7Q2K9XH3AB"},"platform":{"type":"string","description":"The platform key, any_page for any page, or file for a spreadsheet"},"platform_name":{"anyOf":[{"type":"string","description":"The platform's own name, or null"},{"type":"null"}]},"name":{"type":"string","description":"The label of the source"},"url":{"anyOf":[{"type":"string","description":"The link it reads"},{"type":"null"}]},"sync":{"type":"string","description":"once, monthly or weekly: what was chosen for it"},"effective_sync":{"type":"string","description":"The pace it really runs at: the slower of sync and what the plan allows"},"sync_held":{"anyOf":[{"type":"string","description":"null, slowed (set to weekly, read monthly on this plan) or stopped (the plan has no automatic sync)"},{"type":"null"}]},"state":{"type":"string","description":"reading, review, done, weekly, monthly, paused, paused_allowance or errored"},"auto_approve_high_ratings":{"type":"boolean","description":"New 4 and 5 star reviews arrive approved"},"onboarding":{"type":"boolean","description":"True for the \"find testimonials on my website\" source. Its first run is free"},"kept_count":{"type":"integer","description":"Testimonials this source brought in that are still here"},"waiting_count":{"type":"integer","description":"Found items waiting in the review step"},"consecutive_failures":{"type":"integer","description":"Failed runs in a row. At 3 the source is errored"},"last_error":{"anyOf":[{"type":"string","description":"Why the last run failed, in plain words"},{"type":"null"}]},"last_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last read"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a synced source is read next"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_import_sources_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"A new link for the source"},"name":{"type":"string","description":"A new label"},"sync":{"type":"string","description":"once, monthly or weekly. Monthly is on Pro and above, weekly on Business"},"auto_approve_high_ratings":{"type":"boolean","description":"Approve new 4 and 5 star reviews automatically"},"paused":{"type":"boolean","description":"true pauses a synced source, false resumes it"}}}}}}}},"/sites/{site_id}/testimonials/imports/sources/{id}/discard.json":{"post":{"operationId":"testimonial_import_sources_discard","summary":"Discard found items","description":"Give item_ids (ids from testimonial_import_sources_review) or all true for everything still waiting, never both. A discarded item leaves the review step and what was read about the person is erased. No testimonial is deleted. The server responds with 422 and the code selection or unknown_ids otherwise.","tags":["Testimonial import sources"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_import_sources_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Source id, e.g. src_7Q2K9XH3AB"},"platform":{"type":"string","description":"The platform key, any_page for any page, or file for a spreadsheet"},"platform_name":{"anyOf":[{"type":"string","description":"The platform's own name, or null"},{"type":"null"}]},"name":{"type":"string","description":"The label of the source"},"url":{"anyOf":[{"type":"string","description":"The link it reads"},{"type":"null"}]},"sync":{"type":"string","description":"once, monthly or weekly: what was chosen for it"},"effective_sync":{"type":"string","description":"The pace it really runs at: the slower of sync and what the plan allows"},"sync_held":{"anyOf":[{"type":"string","description":"null, slowed (set to weekly, read monthly on this plan) or stopped (the plan has no automatic sync)"},{"type":"null"}]},"state":{"type":"string","description":"reading, review, done, weekly, monthly, paused, paused_allowance or errored"},"auto_approve_high_ratings":{"type":"boolean","description":"New 4 and 5 star reviews arrive approved"},"onboarding":{"type":"boolean","description":"True for the \"find testimonials on my website\" source. Its first run is free"},"kept_count":{"type":"integer","description":"Testimonials this source brought in that are still here"},"waiting_count":{"type":"integer","description":"Found items waiting in the review step"},"consecutive_failures":{"type":"integer","description":"Failed runs in a row. At 3 the source is errored"},"last_error":{"anyOf":[{"type":"string","description":"Why the last run failed, in plain words"},{"type":"null"}]},"last_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last read"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a synced source is read next"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_import_sources_discard","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"item_ids":{"type":"array","items":{"type":"string"},"description":"Ids from testimonial_import_sources_review","default":[]},"all":{"type":"boolean","description":"true discards everything still waiting","default":false}}}}}}}},"/sites/{site_id}/testimonials/imports/find.json":{"post":{"operationId":"testimonial_import_sources_find","summary":"Find testimonials on the site's own website","description":"Reads the site's domain and the pages it links to that look like they hold testimonials, once per site. It is free: it is not one of the Free plan's fetched imports. What it finds waits in the review step of the source it returns.","tags":["Testimonial import sources"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Source id, e.g. src_7Q2K9XH3AB"},"platform":{"type":"string","description":"The platform key, any_page for any page, or file for a spreadsheet"},"platform_name":{"anyOf":[{"type":"string","description":"The platform's own name, or null"},{"type":"null"}]},"name":{"type":"string","description":"The label of the source"},"url":{"anyOf":[{"type":"string","description":"The link it reads"},{"type":"null"}]},"sync":{"type":"string","description":"once, monthly or weekly: what was chosen for it"},"effective_sync":{"type":"string","description":"The pace it really runs at: the slower of sync and what the plan allows"},"sync_held":{"anyOf":[{"type":"string","description":"null, slowed (set to weekly, read monthly on this plan) or stopped (the plan has no automatic sync)"},{"type":"null"}]},"state":{"type":"string","description":"reading, review, done, weekly, monthly, paused, paused_allowance or errored"},"auto_approve_high_ratings":{"type":"boolean","description":"New 4 and 5 star reviews arrive approved"},"onboarding":{"type":"boolean","description":"True for the \"find testimonials on my website\" source. Its first run is free"},"kept_count":{"type":"integer","description":"Testimonials this source brought in that are still here"},"waiting_count":{"type":"integer","description":"Found items waiting in the review step"},"consecutive_failures":{"type":"integer","description":"Failed runs in a row. At 3 the source is errored"},"last_error":{"anyOf":[{"type":"string","description":"Why the last run failed, in plain words"},{"type":"null"}]},"last_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last read"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a synced source is read next"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_import_sources_find","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials/imports.json":{"get":{"operationId":"testimonial_import_sources_list","summary":"List the import sources of a site","description":"meta carries fetched_imports (used, limit and resets_on for the month, limit null is unlimited) and sync (the pace the plan allows).","tags":["Testimonial import sources"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","description":"Only sources in this state: reading, review, done, weekly, monthly, paused, paused_allowance or errored"}},{"name":"platform","in":"query","required":false,"schema":{"type":"string","description":"Only sources of this platform (a key from testimonial_import_platforms_list, any_page or file)"}},{"name":"sync","in":"query","required":false,"schema":{"type":"string","description":"once, monthly or weekly"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Source id, e.g. src_7Q2K9XH3AB"},"platform":{"type":"string","description":"The platform key, any_page for any page, or file for a spreadsheet"},"platform_name":{"anyOf":[{"type":"string","description":"The platform's own name, or null"},{"type":"null"}]},"name":{"type":"string","description":"The label of the source"},"url":{"anyOf":[{"type":"string","description":"The link it reads"},{"type":"null"}]},"sync":{"type":"string","description":"once, monthly or weekly: what was chosen for it"},"effective_sync":{"type":"string","description":"The pace it really runs at: the slower of sync and what the plan allows"},"sync_held":{"anyOf":[{"type":"string","description":"null, slowed (set to weekly, read monthly on this plan) or stopped (the plan has no automatic sync)"},{"type":"null"}]},"state":{"type":"string","description":"reading, review, done, weekly, monthly, paused, paused_allowance or errored"},"auto_approve_high_ratings":{"type":"boolean","description":"New 4 and 5 star reviews arrive approved"},"onboarding":{"type":"boolean","description":"True for the \"find testimonials on my website\" source. Its first run is free"},"kept_count":{"type":"integer","description":"Testimonials this source brought in that are still here"},"waiting_count":{"type":"integer","description":"Found items waiting in the review step"},"consecutive_failures":{"type":"integer","description":"Failed runs in a row. At 3 the source is errored"},"last_error":{"anyOf":[{"type":"string","description":"Why the last run failed, in plain words"},{"type":"null"}]},"last_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last read"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a synced source is read next"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_import_sources_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/imports/sources/{id}/keep.json":{"post":{"operationId":"testimonial_import_sources_keep","summary":"Keep found items as testimonials","description":"Give item_ids (up to 100) or all. Every kept item is stored through the same route as any other testimonial, so duplicates are never stored twice. Nothing kept counts toward the monthly testimonials. meta says how many were kept.","tags":["Testimonial import sources"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_import_sources_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Source id, e.g. src_7Q2K9XH3AB"},"platform":{"type":"string","description":"The platform key, any_page for any page, or file for a spreadsheet"},"platform_name":{"anyOf":[{"type":"string","description":"The platform's own name, or null"},{"type":"null"}]},"name":{"type":"string","description":"The label of the source"},"url":{"anyOf":[{"type":"string","description":"The link it reads"},{"type":"null"}]},"sync":{"type":"string","description":"once, monthly or weekly: what was chosen for it"},"effective_sync":{"type":"string","description":"The pace it really runs at: the slower of sync and what the plan allows"},"sync_held":{"anyOf":[{"type":"string","description":"null, slowed (set to weekly, read monthly on this plan) or stopped (the plan has no automatic sync)"},{"type":"null"}]},"state":{"type":"string","description":"reading, review, done, weekly, monthly, paused, paused_allowance or errored"},"auto_approve_high_ratings":{"type":"boolean","description":"New 4 and 5 star reviews arrive approved"},"onboarding":{"type":"boolean","description":"True for the \"find testimonials on my website\" source. Its first run is free"},"kept_count":{"type":"integer","description":"Testimonials this source brought in that are still here"},"waiting_count":{"type":"integer","description":"Found items waiting in the review step"},"consecutive_failures":{"type":"integer","description":"Failed runs in a row. At 3 the source is errored"},"last_error":{"anyOf":[{"type":"string","description":"Why the last run failed, in plain words"},{"type":"null"}]},"last_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last read"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a synced source is read next"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_import_sources_keep","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"item_ids":{"type":"array","items":{"type":"string"},"description":"Ids from testimonial_import_sources_review, up to 100 a call","default":[]},"all":{"type":"boolean","description":"true keeps every new item","default":false},"status":{"type":"string","description":"pending or approved, for every item that names no status of its own. Left out, a spreadsheet import follows its own default_status and every other source adds them as pending"},"tags":{"type":"array","items":{"type":"string"},"description":"Tag names to add to everything kept. New names are created","default":[]},"collection_id":{"type":"string","description":"A manual collection (col_...) to add everything kept to"},"include_likely_duplicates":{"type":"boolean","description":"With all, also keep the items that look like one already stored. Each pair goes to Duplicates. Left out, a spreadsheet import follows its own \"Likely duplicates\" option and every other source leaves them out"},"keep_approval":{"type":"boolean","description":"For a migration: what was approved there arrives approved, and everything else pending","default":false}}}}}}}},"/sites/{site_id}/testimonials/imports/platforms.json":{"get":{"operationId":"testimonial_import_platforms_list","summary":"List the platforms an import can read","description":"The tested-source registry. A platform is listed only once its import is proven against a real page. Each entry says which link to paste.","tags":["Testimonial import sources"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The key to send as platform"},"name":{"type":"string","description":"The platform's name"},"link":{"type":"string","description":"Which link to paste"},"example":{"type":"string","description":"What such a link looks like"},"resync":{"type":"boolean","description":"Whether automatic sync is offered for it"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_import_platforms_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/imports/sources/{id}/review.json":{"get":{"operationId":"testimonial_import_sources_review","summary":"List what a source found and has not been decided yet","description":"meta carries the counts by badge (new, already_here, likely_duplicate).","tags":["Testimonial import sources"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_import_sources_list","schema":{"type":"string"}},{"name":"show","in":"query","required":false,"schema":{"type":"string","description":"new, duplicates (already here and likely duplicates) or all (the default)","default":"all"}},{"name":"rating","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Only items with one of these ratings, 1 to 5","default":[]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The item's id, for testimonial_import_sources_keep and testimonial_import_sources_discard"},"match":{"type":"string","description":"new, already_here or likely_duplicate"},"decision":{"type":"string","description":"waiting, kept, discarded or skipped"},"person_name":{"anyOf":[{"type":"string","description":"The name read from the page"},{"type":"null"}]},"person_title":{"anyOf":[{"type":"string"},{"type":"null"}]},"person_company":{"anyOf":[{"type":"string"},{"type":"null"}]},"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"body":{"anyOf":[{"type":"string","description":"The words read from the page"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"received_at":{"anyOf":[{"type":"string","format":"date-time","description":"The date read from the page"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"The review's own link, when the platform has one"},{"type":"null"}]},"row_number":{"anyOf":[{"type":"integer","description":"The row of a spreadsheet"},{"type":"null"}]},"error":{"anyOf":[{"type":"string","description":"Why a row was skipped"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When an undecided item is discarded"},{"type":"null"}]}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_import_sources_review","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/imports/sources/{id}/run.json":{"post":{"operationId":"testimonial_import_sources_run","summary":"Read a source again now","description":"A run by hand is a fetched import and counts as one of the month's on the Free plan (402 plan_limit past it). Refused while a run is active (422 in_progress) and after 3 runs of the source in 24 hours on any plan (422 too_many_runs). On an errored source it clears the count of failures.","tags":["Testimonial import sources"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_import_sources_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Source id, e.g. src_7Q2K9XH3AB"},"platform":{"type":"string","description":"The platform key, any_page for any page, or file for a spreadsheet"},"platform_name":{"anyOf":[{"type":"string","description":"The platform's own name, or null"},{"type":"null"}]},"name":{"type":"string","description":"The label of the source"},"url":{"anyOf":[{"type":"string","description":"The link it reads"},{"type":"null"}]},"sync":{"type":"string","description":"once, monthly or weekly: what was chosen for it"},"effective_sync":{"type":"string","description":"The pace it really runs at: the slower of sync and what the plan allows"},"sync_held":{"anyOf":[{"type":"string","description":"null, slowed (set to weekly, read monthly on this plan) or stopped (the plan has no automatic sync)"},{"type":"null"}]},"state":{"type":"string","description":"reading, review, done, weekly, monthly, paused, paused_allowance or errored"},"auto_approve_high_ratings":{"type":"boolean","description":"New 4 and 5 star reviews arrive approved"},"onboarding":{"type":"boolean","description":"True for the \"find testimonials on my website\" source. Its first run is free"},"kept_count":{"type":"integer","description":"Testimonials this source brought in that are still here"},"waiting_count":{"type":"integer","description":"Found items waiting in the review step"},"consecutive_failures":{"type":"integer","description":"Failed runs in a row. At 3 the source is errored"},"last_error":{"anyOf":[{"type":"string","description":"Why the last run failed, in plain words"},{"type":"null"}]},"last_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last read"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a synced source is read next"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_import_sources_run","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials/settings/languages.json":{"get":{"operationId":"testimonial_languages_get","summary":"Get the language settings of a site's testimonials","description":"The default language, the languages offered, whether newly approved testimonials are translated automatically, whether the plan includes translation, whether translation is set up, and the month's characters used and left.","tags":["Testimonial languages"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string","description":"The site (pa_...)"},"default_language":{"type":"string","description":"The fallback language"},"languages":{"type":"array","items":{"type":"string"},"description":"The languages the site is offered in, the default included"},"auto_translate":{"type":"boolean","description":"Newly approved testimonials are translated automatically"},"translation_on_plan":{"type":"boolean","description":"The plan includes translation of testimonials"},"translation_available":{"type":"boolean","description":"Translation is set up at Privatus Analytics. While false nothing can be translated, on any plan"},"characters_used":{"type":"integer","description":"Characters sent for translation this month"},"characters_limit":{"type":"integer","description":"The month's character quota"},"characters_left":{"type":"integer","description":"Characters left this month"},"resets_on":{"type":"string","format":"date","description":"The date the quota starts again"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_languages_get","x-permission":"analytics.read"},"patch":{"operationId":"testimonial_languages_update","summary":"Set the default language, the offered languages and automatic translation","description":"Send only what changes. The default is always among the offered languages, and a language a form is written in cannot be removed (in_use). Switching auto_translate on needs Business or above (402 plan_limit elsewhere): from then on the words of each newly approved testimonial are sent to Google Cloud Translation, and the member is emailed that an assistant changed this.","tags":["Testimonial languages"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string","description":"The site (pa_...)"},"default_language":{"type":"string","description":"The fallback language"},"languages":{"type":"array","items":{"type":"string"},"description":"The languages the site is offered in, the default included"},"auto_translate":{"type":"boolean","description":"Newly approved testimonials are translated automatically"},"translation_on_plan":{"type":"boolean","description":"The plan includes translation of testimonials"},"translation_available":{"type":"boolean","description":"Translation is set up at Privatus Analytics. While false nothing can be translated, on any plan"},"characters_used":{"type":"integer","description":"Characters sent for translation this month"},"characters_limit":{"type":"integer","description":"The month's character quota"},"characters_left":{"type":"integer","description":"Characters left this month"},"resets_on":{"type":"string","format":"date","description":"The date the quota starts again"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_languages_update","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"default_language":{"type":"string","description":"The fallback language, one of the interface languages (en, de, fr and so on)","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]},"languages":{"type":"array","items":{"type":"string","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]},"description":"The languages the site's forms, widgets and walls are offered in. The default is always included"},"auto_translate":{"type":"boolean","description":"Translate each newly approved testimonial into the offered languages, inside the month's quota. Business and up"}}}}}}}},"/sites/{site_id}/testimonials/media/uploads.json":{"post":{"operationId":"testimonial_media_uploads_create","summary":"Start an upload, or add a file from a web address","description":"Two ways. To upload, send filename, content_type and byte_size: the response carries upload, with the url to PUT the file to, the headers to send with it and, for a large file, parts that can be sent one by one. Then call testimonial_media_uploads_finish. Or send source_url and the file is downloaded and processed for you: poll testimonial_media_get until its state is ready. Limits: video and audio up to 500 MB and as long as the plan takes (2 minutes on Pro, 10 minutes on Business, none on Free, where the server responds with 402 plan_limit), images up to 10 MB, a logo up to 2 MB.","tags":["Testimonial media"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_media_uploads_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"What the file is for: recording (a video or audio testimonial, the default for those), attachment (an image kept with a testimonial, the default for images), avatar (a person's photo), logo (the site's logo) or share_image (a wall's share image)"},"filename":{"type":"string","description":"The name of the file, e.g. hello.mp4. Needed for an upload"},"content_type":{"type":"string","description":"The media type of the file, e.g. video/mp4. Needed for an upload"},"byte_size":{"type":"integer","description":"The exact size of the file in bytes. Needed for an upload, and the upload store refuses any other size"},"source_url":{"type":"string","description":"A public http or https address to download the file from, in place of an upload"}},"required":["kind"]}}}}}},"/sites/{site_id}/testimonials/media/{id}.json":{"delete":{"operationId":"testimonial_media_delete","summary":"Delete a file that no testimonial keeps","description":"A file that belongs to a testimonial is deleted with the testimonial, through the trash. The stored files are deleted and their addresses are cleared from the cache.","tags":["Testimonial media"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by the tools that list or create it","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"testimonial_media_get","summary":"Get one file with its state and where to load it","description":"The url is the lasting address of the finished file on the media host, and it is null until the state is ready. The address is the same for everyone and is not signed, so only pass on the address of a file whose shareable field is true.","tags":["Testimonial media"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by the tools that list or create it","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_media_get","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/media/uploads/{id}/finish.json":{"post":{"operationId":"testimonial_media_uploads_finish","summary":"Say an upload is complete, so the file is checked and processed","description":"Call it once the file has been sent. The file must be in the upload store and be exactly the size that was promised. Calling it twice is safe.","tags":["Testimonial media"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by the tools that list or create it","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_media_uploads_finish","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials/media/{id}/retry.json":{"post":{"operationId":"testimonial_media_retry","summary":"Try a failed file again","description":"Processes the file again from the upload that was kept. The upload is kept for 24 hours after a failure. After that the server responds with not_retryable and the file has to be uploaded again.","tags":["Testimonial media"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by the tools that list or create it","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_media_retry","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials/mentions.json":{"get":{"operationId":"testimonial_mentions_list","summary":"List the words and phrases that recur across a site's testimonials","description":"Each term comes with how many testimonials contain it, its share, the average rating of those, and the last 90 days against the 90 before. Sort by rating_asc to read what people complain about, or by rising for what is new. meta.refreshed_at says when the terms were last rebuilt. Pass a term to testimonials_list as mention to read the testimonials.","tags":["Testimonial mentions"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Narrow the list to terms that contain this text"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Which testimonials to count: all (the default), approved, pending or rejected","enum":["all","approved","pending","rejected"],"default":"all"}},{"name":"type","in":"query","required":false,"schema":{"type":"string","description":"all (the default), words or phrases","enum":["all","words","phrases"],"default":"all"}},{"name":"min_count","in":"query","required":false,"schema":{"type":"integer","description":"Leave out terms in fewer testimonials than this. The default is 3, which is also the least a term needs to be kept","default":3}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"count (the default, most mentioned first), rising (more in the last 90 days than in the 90 before) or rating_asc (lowest average rating first)","enum":["count","rising","rating_asc"],"default":"count"}},{"name":"hidden","in":"query","required":false,"schema":{"type":"boolean","description":"true lists the hidden terms instead","default":false}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"term":{"type":"string","description":"The term in lowercase. Pass it to testimonials_list as mention"},"label":{"type":"string","description":"The term in its most common written form"},"type":{"type":"string","description":"word or phrase"},"count":{"type":"integer","description":"How many testimonials contain it, for the status that was asked for"},"share":{"anyOf":[{"type":"number","description":"count as a percentage of the testimonials on the site"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"How many testimonials contain it, whatever their status"},"approved_count":{"type":"integer","description":"How many of those are approved"},"pending_count":{"type":"integer","description":"How many of those are pending"},"rejected_count":{"type":"integer","description":"How many of those are rejected"},"average_rating":{"anyOf":[{"type":"number","description":"The mean rating of the rated testimonials that contain it, whatever their status. Null when none is rated"},{"type":"null"}]},"recent_count":{"type":"integer","description":"How many were received in the last 90 days"},"previous_count":{"type":"integer","description":"How many were received in the 90 days before that"},"hidden":{"type":"boolean","description":"true when a member hid the term"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_mentions_list","x-permission":"analytics.read"},"patch":{"operationId":"testimonial_mentions_update","summary":"Hide a term that is only noise, or show it again","description":"A hidden term leaves the Mentions list and the inbox's Mentions facet, and stays hidden when the terms are rebuilt.","tags":["Testimonial mentions"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"term":{"type":"string","description":"The term in lowercase. Pass it to testimonials_list as mention"},"label":{"type":"string","description":"The term in its most common written form"},"type":{"type":"string","description":"word or phrase"},"count":{"type":"integer","description":"How many testimonials contain it, for the status that was asked for"},"share":{"anyOf":[{"type":"number","description":"count as a percentage of the testimonials on the site"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"How many testimonials contain it, whatever their status"},"approved_count":{"type":"integer","description":"How many of those are approved"},"pending_count":{"type":"integer","description":"How many of those are pending"},"rejected_count":{"type":"integer","description":"How many of those are rejected"},"average_rating":{"anyOf":[{"type":"number","description":"The mean rating of the rated testimonials that contain it, whatever their status. Null when none is rated"},{"type":"null"}]},"recent_count":{"type":"integer","description":"How many were received in the last 90 days"},"previous_count":{"type":"integer","description":"How many were received in the 90 days before that"},"hidden":{"type":"boolean","description":"true when a member hid the term"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_mentions_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"term":{"type":"string","description":"The term, as testimonial_mentions_list returns it"},"hidden":{"type":"boolean","description":"true hides it. false shows it again"}},"required":["term","hidden"]}}}}}},"/sites/{site_id}/testimonials/mentions/tag.json":{"post":{"operationId":"testimonial_mentions_tag","summary":"Tag every testimonial that mentions a word or phrase","description":"One bulk action on the whole result, with undo. The term is any word or two-word phrase, matched with stemming the way Mentions are counted. A tag named for the first time is created. Responds with an undo id that testimonials_bulk_undo takes for 7 days. More than 100 run in the background.","tags":["Testimonial mentions"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"anyOf":[{"type":"string","description":"The undo record id (blk_...). Null for a dry run and for delete_permanently"},{"type":"null"}]},"action":{"type":"string","description":"The action that ran"},"state":{"type":"string","description":"done, running (in the background), dry_run, undone, failed or expired"},"total":{"type":"integer","description":"How many testimonials the selection held"},"changed":{"type":"integer","description":"How many were changed"},"skipped":{"type":"integer","description":"How many were left as they were"},"skipped_reasons":{"type":"object","description":"Why, with a count each: already_in_state, waiting_for_allowance, in_trash, not_in_trash"},"undoable":{"type":"boolean","description":"It can be undone now"},"undo_until":{"anyOf":[{"type":"string","format":"date-time","description":"Until when it can be undone"},{"type":"null"}]},"reverted":{"anyOf":[{"type":"integer","description":"After an undo, how many went back"},{"type":"null"}]},"left":{"anyOf":[{"type":"object","description":"After an undo, how many were left alone and why: changed_since, deleted"},{"type":"null"}]},"created_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the run began"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_mentions_tag","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"term":{"type":"string","description":"A word or a two-word phrase, e.g. onboarding"},"tags":{"type":"array","items":{"type":"string"},"description":"Tag ids (tag_...) or names. A new name creates the tag"},"confirm_count":{"type":"integer","description":"Optional. The number of testimonials you expect to tag. If it has changed, nothing runs and the error count_changed says the new number"},"dry_run":{"type":"boolean","description":"true responds with what would change and changes nothing","default":false}},"required":["term","tags"]}}}}}},"/sites/{site_id}/testimonials/imports/migrations/{id}/discard.json":{"post":{"operationId":"testimonial_migrations_discard","summary":"Discard what a migration read","description":"Give item_ids (ids from testimonial_migrations_review) or all true for everything still waiting, never both. A discarded item leaves the review step and what was read about the person is erased. No testimonial is deleted. The server responds with 422 and the code selection or unknown_ids otherwise.","tags":["Testimonial migrations"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_migrations_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Migration id, e.g. mig_7Q2K9XH3AB"},"tool":{"type":"string","description":"senja or testimonial_to"},"status":{"type":"string","description":"reading, review, importing, done or failed"},"found_count":{"type":"integer","description":"Testimonials read from the other tool"},"kept_count":{"type":"integer","description":"Testimonials kept"},"duplicate_count":{"type":"integer","description":"Already here"},"failed_count":{"type":"integer","description":"Could not be stored"},"media_total":{"type":"integer","description":"Videos and audio being copied into the media store"},"media_copied":{"type":"integer","description":"How many of them are copied"},"waiting_count":{"type":"integer","description":"Still waiting in the review step"},"key_wiped":{"type":"boolean","description":"True once the pasted key is gone"},"error":{"anyOf":[{"type":"string","description":"Why it failed, in plain words"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_migrations_discard","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"item_ids":{"type":"array","items":{"type":"string"},"description":"Ids from testimonial_import_sources_review","default":[]},"all":{"type":"boolean","description":"true discards everything still waiting","default":false}}}}}}}},"/sites/{site_id}/testimonials/imports/migrations.json":{"get":{"operationId":"testimonial_migrations_list","summary":"List the migrations of a site","description":"Newest first. A migration is one export file from another testimonial tool. Each has the tool it came from, its status and how many testimonials were found, kept, duplicates and failed.","tags":["Testimonial migrations"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Migration id, e.g. mig_7Q2K9XH3AB"},"tool":{"type":"string","description":"senja or testimonial_to"},"status":{"type":"string","description":"reading, review, importing, done or failed"},"found_count":{"type":"integer","description":"Testimonials read from the other tool"},"kept_count":{"type":"integer","description":"Testimonials kept"},"duplicate_count":{"type":"integer","description":"Already here"},"failed_count":{"type":"integer","description":"Could not be stored"},"media_total":{"type":"integer","description":"Videos and audio being copied into the media store"},"media_copied":{"type":"integer","description":"How many of them are copied"},"waiting_count":{"type":"integer","description":"Still waiting in the review step"},"key_wiped":{"type":"boolean","description":"True once the pasted key is gone"},"error":{"anyOf":[{"type":"string","description":"Why it failed, in plain words"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_migrations_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/imports/migrations/{id}/keep.json":{"post":{"operationId":"testimonial_migrations_keep","summary":"Keep what a migration read as testimonials","description":"Give item_ids (up to 100 a call, from testimonial_migrations_review) or all true, never both. Each kept item becomes a testimonial with status pending or approved, and keep_approval true keeps the approval it had in the other tool. With all, likely duplicates are left out unless include_likely_duplicates is true. Nothing kept counts toward the monthly testimonials. What is not kept stays in the review step for 30 days.","tags":["Testimonial migrations"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_migrations_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Migration id, e.g. mig_7Q2K9XH3AB"},"tool":{"type":"string","description":"senja or testimonial_to"},"status":{"type":"string","description":"reading, review, importing, done or failed"},"found_count":{"type":"integer","description":"Testimonials read from the other tool"},"kept_count":{"type":"integer","description":"Testimonials kept"},"duplicate_count":{"type":"integer","description":"Already here"},"failed_count":{"type":"integer","description":"Could not be stored"},"media_total":{"type":"integer","description":"Videos and audio being copied into the media store"},"media_copied":{"type":"integer","description":"How many of them are copied"},"waiting_count":{"type":"integer","description":"Still waiting in the review step"},"key_wiped":{"type":"boolean","description":"True once the pasted key is gone"},"error":{"anyOf":[{"type":"string","description":"Why it failed, in plain words"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_migrations_keep","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"item_ids":{"type":"array","items":{"type":"string"},"description":"Ids from testimonial_import_sources_review, up to 100 a call","default":[]},"all":{"type":"boolean","description":"true keeps every new item","default":false},"status":{"type":"string","description":"pending or approved, for every item that names no status of its own. Left out, a spreadsheet import follows its own default_status and every other source adds them as pending"},"tags":{"type":"array","items":{"type":"string"},"description":"Tag names to add to everything kept. New names are created","default":[]},"collection_id":{"type":"string","description":"A manual collection (col_...) to add everything kept to"},"include_likely_duplicates":{"type":"boolean","description":"With all, also keep the items that look like one already stored. Each pair goes to Duplicates. Left out, a spreadsheet import follows its own \"Likely duplicates\" option and every other source leaves them out"},"keep_approval":{"type":"boolean","description":"For a migration: what was approved there arrives approved, and everything else pending","default":false}}}}}}}},"/sites/{site_id}/testimonials/imports/migrations/{id}/review.json":{"get":{"operationId":"testimonial_migrations_review","summary":"List what a migration read and has not been decided yet","description":"Lists the items still waiting for a decision, newest run first. show is new, duplicates or all (the default), and rating keeps only the star ratings listed. Pass the item ids to testimonial_migrations_keep or testimonial_migrations_discard.","tags":["Testimonial migrations"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_migrations_list","schema":{"type":"string"}},{"name":"show","in":"query","required":false,"schema":{"type":"string","description":"new, duplicates (already here and likely duplicates) or all (the default)","default":"all"}},{"name":"rating","in":"query","required":false,"schema":{"type":"array","items":{"type":"integer"},"description":"Only items with one of these ratings, 1 to 5","default":[]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The item's id, for testimonial_import_sources_keep and testimonial_import_sources_discard"},"match":{"type":"string","description":"new, already_here or likely_duplicate"},"decision":{"type":"string","description":"waiting, kept, discarded or skipped"},"person_name":{"anyOf":[{"type":"string","description":"The name read from the page"},{"type":"null"}]},"person_title":{"anyOf":[{"type":"string"},{"type":"null"}]},"person_company":{"anyOf":[{"type":"string"},{"type":"null"}]},"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"body":{"anyOf":[{"type":"string","description":"The words read from the page"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"received_at":{"anyOf":[{"type":"string","format":"date-time","description":"The date read from the page"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"The review's own link, when the platform has one"},{"type":"null"}]},"row_number":{"anyOf":[{"type":"integer","description":"The row of a spreadsheet"},{"type":"null"}]},"error":{"anyOf":[{"type":"string","description":"Why a row was skipped"},{"type":"null"}]},"expires_at":{"anyOf":[{"type":"string","format":"date-time","description":"When an undecided item is discarded"},{"type":"null"}]}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_migrations_review","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/imports/migrations/{id}.json":{"get":{"operationId":"testimonial_migrations_get","summary":"Get a migration's progress and counts","description":"Returns the tool the file came from, the status, how many testimonials were found, kept, duplicates and failed, how many media files it brings and when it started and finished. Poll it while the status says the file is still being read.","tags":["Testimonial migrations"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_migrations_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Migration id, e.g. mig_7Q2K9XH3AB"},"tool":{"type":"string","description":"senja or testimonial_to"},"status":{"type":"string","description":"reading, review, importing, done or failed"},"found_count":{"type":"integer","description":"Testimonials read from the other tool"},"kept_count":{"type":"integer","description":"Testimonials kept"},"duplicate_count":{"type":"integer","description":"Already here"},"failed_count":{"type":"integer","description":"Could not be stored"},"media_total":{"type":"integer","description":"Videos and audio being copied into the media store"},"media_copied":{"type":"integer","description":"How many of them are copied"},"waiting_count":{"type":"integer","description":"Still waiting in the review step"},"key_wiped":{"type":"boolean","description":"True once the pasted key is gone"},"error":{"anyOf":[{"type":"string","description":"Why it failed, in plain words"},{"type":"null"}]},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_migrations_get","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/people/{id}/ask_again.json":{"post":{"operationId":"testimonial_people_ask_again","summary":"Start a request with this person as its only recipient","description":"It uses the form they last used, or the starter form. Nothing is sent until the request is sent. It the server responds with 422 and the code no_email, bounced or unsubscribed when the person cannot be asked, and requests_unavailable while requests are not available.","tags":["Testimonial people"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_people_list","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Request id, e.g. req_7Q2K9XH3AB"},"name":{"type":"string","description":"The request's name"},"status":{"type":"string","description":"draft until it is sent"},"form_id":{"anyOf":[{"type":"string","description":"The form it asks with"},{"type":"null"}]},"recipients_count":{"type":"integer","description":"How many people it will ask"},"created_at":{"type":"string","format":"date-time","description":"When it was started"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_people_ask_again","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"form_id":{"type":"string","description":"The form (frm_...) to ask with. Left out, it is the form they last used, or the starter form"}}}}}}}},"/sites/{site_id}/testimonials/people.json":{"post":{"operationId":"testimonial_people_create","summary":"Add a person to a site","description":"name is required (up to 120 characters). email is never shown publicly: it groups later testimonials under this person and lets the site ask them again, and an address another person of the site already has is refused. avatar_media_id is the id (med_...) of an image already uploaded to the site. Adding a person adds no testimonial.","tags":["Testimonial people"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]},"company_id":{"anyOf":[{"type":"string","description":"The id of their company for the companies operations"},{"type":"null"}]},"approved_count":{"type":"integer","description":"How many of their testimonials are approved"},"average_rating":{"anyOf":[{"type":"number","description":"The average rating of their testimonials, or null"},{"type":"null"}]},"last_asked_at":{"anyOf":[{"type":"string","format":"date-time","description":"When this site last asked them"},{"type":"null"}]},"last_ask_outcome":{"anyOf":[{"type":"string","description":"How the last ask ended: scheduled, sent, opened, submitted, bounced, unsubscribed, stopped or skipped"},{"type":"null"}]},"possible_duplicate":{"type":"boolean","description":"Another person of the site has the same name and company"},"created_at":{"type":"string","format":"date-time","description":"When the person was first stored"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_people_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"The person's name, up to 120 characters"},"title":{"type":"string","description":"Their job title"},"company":{"type":"string","description":"Where they work"},"company_url":{"type":"string","description":"The company's website (http or https). It groups people into companies"},"social_url":{"type":"string","description":"A link to their profile (http or https)"},"email":{"type":"string","description":"Their email address. Never shown publicly. One person per address on a site"},"avatar_media_id":{"type":"string","description":"The id (med_...) of an image already uploaded to this site, as their photo"}}}}}}},"get":{"operationId":"testimonial_people_list","summary":"List the people of a site, filtered and sorted","description":"Each person comes with their count of testimonials, how many are approved, their average rating and the last ask with its outcome. The email is null unless the caller holds content.write, and has_email still says whether one is on record.","tags":["Testimonial people"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Part of a name or a company. For a caller with content.write, also part of an email address"}},{"name":"company","in":"query","required":false,"schema":{"type":"string","description":"A company name or website host. Only its people are listed"}},{"name":"has_email","in":"query","required":false,"schema":{"type":"string","description":"yes for people with an email address on record, no for those without","enum":["yes","no"]}},{"name":"testimonials","in":"query","required":false,"schema":{"type":"string","description":"one for people with exactly one testimonial, several for two or more","enum":["one","several"]}},{"name":"asked","in":"query","required":false,"schema":{"type":"string","description":"never for people who were never asked, waiting for those asked with no response yet, answered for those who answered an ask","enum":["never","waiting","answered"]}},{"name":"newest","in":"query","required":false,"schema":{"type":"string","description":"fresh when their newest testimonial is under two years old, old when it is over two years old","enum":["fresh","old"]}},{"name":"duplicate","in":"query","required":false,"schema":{"type":"string","description":"yes for people who look like another person (the same name and company)","enum":["yes"]}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"name (the default), testimonials_desc, received_desc or asked_desc","enum":["name","testimonials_desc","received_desc","asked_desc"],"default":"name"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]},"company_id":{"anyOf":[{"type":"string","description":"The id of their company for the companies operations"},{"type":"null"}]},"approved_count":{"type":"integer","description":"How many of their testimonials are approved"},"average_rating":{"anyOf":[{"type":"number","description":"The average rating of their testimonials, or null"},{"type":"null"}]},"last_asked_at":{"anyOf":[{"type":"string","format":"date-time","description":"When this site last asked them"},{"type":"null"}]},"last_ask_outcome":{"anyOf":[{"type":"string","description":"How the last ask ended: scheduled, sent, opened, submitted, bounced, unsubscribed, stopped or skipped"},{"type":"null"}]},"possible_duplicate":{"type":"boolean","description":"Another person of the site has the same name and company"},"created_at":{"type":"string","format":"date-time","description":"When the person was first stored"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_people_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/people/{id}/permanent.json":{"delete":{"operationId":"testimonial_people_delete_permanently","summary":"Delete a person for good, with everything they said, the files and the ask history","description":"For an erasure request. This cannot be undone. It needs confirm, the person's name or id, and leaves one audit entry that holds neither the name nor the words.","tags":["Testimonial people"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_people_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The id of what was deleted"},"deleted":{"type":"boolean","description":"Always true"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"string","description":"The person's name, or their id, typed to confirm"}}}}}}}},"/sites/{site_id}/testimonials/people/{id}/merge.json":{"post":{"operationId":"testimonial_people_merge","summary":"Merge other records of the same person into this one","description":"The person in the path stays. Everything the others said and every ask sent to them moves over, and the others are removed. A field this person has blank is filled from the others, oldest first, and use names whose value wins for a field. The response carries meta.undo_id, which testimonial_undo_records_undo takes for 7 days.","tags":["Testimonial people"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_people_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]},"company_id":{"anyOf":[{"type":"string","description":"The id of their company for the companies operations"},{"type":"null"}]},"approved_count":{"type":"integer","description":"How many of their testimonials are approved"},"average_rating":{"anyOf":[{"type":"number","description":"The average rating of their testimonials, or null"},{"type":"null"}]},"last_asked_at":{"anyOf":[{"type":"string","format":"date-time","description":"When this site last asked them"},{"type":"null"}]},"last_ask_outcome":{"anyOf":[{"type":"string","description":"How the last ask ended: scheduled, sent, opened, submitted, bounced, unsubscribed, stopped or skipped"},{"type":"null"}]},"possible_duplicate":{"type":"boolean","description":"Another person of the site has the same name and company"},"created_at":{"type":"string","format":"date-time","description":"When the person was first stored"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_people_merge","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"duplicate_ids":{"type":"array","items":{"type":"string"},"description":"The ids (per_...) of 1 to 20 other records of the same person. They are removed"},"use":{"type":"object","additionalProperties":true,"description":"For a field, the id of the person whose value wins, for example {\"email\": \"per_...\"}. Fields: name, title, company, company_url, photo, email, social_url","default":{}}},"required":["duplicate_ids"]}}}}}},"/sites/{site_id}/testimonials/people/{id}.json":{"get":{"operationId":"testimonial_people_get","summary":"Get one person with what was asked of them and the people who look like the same person","description":"Their testimonials are testimonials_list with person_id. can_ask and cannot_ask_reason say whether testimonial_people_ask_again would go through.","tags":["Testimonial people"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_people_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]},"company_id":{"anyOf":[{"type":"string","description":"The id of their company for the companies operations"},{"type":"null"}]},"approved_count":{"type":"integer","description":"How many of their testimonials are approved"},"average_rating":{"anyOf":[{"type":"number","description":"The average rating of their testimonials, or null"},{"type":"null"}]},"last_asked_at":{"anyOf":[{"type":"string","format":"date-time","description":"When this site last asked them"},{"type":"null"}]},"last_ask_outcome":{"anyOf":[{"type":"string","description":"How the last ask ended: scheduled, sent, opened, submitted, bounced, unsubscribed, stopped or skipped"},{"type":"null"}]},"possible_duplicate":{"type":"boolean","description":"Another person of the site has the same name and company"},"created_at":{"type":"string","format":"date-time","description":"When the person was first stored"},"asks":{"type":"array","items":{"type":"object"},"description":"Each ask sent to them, newest first: request_id, request_name, form_id, outcome and asked_at"},"twins":{"type":"array","items":{"type":"object"},"description":"People who look like the same person: id, name, testimonials_count and reason"},"can_ask":{"type":"boolean","description":"Whether testimonial_people_ask_again would go through"},"cannot_ask_reason":{"anyOf":[{"type":"string","description":"no_email, bounced, unsubscribed or requests_unavailable"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_people_get","x-permission":"analytics.read"},"patch":{"operationId":"testimonial_people_update","summary":"Edit a person. Only the fields sent change","description":"An empty value clears a field, except the name. An email another person of the site already has is refused. The company page a person is listed on follows the company name and website.","tags":["Testimonial people"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_people_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]},"company_id":{"anyOf":[{"type":"string","description":"The id of their company for the companies operations"},{"type":"null"}]},"approved_count":{"type":"integer","description":"How many of their testimonials are approved"},"average_rating":{"anyOf":[{"type":"number","description":"The average rating of their testimonials, or null"},{"type":"null"}]},"last_asked_at":{"anyOf":[{"type":"string","format":"date-time","description":"When this site last asked them"},{"type":"null"}]},"last_ask_outcome":{"anyOf":[{"type":"string","description":"How the last ask ended: scheduled, sent, opened, submitted, bounced, unsubscribed, stopped or skipped"},{"type":"null"}]},"possible_duplicate":{"type":"boolean","description":"Another person of the site has the same name and company"},"created_at":{"type":"string","format":"date-time","description":"When the person was first stored"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_people_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"The person's name, up to 120 characters"},"title":{"type":"string","description":"Their job title. Empty clears it"},"company":{"type":"string","description":"Where they work. Empty clears it"},"company_url":{"type":"string","description":"The company's website (http or https). Empty clears it"},"social_url":{"type":"string","description":"A link to their profile (http or https). Empty clears it"},"email":{"type":"string","description":"Their email address. Never shown publicly. Empty clears it"},"avatar_media_id":{"type":"string","description":"The id (med_...) of an image already uploaded to this site. Empty removes the photo"}}}}}}}},"/sites/{site_id}/testimonials/settings/purchase_connections/{id}.json":{"delete":{"operationId":"testimonial_purchase_connections_delete","summary":"Disconnect a payment account","description":"Deletes the connection and its key. Buyers still waiting for their first email are not asked. The standing request stays as the record of what was sent.","tags":["Testimonial purchase connections"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_purchase_connections_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Connection id, e.g. pc_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"provider":{"type":"string","description":"stripe or paddle"},"name":{"type":"string","description":"Name of the connection and its request"},"status":{"type":"string","description":"active or errored"},"error":{"anyOf":[{"type":"string","description":"What is wrong, when the connection is errored"},{"type":"null"}]},"paused":{"type":"boolean","description":"true when the workspace's plan does not include requests after a purchase (Business and up). The connection is kept, reads no payments and asks nobody"},"all_products":{"type":"boolean","description":"Whether the buyers of every product are asked"},"product_ids":{"type":"array","items":{"type":"string"},"description":"The products whose buyers are asked"},"delay_days":{"type":"integer","description":"Days after the payment before the first email"},"form_id":{"anyOf":[{"type":"string","description":"The form the email leads to"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The standing request buyers are added to"},{"type":"null"}]},"connected_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was connected. Earlier payments never count"},{"type":"null"}]},"last_checked_at":{"anyOf":[{"type":"string","format":"date-time","description":"When payments were last read"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials/settings/purchase_connections.json":{"get":{"operationId":"testimonial_purchase_connections_list","summary":"List the purchase connections of a site","description":"Each with its rule, its state and its standing request. The key is never returned. paused is true on a plan without requests after a purchase: the connection is kept, reads no payments and asks nobody.","tags":["Testimonial purchase connections"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Connection id, e.g. pc_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"provider":{"type":"string","description":"stripe or paddle"},"name":{"type":"string","description":"Name of the connection and its request"},"status":{"type":"string","description":"active or errored"},"error":{"anyOf":[{"type":"string","description":"What is wrong, when the connection is errored"},{"type":"null"}]},"paused":{"type":"boolean","description":"true when the workspace's plan does not include requests after a purchase (Business and up). The connection is kept, reads no payments and asks nobody"},"all_products":{"type":"boolean","description":"Whether the buyers of every product are asked"},"product_ids":{"type":"array","items":{"type":"string"},"description":"The products whose buyers are asked"},"delay_days":{"type":"integer","description":"Days after the payment before the first email"},"form_id":{"anyOf":[{"type":"string","description":"The form the email leads to"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The standing request buyers are added to"},{"type":"null"}]},"connected_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was connected. Earlier payments never count"},{"type":"null"}]},"last_checked_at":{"anyOf":[{"type":"string","format":"date-time","description":"When payments were last read"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_purchase_connections_list","x-permission":"sites.manage"}},"/sites/{site_id}/testimonials/requests/{request_id}/recipients.json":{"post":{"operationId":"testimonial_request_recipients_create","summary":"Add people to a request","description":"Up to 500 in one call. Added to a draft they wait for testimonial_requests_send. Added to a running request they get their first email at once. The response says how many were queued and how many skipped, by reason. Adding to a running request emails people outside the workspace, so the member is told by email.","tags":["Testimonial request recipients"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"request_id","in":"path","required":true,"description":"Testimonial request id (req_...), from testimonial_requests_list","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"added":{"type":"integer","description":"How many people are now queued"},"skipped":{"type":"object","description":"How many were skipped, by reason: invalid_email, duplicate, already_gave, already_being_asked, asked_recently, opted_out"},"skipped_total":{"type":"integer","description":"How many were skipped in all"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_request_recipients_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"recipients":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"A list of up to 500 people, each { email, name, company, title, properties }. Only email is required"}},"required":["recipients"]}}}}},"delete":{"operationId":"testimonial_request_recipients_delete","summary":"Remove chosen people from a request","description":"Only people nothing was sent to (queued or skipped). Takes up to 100 addresses in the body. Over MCP the tool changes nothing and responds with the page of the app where a person does it.","tags":["Testimonial request recipients"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"request_id","in":"path","required":true,"description":"Testimonial request id (req_...), from testimonial_requests_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"email":{"anyOf":[{"type":"string","description":"The address. null unless the caller may edit content"},{"type":"null"}]},"name":{"anyOf":[{"type":"string","description":"Name, when known"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Company, when known"},{"type":"null"}]},"status":{"type":"string","description":"One of queued, sent, opened, clicked, submitted, bounced, unsubscribed, skipped"},"skip_reason":{"anyOf":[{"type":"string","description":"Why a skipped person is not asked: invalid_email, already_gave, already_being_asked, asked_recently, opted_out or refunded"},{"type":"null"}]},"stopped":{"type":"boolean","description":"true when a member stopped this person. They keep their status"},"emails_sent":{"type":"integer","description":"How many emails they were sent"},"last_event_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last thing happened"},{"type":"null"}]},"next_email_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their next email goes out"},{"type":"null"}]},"sent_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their first email went out"},{"type":"null"}]},"opened_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they first opened an email"},{"type":"null"}]},"clicked_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they first loaded their link"},{"type":"null"}]},"submitted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they answered"},{"type":"null"}]},"bounced_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their email bounced"},{"type":"null"}]},"unsubscribed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they unsubscribed"},{"type":"null"}]},"testimonial_id":{"anyOf":[{"type":"string","description":"The testimonial they gave. It is verified, because it came through their own link"},{"type":"null"}]},"product_name":{"anyOf":[{"type":"string","description":"For a buyer, the product they paid for"},{"type":"null"}]},"paid_at":{"anyOf":[{"type":"string","format":"date-time","description":"For a buyer, when they paid"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When they were added"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"emails":{"type":"array","items":{"type":"string"},"description":"A list of up to 100 addresses of people in this request"}},"required":["emails"]}}}}},"get":{"operationId":"testimonial_request_recipients_list","summary":"List the people of a request","description":"Filter by where a person stands now: status opened is \"opened and did not click or answer\". The email address is null unless the caller may edit content.","tags":["Testimonial request recipients"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"request_id","in":"path","required":true,"description":"Testimonial request id (req_...), from testimonial_requests_list","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Where a person stands now: queued, sent, opened, clicked, submitted, bounced, unsubscribed or skipped. stopped lists the people a member stopped","enum":["queued","sent","opened","clicked","submitted","bounced","unsubscribed","skipped","stopped"]}},{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"Searches the name and the company. For a caller with content.write, also the address"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"email":{"anyOf":[{"type":"string","description":"The address. null unless the caller may edit content"},{"type":"null"}]},"name":{"anyOf":[{"type":"string","description":"Name, when known"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Company, when known"},{"type":"null"}]},"status":{"type":"string","description":"One of queued, sent, opened, clicked, submitted, bounced, unsubscribed, skipped"},"skip_reason":{"anyOf":[{"type":"string","description":"Why a skipped person is not asked: invalid_email, already_gave, already_being_asked, asked_recently, opted_out or refunded"},{"type":"null"}]},"stopped":{"type":"boolean","description":"true when a member stopped this person. They keep their status"},"emails_sent":{"type":"integer","description":"How many emails they were sent"},"last_event_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last thing happened"},{"type":"null"}]},"next_email_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their next email goes out"},{"type":"null"}]},"sent_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their first email went out"},{"type":"null"}]},"opened_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they first opened an email"},{"type":"null"}]},"clicked_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they first loaded their link"},{"type":"null"}]},"submitted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they answered"},{"type":"null"}]},"bounced_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their email bounced"},{"type":"null"}]},"unsubscribed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they unsubscribed"},{"type":"null"}]},"testimonial_id":{"anyOf":[{"type":"string","description":"The testimonial they gave. It is verified, because it came through their own link"},{"type":"null"}]},"product_name":{"anyOf":[{"type":"string","description":"For a buyer, the product they paid for"},{"type":"null"}]},"paid_at":{"anyOf":[{"type":"string","format":"date-time","description":"For a buyer, when they paid"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When they were added"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_request_recipients_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/requests/{request_id}/recipients/import.json":{"post":{"operationId":"testimonial_request_recipients_import","summary":"Add people to a request from a CSV file","description":"Two calls. Send the file (or its text as csv) to get the columns, their first rows and an upload_token. Then send the mapping from column number to field. Up to 5 MB and 10,000 rows. Adding to a running request emails people outside the workspace, so the member is told by email.","tags":["Testimonial request recipients"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"request_id","in":"path","required":true,"description":"Testimonial request id (req_...), from testimonial_requests_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"state":{"type":"string","description":"mapping (send the mapping next) or imported"},"rows_count":{"type":"integer","description":"Rows in the file, without the header"},"columns":{"type":"array","items":{"type":"object"},"description":"For the mapping: each column with its index, header, suggested field and first five values"},"upload_token":{"anyOf":[{"type":"string","description":"Stands for the file in the second call, for 30 minutes"},{"type":"null"}]},"added":{"anyOf":[{"type":"integer","description":"How many people are now queued"},{"type":"null"}]},"skipped":{"anyOf":[{"type":"object","description":"How many were skipped, by reason"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_request_recipients_import","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"The CSV file, up to 5 MB and 10,000 rows. Its first row is the header"},"csv":{"type":"string","description":"The CSV as text, for a caller that cannot upload a file"},"upload_token":{"type":"string","description":"What the first call returned. It stands for the file for 30 minutes"},"mapping":{"type":"object","additionalProperties":true,"description":"What each column holds, by column number counted from 0, e.g. { \"0\": \"name\", \"1\": \"email\" }. One column must be email. Others: name, first_name, company, title, ignore, or property:<key> for a custom property"}}}}}}}},"/sites/{site_id}/testimonials/requests/{request_id}/recipients/resume.json":{"post":{"operationId":"testimonial_request_recipients_resume","summary":"Resume chosen people of a request","description":"They continue where they stopped. Takes up to 100 addresses in the body. This emails people outside the workspace, so the member is told by email.","tags":["Testimonial request recipients"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"request_id","in":"path","required":true,"description":"Testimonial request id (req_...), from testimonial_requests_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"email":{"anyOf":[{"type":"string","description":"The address. null unless the caller may edit content"},{"type":"null"}]},"name":{"anyOf":[{"type":"string","description":"Name, when known"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Company, when known"},{"type":"null"}]},"status":{"type":"string","description":"One of queued, sent, opened, clicked, submitted, bounced, unsubscribed, skipped"},"skip_reason":{"anyOf":[{"type":"string","description":"Why a skipped person is not asked: invalid_email, already_gave, already_being_asked, asked_recently, opted_out or refunded"},{"type":"null"}]},"stopped":{"type":"boolean","description":"true when a member stopped this person. They keep their status"},"emails_sent":{"type":"integer","description":"How many emails they were sent"},"last_event_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last thing happened"},{"type":"null"}]},"next_email_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their next email goes out"},{"type":"null"}]},"sent_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their first email went out"},{"type":"null"}]},"opened_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they first opened an email"},{"type":"null"}]},"clicked_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they first loaded their link"},{"type":"null"}]},"submitted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they answered"},{"type":"null"}]},"bounced_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their email bounced"},{"type":"null"}]},"unsubscribed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they unsubscribed"},{"type":"null"}]},"testimonial_id":{"anyOf":[{"type":"string","description":"The testimonial they gave. It is verified, because it came through their own link"},{"type":"null"}]},"product_name":{"anyOf":[{"type":"string","description":"For a buyer, the product they paid for"},{"type":"null"}]},"paid_at":{"anyOf":[{"type":"string","format":"date-time","description":"For a buyer, when they paid"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When they were added"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_request_recipients_resume","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"emails":{"type":"array","items":{"type":"string"},"description":"A list of up to 100 addresses of people in this request"}},"required":["emails"]}}}}}},"/sites/{site_id}/testimonials/requests/{request_id}/recipients/stop.json":{"post":{"operationId":"testimonial_request_recipients_stop","summary":"Stop chosen people of a request","description":"They get no further email. Each keeps their status and gains \"stopped\". Takes up to 100 addresses in the body.","tags":["Testimonial request recipients"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"request_id","in":"path","required":true,"description":"Testimonial request id (req_...), from testimonial_requests_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"email":{"anyOf":[{"type":"string","description":"The address. null unless the caller may edit content"},{"type":"null"}]},"name":{"anyOf":[{"type":"string","description":"Name, when known"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Company, when known"},{"type":"null"}]},"status":{"type":"string","description":"One of queued, sent, opened, clicked, submitted, bounced, unsubscribed, skipped"},"skip_reason":{"anyOf":[{"type":"string","description":"Why a skipped person is not asked: invalid_email, already_gave, already_being_asked, asked_recently, opted_out or refunded"},{"type":"null"}]},"stopped":{"type":"boolean","description":"true when a member stopped this person. They keep their status"},"emails_sent":{"type":"integer","description":"How many emails they were sent"},"last_event_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last thing happened"},{"type":"null"}]},"next_email_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their next email goes out"},{"type":"null"}]},"sent_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their first email went out"},{"type":"null"}]},"opened_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they first opened an email"},{"type":"null"}]},"clicked_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they first loaded their link"},{"type":"null"}]},"submitted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they answered"},{"type":"null"}]},"bounced_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their email bounced"},{"type":"null"}]},"unsubscribed_at":{"anyOf":[{"type":"string","format":"date-time","description":"When they unsubscribed"},{"type":"null"}]},"testimonial_id":{"anyOf":[{"type":"string","description":"The testimonial they gave. It is verified, because it came through their own link"},{"type":"null"}]},"product_name":{"anyOf":[{"type":"string","description":"For a buyer, the product they paid for"},{"type":"null"}]},"paid_at":{"anyOf":[{"type":"string","format":"date-time","description":"For a buyer, when they paid"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When they were added"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_request_recipients_stop","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"emails":{"type":"array","items":{"type":"string"},"description":"A list of up to 100 addresses of people in this request"}},"required":["emails"]}}}}}},"/requests/resubscribe/{token}.json":{"post":{"operationId":"testimonial_request_resubscribes_confirm","summary":"Confirm receiving testimonial requests again","description":"The POST behind the button of the confirmation page. It lifts the opt-out, so the address can be asked again.","tags":["Testimonial requests"],"parameters":[{"name":"token","in":"path","required":true,"description":"The token from the confirmation email. It works for 7 days","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"The token from the confirmation email. It works for 7 days"}},"required":["token"]}}}},"security":[]}},"/requests/resubscribe.json":{"post":{"operationId":"testimonial_request_resubscribes_create","summary":"Ask for the email that lets an address receive requests again","description":"Sends a confirmation email to the address itself, when it had unsubscribed. The response is the same whether it had or not.","tags":["Testimonial requests"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"The token from the unsubscribe link of a request email"}},"required":["token"]}}}},"security":[]}},"/requests/unsubscribe/{token}.json":{"post":{"operationId":"testimonial_request_unsubscribes_create","summary":"Unsubscribe an address from testimonial requests","description":"The POST behind the unsubscribe page's button, and what a mail app's own unsubscribe button calls. The token comes from the link in the email.","tags":["Testimonial requests"],"parameters":[{"name":"token","in":"path","required":true,"description":"The token from the unsubscribe link of a request email","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"The token from the unsubscribe link of a request email"}},"required":["token"]}}}},"security":[]}},"/sites/{site_id}/testimonials/requests.json":{"post":{"operationId":"testimonial_requests_create","summary":"Start a request as a draft","description":"Creates a draft with its email and its recipients. Nothing is sent until testimonial_requests_send. Anything left out starts from a default: the email, one follow-up after 5 days, the site's name as the sender and you as the reply address. Each recipient is stored as queued, or as skipped with the reason.","tags":["Testimonial requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Request id, e.g. req_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"kind":{"type":"string","description":"campaign, or purchases for the standing request of a purchase connection"},"status":{"type":"string","description":"One of draft, scheduled, sending (first emails are going out), waiting (follow-ups are pending), stopped, finished"},"form_id":{"anyOf":[{"type":"string","description":"The form the button opens"},{"type":"null"}]},"sender_name":{"anyOf":[{"type":"string","description":"The name shown beside the From address of the site's email provider"},{"type":"null"}]},"reply_to":{"anyOf":[{"type":"string","description":"The member replies go to"},{"type":"null"}]},"subject":{"anyOf":[{"type":"string","description":"Subject of the first email, with its merge fields"},{"type":"null"}]},"body":{"anyOf":[{"type":"string","description":"Body of the first email, with its merge fields"},{"type":"null"}]},"button_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"show_logo":{"type":"boolean","description":"Whether the logo of the brand kit is above the body"},"skip_existing":{"type":"boolean","description":"Whether people who already gave a testimonial through the form are left out"},"follow_ups":{"type":"array","items":{"type":"object"},"description":"The follow-ups in order, each { delay_days, subject, body }"},"send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled request starts"},{"type":"null"}]},"next_send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the next email goes out"},{"type":"null"}]},"sent_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the first email went out"},{"type":"null"}]},"stopped_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was stopped"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last email went out or the last person answered"},{"type":"null"}]},"recipients_count":{"type":"integer","description":"Everyone added, including the skipped"},"sent_count":{"type":"integer","description":"People who were sent at least one email"},"opened_count":{"type":"integer","description":"People who opened an email. Approximate, because mail apps block or preload images"},"clicked_count":{"type":"integer","description":"People who loaded their own link"},"submitted_count":{"type":"integer","description":"People who answered"},"bounced_count":{"type":"integer","description":"People whose email bounced or who reported it as spam"},"unsubscribed_count":{"type":"integer","description":"People who unsubscribed"},"purchase_connection_id":{"anyOf":[{"type":"string","description":"The purchase connection this is the standing request of"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_requests_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Internal name, 1 to 100 characters. The default is \"Request of\" and the date"},"form_id":{"type":"string","description":"The form the button opens, e.g. frm_7Q2K9XH3AB. The default is the site's starter form"},"sender_name":{"type":"string","description":"Up to 60 characters. The name shown beside the From address of the site's email provider. The default is the site's name"},"reply_to":{"type":"string","description":"The confirmed email address of a member who can open the site. Replies go to that person. The default is the caller"},"subject":{"type":"string","description":"Up to 150 characters. Merge fields are allowed"},"body":{"type":"string","description":"Plain text with line breaks, up to 5,000 characters. Merge fields: {{first_name}}, {{name}}, {{company}}, {{site_name}}, {{sender_name}}, each with an optional fallback such as {{first_name|there}}. An unknown field is an error"},"button_label":{"type":"string","description":"Up to 40 characters. The default is \"Share your experience\". The button cannot be removed"},"show_logo":{"type":"boolean","description":"false leaves the logo of the brand kit out of the email"},"skip_existing":{"type":"boolean","description":"true (the default) leaves out anyone who already gave a testimonial through this form"},"follow_ups":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"A list of 0 to 3 follow-ups, each { delay_days, subject, body }. delay_days is 1 to 30, counted from the previous email. A follow-up without a subject reuses the first email's"},"recipients":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"A list of up to 500 people, each { email, name, company, title, properties }. Only email is required","default":[]}}}}}}},"get":{"operationId":"testimonial_requests_list","summary":"List the requests of a site","description":"Newest first, each with its email and its funnel counts. Filter by status, form or period.","tags":["Testimonial requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"Searches the name and the subject"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"One of draft, scheduled, sending, waiting, stopped, finished","enum":["draft","scheduled","sending","waiting","stopped","finished"]}},{"name":"form_id","in":"query","required":false,"schema":{"type":"string","description":"Only requests that lead to this form, e.g. frm_7Q2K9XH3AB"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","description":"Requests created or sent within 7d, 30d, 90d or 12m. all (the default) lists every one","enum":["7d","30d","90d","12m","all"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Request id, e.g. req_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"kind":{"type":"string","description":"campaign, or purchases for the standing request of a purchase connection"},"status":{"type":"string","description":"One of draft, scheduled, sending (first emails are going out), waiting (follow-ups are pending), stopped, finished"},"form_id":{"anyOf":[{"type":"string","description":"The form the button opens"},{"type":"null"}]},"sender_name":{"anyOf":[{"type":"string","description":"The name shown beside the From address of the site's email provider"},{"type":"null"}]},"reply_to":{"anyOf":[{"type":"string","description":"The member replies go to"},{"type":"null"}]},"subject":{"anyOf":[{"type":"string","description":"Subject of the first email, with its merge fields"},{"type":"null"}]},"body":{"anyOf":[{"type":"string","description":"Body of the first email, with its merge fields"},{"type":"null"}]},"button_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"show_logo":{"type":"boolean","description":"Whether the logo of the brand kit is above the body"},"skip_existing":{"type":"boolean","description":"Whether people who already gave a testimonial through the form are left out"},"follow_ups":{"type":"array","items":{"type":"object"},"description":"The follow-ups in order, each { delay_days, subject, body }"},"send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled request starts"},{"type":"null"}]},"next_send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the next email goes out"},{"type":"null"}]},"sent_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the first email went out"},{"type":"null"}]},"stopped_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was stopped"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last email went out or the last person answered"},{"type":"null"}]},"recipients_count":{"type":"integer","description":"Everyone added, including the skipped"},"sent_count":{"type":"integer","description":"People who were sent at least one email"},"opened_count":{"type":"integer","description":"People who opened an email. Approximate, because mail apps block or preload images"},"clicked_count":{"type":"integer","description":"People who loaded their own link"},"submitted_count":{"type":"integer","description":"People who answered"},"bounced_count":{"type":"integer","description":"People whose email bounced or who reported it as spam"},"unsubscribed_count":{"type":"integer","description":"People who unsubscribed"},"purchase_connection_id":{"anyOf":[{"type":"string","description":"The purchase connection this is the standing request of"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_requests_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/requests/{id}.json":{"delete":{"operationId":"testimonial_requests_delete","summary":"Delete a draft","description":"Only a request that was never sent can be deleted. A sent request is kept as the record of mail that was sent. Over MCP the tool changes nothing and responds with the page of the app where a person does it.","tags":["Testimonial requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_requests_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Request id, e.g. req_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"kind":{"type":"string","description":"campaign, or purchases for the standing request of a purchase connection"},"status":{"type":"string","description":"One of draft, scheduled, sending (first emails are going out), waiting (follow-ups are pending), stopped, finished"},"form_id":{"anyOf":[{"type":"string","description":"The form the button opens"},{"type":"null"}]},"sender_name":{"anyOf":[{"type":"string","description":"The name shown beside the From address of the site's email provider"},{"type":"null"}]},"reply_to":{"anyOf":[{"type":"string","description":"The member replies go to"},{"type":"null"}]},"subject":{"anyOf":[{"type":"string","description":"Subject of the first email, with its merge fields"},{"type":"null"}]},"body":{"anyOf":[{"type":"string","description":"Body of the first email, with its merge fields"},{"type":"null"}]},"button_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"show_logo":{"type":"boolean","description":"Whether the logo of the brand kit is above the body"},"skip_existing":{"type":"boolean","description":"Whether people who already gave a testimonial through the form are left out"},"follow_ups":{"type":"array","items":{"type":"object"},"description":"The follow-ups in order, each { delay_days, subject, body }"},"send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled request starts"},{"type":"null"}]},"next_send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the next email goes out"},{"type":"null"}]},"sent_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the first email went out"},{"type":"null"}]},"stopped_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was stopped"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last email went out or the last person answered"},{"type":"null"}]},"recipients_count":{"type":"integer","description":"Everyone added, including the skipped"},"sent_count":{"type":"integer","description":"People who were sent at least one email"},"opened_count":{"type":"integer","description":"People who opened an email. Approximate, because mail apps block or preload images"},"clicked_count":{"type":"integer","description":"People who loaded their own link"},"submitted_count":{"type":"integer","description":"People who answered"},"bounced_count":{"type":"integer","description":"People whose email bounced or who reported it as spam"},"unsubscribed_count":{"type":"integer","description":"People who unsubscribed"},"purchase_connection_id":{"anyOf":[{"type":"string","description":"The purchase connection this is the standing request of"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"testimonial_requests_get","summary":"Get one request with its email, follow-ups and funnel counts","description":"Returns the email, the follow-ups, the status and the funnel counts (sent, opened, clicked, submitted, bounced, unsubscribed) of one request.","tags":["Testimonial requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Request id, e.g. req_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Request id, e.g. req_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"kind":{"type":"string","description":"campaign, or purchases for the standing request of a purchase connection"},"status":{"type":"string","description":"One of draft, scheduled, sending (first emails are going out), waiting (follow-ups are pending), stopped, finished"},"form_id":{"anyOf":[{"type":"string","description":"The form the button opens"},{"type":"null"}]},"sender_name":{"anyOf":[{"type":"string","description":"The name shown beside the From address of the site's email provider"},{"type":"null"}]},"reply_to":{"anyOf":[{"type":"string","description":"The member replies go to"},{"type":"null"}]},"subject":{"anyOf":[{"type":"string","description":"Subject of the first email, with its merge fields"},{"type":"null"}]},"body":{"anyOf":[{"type":"string","description":"Body of the first email, with its merge fields"},{"type":"null"}]},"button_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"show_logo":{"type":"boolean","description":"Whether the logo of the brand kit is above the body"},"skip_existing":{"type":"boolean","description":"Whether people who already gave a testimonial through the form are left out"},"follow_ups":{"type":"array","items":{"type":"object"},"description":"The follow-ups in order, each { delay_days, subject, body }"},"send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled request starts"},{"type":"null"}]},"next_send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the next email goes out"},{"type":"null"}]},"sent_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the first email went out"},{"type":"null"}]},"stopped_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was stopped"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last email went out or the last person answered"},{"type":"null"}]},"recipients_count":{"type":"integer","description":"Everyone added, including the skipped"},"sent_count":{"type":"integer","description":"People who were sent at least one email"},"opened_count":{"type":"integer","description":"People who opened an email. Approximate, because mail apps block or preload images"},"clicked_count":{"type":"integer","description":"People who loaded their own link"},"submitted_count":{"type":"integer","description":"People who answered"},"bounced_count":{"type":"integer","description":"People whose email bounced or who reported it as spam"},"unsubscribed_count":{"type":"integer","description":"People who unsubscribed"},"purchase_connection_id":{"anyOf":[{"type":"string","description":"The purchase connection this is the standing request of"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_requests_get","x-permission":"analytics.read"},"patch":{"operationId":"testimonial_requests_update","summary":"Change a request's name, form or email","description":"Allowed at any time. A change applies to every email not yet sent. Changing a follow-up's delay re-times the follow-ups that are waiting.","tags":["Testimonial requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_requests_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Request id, e.g. req_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"kind":{"type":"string","description":"campaign, or purchases for the standing request of a purchase connection"},"status":{"type":"string","description":"One of draft, scheduled, sending (first emails are going out), waiting (follow-ups are pending), stopped, finished"},"form_id":{"anyOf":[{"type":"string","description":"The form the button opens"},{"type":"null"}]},"sender_name":{"anyOf":[{"type":"string","description":"The name shown beside the From address of the site's email provider"},{"type":"null"}]},"reply_to":{"anyOf":[{"type":"string","description":"The member replies go to"},{"type":"null"}]},"subject":{"anyOf":[{"type":"string","description":"Subject of the first email, with its merge fields"},{"type":"null"}]},"body":{"anyOf":[{"type":"string","description":"Body of the first email, with its merge fields"},{"type":"null"}]},"button_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"show_logo":{"type":"boolean","description":"Whether the logo of the brand kit is above the body"},"skip_existing":{"type":"boolean","description":"Whether people who already gave a testimonial through the form are left out"},"follow_ups":{"type":"array","items":{"type":"object"},"description":"The follow-ups in order, each { delay_days, subject, body }"},"send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled request starts"},{"type":"null"}]},"next_send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the next email goes out"},{"type":"null"}]},"sent_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the first email went out"},{"type":"null"}]},"stopped_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was stopped"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last email went out or the last person answered"},{"type":"null"}]},"recipients_count":{"type":"integer","description":"Everyone added, including the skipped"},"sent_count":{"type":"integer","description":"People who were sent at least one email"},"opened_count":{"type":"integer","description":"People who opened an email. Approximate, because mail apps block or preload images"},"clicked_count":{"type":"integer","description":"People who loaded their own link"},"submitted_count":{"type":"integer","description":"People who answered"},"bounced_count":{"type":"integer","description":"People whose email bounced or who reported it as spam"},"unsubscribed_count":{"type":"integer","description":"People who unsubscribed"},"purchase_connection_id":{"anyOf":[{"type":"string","description":"The purchase connection this is the standing request of"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_requests_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Internal name, 1 to 100 characters. The default is \"Request of\" and the date"},"form_id":{"type":"string","description":"The form the button opens, e.g. frm_7Q2K9XH3AB. The default is the site's starter form"},"sender_name":{"type":"string","description":"Up to 60 characters. The name shown beside the From address of the site's email provider. The default is the site's name"},"reply_to":{"type":"string","description":"The confirmed email address of a member who can open the site. Replies go to that person. The default is the caller"},"subject":{"type":"string","description":"Up to 150 characters. Merge fields are allowed"},"body":{"type":"string","description":"Plain text with line breaks, up to 5,000 characters. Merge fields: {{first_name}}, {{name}}, {{company}}, {{site_name}}, {{sender_name}}, each with an optional fallback such as {{first_name|there}}. An unknown field is an error"},"button_label":{"type":"string","description":"Up to 40 characters. The default is \"Share your experience\". The button cannot be removed"},"show_logo":{"type":"boolean","description":"false leaves the logo of the brand kit out of the email"},"skip_existing":{"type":"boolean","description":"true (the default) leaves out anyone who already gave a testimonial through this form"},"follow_ups":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"A list of 0 to 3 follow-ups, each { delay_days, subject, body }. delay_days is 1 to 30, counted from the previous email. A follow-up without a subject reuses the first email's"}}}}}}}},"/sites/{site_id}/testimonials/requests/{id}/duplicate.json":{"post":{"operationId":"testimonial_requests_duplicate","summary":"Copy a request into a new draft","description":"The copy has the same form and email, and no recipients yet.","tags":["Testimonial requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_requests_list","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Request id, e.g. req_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"kind":{"type":"string","description":"campaign, or purchases for the standing request of a purchase connection"},"status":{"type":"string","description":"One of draft, scheduled, sending (first emails are going out), waiting (follow-ups are pending), stopped, finished"},"form_id":{"anyOf":[{"type":"string","description":"The form the button opens"},{"type":"null"}]},"sender_name":{"anyOf":[{"type":"string","description":"The name shown beside the From address of the site's email provider"},{"type":"null"}]},"reply_to":{"anyOf":[{"type":"string","description":"The member replies go to"},{"type":"null"}]},"subject":{"anyOf":[{"type":"string","description":"Subject of the first email, with its merge fields"},{"type":"null"}]},"body":{"anyOf":[{"type":"string","description":"Body of the first email, with its merge fields"},{"type":"null"}]},"button_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"show_logo":{"type":"boolean","description":"Whether the logo of the brand kit is above the body"},"skip_existing":{"type":"boolean","description":"Whether people who already gave a testimonial through the form are left out"},"follow_ups":{"type":"array","items":{"type":"object"},"description":"The follow-ups in order, each { delay_days, subject, body }"},"send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled request starts"},{"type":"null"}]},"next_send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the next email goes out"},{"type":"null"}]},"sent_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the first email went out"},{"type":"null"}]},"stopped_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was stopped"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last email went out or the last person answered"},{"type":"null"}]},"recipients_count":{"type":"integer","description":"Everyone added, including the skipped"},"sent_count":{"type":"integer","description":"People who were sent at least one email"},"opened_count":{"type":"integer","description":"People who opened an email. Approximate, because mail apps block or preload images"},"clicked_count":{"type":"integer","description":"People who loaded their own link"},"submitted_count":{"type":"integer","description":"People who answered"},"bounced_count":{"type":"integer","description":"People whose email bounced or who reported it as spam"},"unsubscribed_count":{"type":"integer","description":"People who unsubscribed"},"purchase_connection_id":{"anyOf":[{"type":"string","description":"The purchase connection this is the standing request of"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_requests_duplicate","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Name of the copy. The default is \"Copy of\" and the name"}}}}}}}},"/sites/{site_id}/testimonials/requests/{id}/preview.json":{"get":{"operationId":"testimonial_requests_preview","summary":"See one email of a request as its first recipient gets it","description":"The sender, the subject and the body with the merge fields filled in. Nothing is sent. step 0 is the first email, 1 to 3 the follow-ups.","tags":["Testimonial requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_requests_list","schema":{"type":"string"}},{"name":"step","in":"query","required":false,"schema":{"type":"integer","description":"0 for the first email (the default), 1 to 3 for a follow-up","default":0}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"step":{"type":"integer","description":"0 for the first email, 1 to 3 for a follow-up"},"from":{"type":"string","description":"The From line"},"reply_to":{"anyOf":[{"type":"string","description":"Where replies go"},{"type":"null"}]},"to_name":{"anyOf":[{"type":"string","description":"The person the fields were filled in for"},{"type":"null"}]},"subject":{"type":"string","description":"The subject, filled in"},"text":{"type":"string","description":"The body, filled in"},"button_label":{"type":"string","description":"Text of the button"},"button_url":{"type":"string","description":"Where the button leads. In a preview it is the form's public link"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_requests_preview","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/requests/{id}/resume.json":{"post":{"operationId":"testimonial_requests_resume","summary":"Resume a stopped request","description":"Continues where it stopped. A follow-up that came due while stopped is timed again from now, so nothing goes out in a bunch. This emails people outside the workspace, so the member is told by email that an assistant resumed it.","tags":["Testimonial requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_requests_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Request id, e.g. req_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"kind":{"type":"string","description":"campaign, or purchases for the standing request of a purchase connection"},"status":{"type":"string","description":"One of draft, scheduled, sending (first emails are going out), waiting (follow-ups are pending), stopped, finished"},"form_id":{"anyOf":[{"type":"string","description":"The form the button opens"},{"type":"null"}]},"sender_name":{"anyOf":[{"type":"string","description":"The name shown beside the From address of the site's email provider"},{"type":"null"}]},"reply_to":{"anyOf":[{"type":"string","description":"The member replies go to"},{"type":"null"}]},"subject":{"anyOf":[{"type":"string","description":"Subject of the first email, with its merge fields"},{"type":"null"}]},"body":{"anyOf":[{"type":"string","description":"Body of the first email, with its merge fields"},{"type":"null"}]},"button_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"show_logo":{"type":"boolean","description":"Whether the logo of the brand kit is above the body"},"skip_existing":{"type":"boolean","description":"Whether people who already gave a testimonial through the form are left out"},"follow_ups":{"type":"array","items":{"type":"object"},"description":"The follow-ups in order, each { delay_days, subject, body }"},"send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled request starts"},{"type":"null"}]},"next_send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the next email goes out"},{"type":"null"}]},"sent_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the first email went out"},{"type":"null"}]},"stopped_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was stopped"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last email went out or the last person answered"},{"type":"null"}]},"recipients_count":{"type":"integer","description":"Everyone added, including the skipped"},"sent_count":{"type":"integer","description":"People who were sent at least one email"},"opened_count":{"type":"integer","description":"People who opened an email. Approximate, because mail apps block or preload images"},"clicked_count":{"type":"integer","description":"People who loaded their own link"},"submitted_count":{"type":"integer","description":"People who answered"},"bounced_count":{"type":"integer","description":"People whose email bounced or who reported it as spam"},"unsubscribed_count":{"type":"integer","description":"People who unsubscribed"},"purchase_connection_id":{"anyOf":[{"type":"string","description":"The purchase connection this is the standing request of"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_requests_resume","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials/requests/{id}/send.json":{"post":{"operationId":"testimonial_requests_send","summary":"Send a request, now or at a time","description":"Needs confirm_relationship: true. The queued recipients are checked once more, then the first emails go out (or wait for send_at). Follow-ups go to the people who have not answered. Request emails are sent through the site's own email provider (Settings > Email sending, Business and up), so a site without a working connection gets 422 no_email_connection or email_connection_paused, and another plan gets 402 plan_limit. Every email counts toward the site's monthly cap of request emails (10,000 unless we set another). At the cap nothing is dropped: the people stay queued and sending continues on the 1st. This emails people outside the workspace, so the member is told by email that an assistant sent it.","tags":["Testimonial requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_requests_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Request id, e.g. req_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"kind":{"type":"string","description":"campaign, or purchases for the standing request of a purchase connection"},"status":{"type":"string","description":"One of draft, scheduled, sending (first emails are going out), waiting (follow-ups are pending), stopped, finished"},"form_id":{"anyOf":[{"type":"string","description":"The form the button opens"},{"type":"null"}]},"sender_name":{"anyOf":[{"type":"string","description":"The name shown beside the From address of the site's email provider"},{"type":"null"}]},"reply_to":{"anyOf":[{"type":"string","description":"The member replies go to"},{"type":"null"}]},"subject":{"anyOf":[{"type":"string","description":"Subject of the first email, with its merge fields"},{"type":"null"}]},"body":{"anyOf":[{"type":"string","description":"Body of the first email, with its merge fields"},{"type":"null"}]},"button_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"show_logo":{"type":"boolean","description":"Whether the logo of the brand kit is above the body"},"skip_existing":{"type":"boolean","description":"Whether people who already gave a testimonial through the form are left out"},"follow_ups":{"type":"array","items":{"type":"object"},"description":"The follow-ups in order, each { delay_days, subject, body }"},"send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled request starts"},{"type":"null"}]},"next_send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the next email goes out"},{"type":"null"}]},"sent_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the first email went out"},{"type":"null"}]},"stopped_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was stopped"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last email went out or the last person answered"},{"type":"null"}]},"recipients_count":{"type":"integer","description":"Everyone added, including the skipped"},"sent_count":{"type":"integer","description":"People who were sent at least one email"},"opened_count":{"type":"integer","description":"People who opened an email. Approximate, because mail apps block or preload images"},"clicked_count":{"type":"integer","description":"People who loaded their own link"},"submitted_count":{"type":"integer","description":"People who answered"},"bounced_count":{"type":"integer","description":"People whose email bounced or who reported it as spam"},"unsubscribed_count":{"type":"integer","description":"People who unsubscribed"},"purchase_connection_id":{"anyOf":[{"type":"string","description":"The purchase connection this is the standing request of"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_requests_send","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm_relationship":{"type":"boolean","description":"Must be true. It says these people are customers or contacts of the site and you may email them","default":false},"send_at":{"type":"string","description":"When to send, e.g. 2026-10-12T09:00. Without a zone it is in the site's time zone. Leave it out to send now"}}}}}}}},"/sites/{site_id}/testimonials/requests/{id}/send_test.json":{"post":{"operationId":"testimonial_requests_send_test","summary":"Send one email of a request to your own address","description":"Goes to the caller's own address only, through the site's own email provider like the real ones (422 no_email_connection without one). It has no personal link and no open counter, and does not count toward the site's monthly cap.","tags":["Testimonial requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_requests_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"step":{"type":"integer","description":"0 for the first email, 1 to 3 for a follow-up"},"from":{"type":"string","description":"The From line"},"reply_to":{"anyOf":[{"type":"string","description":"Where replies go"},{"type":"null"}]},"to_name":{"anyOf":[{"type":"string","description":"The person the fields were filled in for"},{"type":"null"}]},"subject":{"type":"string","description":"The subject, filled in"},"text":{"type":"string","description":"The body, filled in"},"button_label":{"type":"string","description":"Text of the button"},"button_url":{"type":"string","description":"Where the button leads. In a preview it is the form's public link"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_requests_send_test","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"step":{"type":"integer","description":"0 for the first email (the default), 1 to 3 for a follow-up","default":0}}}}}}}},"/sites/{site_id}/testimonials/requests/{id}/stop.json":{"post":{"operationId":"testimonial_requests_stop","summary":"Stop a request","description":"Cancels every email not yet sent, at once. Nothing already sent is affected, and testimonial_requests_resume continues where it stopped.","tags":["Testimonial requests"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_requests_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Request id, e.g. req_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"kind":{"type":"string","description":"campaign, or purchases for the standing request of a purchase connection"},"status":{"type":"string","description":"One of draft, scheduled, sending (first emails are going out), waiting (follow-ups are pending), stopped, finished"},"form_id":{"anyOf":[{"type":"string","description":"The form the button opens"},{"type":"null"}]},"sender_name":{"anyOf":[{"type":"string","description":"The name shown beside the From address of the site's email provider"},{"type":"null"}]},"reply_to":{"anyOf":[{"type":"string","description":"The member replies go to"},{"type":"null"}]},"subject":{"anyOf":[{"type":"string","description":"Subject of the first email, with its merge fields"},{"type":"null"}]},"body":{"anyOf":[{"type":"string","description":"Body of the first email, with its merge fields"},{"type":"null"}]},"button_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"show_logo":{"type":"boolean","description":"Whether the logo of the brand kit is above the body"},"skip_existing":{"type":"boolean","description":"Whether people who already gave a testimonial through the form are left out"},"follow_ups":{"type":"array","items":{"type":"object"},"description":"The follow-ups in order, each { delay_days, subject, body }"},"send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a scheduled request starts"},{"type":"null"}]},"next_send_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the next email goes out"},{"type":"null"}]},"sent_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the first email went out"},{"type":"null"}]},"stopped_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was stopped"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the last email went out or the last person answered"},{"type":"null"}]},"recipients_count":{"type":"integer","description":"Everyone added, including the skipped"},"sent_count":{"type":"integer","description":"People who were sent at least one email"},"opened_count":{"type":"integer","description":"People who opened an email. Approximate, because mail apps block or preload images"},"clicked_count":{"type":"integer","description":"People who loaded their own link"},"submitted_count":{"type":"integer","description":"People who answered"},"bounced_count":{"type":"integer","description":"People whose email bounced or who reported it as spam"},"unsubscribed_count":{"type":"integer","description":"People who unsubscribed"},"purchase_connection_id":{"anyOf":[{"type":"string","description":"The purchase connection this is the standing request of"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was created"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_requests_stop","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials/views.json":{"post":{"operationId":"testimonial_saved_views_create","summary":"Save a filter, search text, sort and layout of the inbox under a name","description":"A personal view needs only analytics.read. A shared one needs content.write and is refused with the code not_allowed otherwise. A pinned view sits in the sidebar with its count. Open it with testimonials_list and view_id.","tags":["Testimonial saved views"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Saved view id, e.g. vw_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"The name shown in the views menu and the sidebar"},"filters":{"type":"object","description":"The inbox filter inputs it stores, e.g. {\"status\": [\"approved\"], \"rating\": [\"5\"]}"},"q":{"anyOf":[{"type":"string","description":"The search text it stores, operators included"},{"type":"null"}]},"sort":{"anyOf":[{"type":"string","description":"The sort it opens with, or null for the default"},{"type":"null"}]},"layout":{"type":"string","description":"list, cards, board or highlights"},"columns":{"type":"array","items":{"type":"string"},"description":"The columns of the list layout it opens with. Empty means the member's own choice"},"pinned":{"type":"boolean","description":"Shown in the sidebar under Testimonials with its count"},"shared":{"type":"boolean","description":"Visible to every member who can open the site. False means only its owner"},"position":{"type":"integer","description":"Its place among the pinned views"},"mine":{"type":"boolean","description":"True when the caller owns it"},"owner_name":{"anyOf":[{"type":"string","description":"The name of the member who made it"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was saved"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_saved_views_create","x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Required, up to 60 characters, unique per owner"},"filters":{"type":"object","additionalProperties":true,"description":"The inbox filter inputs to store, the same ones testimonials_list takes, e.g. {\"status\": [\"approved\"], \"tag_id\": [\"tag_7Q2K9XH3AB\"]}. Not q, which has its own input"},"q":{"type":"string","description":"The search text to store, operators included, up to 500 characters"},"sort":{"type":"string","description":"A sort of testimonials_list. Leave out for the default"},"layout":{"type":"string","description":"list (the default), cards, board or highlights"},"columns":{"type":"array","items":{"type":"string"},"description":"Columns of the list layout, e.g. [\"person\", \"rating\", \"status\"]. A custom property column is prop.<key>"},"pinned":{"type":"boolean","description":"true shows it in the sidebar under Testimonials with its count"},"shared":{"type":"boolean","description":"true shows it to every member who can open the site. Needs content.write"},"position":{"type":"integer","description":"Its place among the pinned views. Leave out to add it last"}}}}}}},"get":{"operationId":"testimonial_saved_views_list","summary":"List the saved views of a site that the caller can open","description":"Returns the caller's own views and every shared one, pinned ones first in their order, then by name. scope is all (the default), mine or shared. Pass a view's id as view_id to testimonials_list to read the testimonials it holds.","tags":["Testimonial saved views"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"scope","in":"query","required":false,"schema":{"type":"string","description":"all (the default) lists the caller's own views and every shared one, mine only the caller's personal ones, shared only the shared ones","enum":["all","mine","shared"],"default":"all"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Saved view id, e.g. vw_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"The name shown in the views menu and the sidebar"},"filters":{"type":"object","description":"The inbox filter inputs it stores, e.g. {\"status\": [\"approved\"], \"rating\": [\"5\"]}"},"q":{"anyOf":[{"type":"string","description":"The search text it stores, operators included"},{"type":"null"}]},"sort":{"anyOf":[{"type":"string","description":"The sort it opens with, or null for the default"},{"type":"null"}]},"layout":{"type":"string","description":"list, cards, board or highlights"},"columns":{"type":"array","items":{"type":"string"},"description":"The columns of the list layout it opens with. Empty means the member's own choice"},"pinned":{"type":"boolean","description":"Shown in the sidebar under Testimonials with its count"},"shared":{"type":"boolean","description":"Visible to every member who can open the site. False means only its owner"},"position":{"type":"integer","description":"Its place among the pinned views"},"mine":{"type":"boolean","description":"True when the caller owns it"},"owner_name":{"anyOf":[{"type":"string","description":"The name of the member who made it"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was saved"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_saved_views_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/views/{id}.json":{"delete":{"operationId":"testimonial_saved_views_destroy","summary":"Delete a saved view. No testimonial is touched","description":"A saved view is a stored filter, so only the view goes. A widget or wall fed by the view keeps its settings and has nothing to show until it is given another feed. A personal view is deleted by its owner, and a shared one needs content.write. Otherwise the call is refused with the code not_allowed. Over MCP the tool changes nothing and responds with the page of the app where a person does it.","tags":["Testimonial saved views"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_saved_views_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Saved view id, e.g. vw_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"The name shown in the views menu and the sidebar"},"filters":{"type":"object","description":"The inbox filter inputs it stores, e.g. {\"status\": [\"approved\"], \"rating\": [\"5\"]}"},"q":{"anyOf":[{"type":"string","description":"The search text it stores, operators included"},{"type":"null"}]},"sort":{"anyOf":[{"type":"string","description":"The sort it opens with, or null for the default"},{"type":"null"}]},"layout":{"type":"string","description":"list, cards, board or highlights"},"columns":{"type":"array","items":{"type":"string"},"description":"The columns of the list layout it opens with. Empty means the member's own choice"},"pinned":{"type":"boolean","description":"Shown in the sidebar under Testimonials with its count"},"shared":{"type":"boolean","description":"Visible to every member who can open the site. False means only its owner"},"position":{"type":"integer","description":"Its place among the pinned views"},"mine":{"type":"boolean","description":"True when the caller owns it"},"owner_name":{"anyOf":[{"type":"string","description":"The name of the member who made it"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was saved"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"patch":{"operationId":"testimonial_saved_views_update","summary":"Rename a saved view, change what it stores, pin it or share it","description":"Only the inputs sent change: name, the stored search (q), filters, sort, layout, columns, position, pinned and shared. A personal view is changed by its owner. Changing a shared view, and sharing or unsharing any view, needs content.write.","tags":["Testimonial saved views"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_saved_views_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Saved view id, e.g. vw_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"The name shown in the views menu and the sidebar"},"filters":{"type":"object","description":"The inbox filter inputs it stores, e.g. {\"status\": [\"approved\"], \"rating\": [\"5\"]}"},"q":{"anyOf":[{"type":"string","description":"The search text it stores, operators included"},{"type":"null"}]},"sort":{"anyOf":[{"type":"string","description":"The sort it opens with, or null for the default"},{"type":"null"}]},"layout":{"type":"string","description":"list, cards, board or highlights"},"columns":{"type":"array","items":{"type":"string"},"description":"The columns of the list layout it opens with. Empty means the member's own choice"},"pinned":{"type":"boolean","description":"Shown in the sidebar under Testimonials with its count"},"shared":{"type":"boolean","description":"Visible to every member who can open the site. False means only its owner"},"position":{"type":"integer","description":"Its place among the pinned views"},"mine":{"type":"boolean","description":"True when the caller owns it"},"owner_name":{"anyOf":[{"type":"string","description":"The name of the member who made it"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was saved"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_saved_views_update","x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Up to 60 characters, unique per owner"},"filters":{"type":"object","additionalProperties":true,"description":"The inbox filter inputs to store. Replaces what was stored"},"q":{"type":"string","description":"The search text to store. Empty clears it"},"sort":{"type":"string","description":"A sort of testimonials_list. Empty returns to the default"},"layout":{"type":"string","description":"list, cards, board or highlights"},"columns":{"type":"array","items":{"type":"string"},"description":"Columns of the list layout. An empty list returns to the member's own choice"},"pinned":{"type":"boolean","description":"true pins it to the sidebar, false unpins it"},"shared":{"type":"boolean","description":"true shares it with the workspace, false makes it personal again. Needs content.write"},"position":{"type":"integer","description":"Its place among the pinned views"}}}}}}}},"/sites/{site_id}/testimonials/imports/spreadsheet.json":{"post":{"operationId":"testimonial_spreadsheet_imports_create","summary":"Upload a spreadsheet (or send CSV text) and read its columns","description":"Step 1 of a spreadsheet import. Send file (CSV, TSV or XLSX, 10 MB and 5,000 rows at most, headers in the first row) or content (CSV text up to 1 MB). The response has the columns, three sample values of each and a first guess of where each column goes. Nothing is imported yet: continue with testimonial_spreadsheet_imports_update and testimonial_spreadsheet_imports_run. A spreadsheet never counts toward the monthly testimonials or the fetched imports.","tags":["Testimonial spreadsheet imports"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The spreadsheet's id (src_...). Use it as the source id to review and keep"},"name":{"type":"string"},"state":{"type":"string"},"rows":{"type":"integer","description":"Rows in the file, without the header"},"columns":{"type":"array","items":{"type":"string"},"description":"The file's column names"},"samples":{"type":"object","description":"The first three values of each column. Empty for a caller without content.write"},"mapping":{"type":"object","description":"Column name to field key. An empty value means do not import"},"fields":{"type":"array","items":{"type":"string"},"description":"The field keys a column can go to"},"default_status":{"type":"string","description":"pending or approved"},"tags":{"type":"array","items":{"type":"string"}},"collection_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"default_source_name":{"anyOf":[{"type":"string"},{"type":"null"}]},"date_format":{"type":"string","description":"auto, ymd, dmy or mdy"},"duplicates":{"type":"string","description":"skip or queue"},"counts":{"type":"object","description":"What the last reading found: ready, already_here, likely_duplicate, kept, and skipped by reason"},"waiting_count":{"type":"integer","description":"Rows waiting in the review step"},"kept_count":{"type":"integer","description":"Rows kept as testimonials"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_spreadsheet_imports_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"The file. CSV, TSV or XLSX, 10 MB and 5,000 rows at most, with headers in the first row"},"content":{"type":"string","description":"CSV text up to 1 MB, for a caller that cannot send a file"},"filename":{"type":"string","description":"The name to show for it. The ending says the type when content is not CSV"}}}}}}}},"/sites/{site_id}/testimonials/imports/spreadsheet/{id}/run.json":{"post":{"operationId":"testimonial_spreadsheet_imports_run","summary":"Read the matched file into the review step","description":"Rows that can be used wait with a tick box. Rows that cannot are listed with their row number and the reason. Keep them with testimonial_import_sources_keep, using the spreadsheet's id as the source id.","tags":["Testimonial spreadsheet imports"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by the tools that list or create it","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The spreadsheet's id (src_...). Use it as the source id to review and keep"},"name":{"type":"string"},"state":{"type":"string"},"rows":{"type":"integer","description":"Rows in the file, without the header"},"columns":{"type":"array","items":{"type":"string"},"description":"The file's column names"},"samples":{"type":"object","description":"The first three values of each column. Empty for a caller without content.write"},"mapping":{"type":"object","description":"Column name to field key. An empty value means do not import"},"fields":{"type":"array","items":{"type":"string"},"description":"The field keys a column can go to"},"default_status":{"type":"string","description":"pending or approved"},"tags":{"type":"array","items":{"type":"string"}},"collection_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"default_source_name":{"anyOf":[{"type":"string"},{"type":"null"}]},"date_format":{"type":"string","description":"auto, ymd, dmy or mdy"},"duplicates":{"type":"string","description":"skip or queue"},"counts":{"type":"object","description":"What the last reading found: ready, already_here, likely_duplicate, kept, and skipped by reason"},"waiting_count":{"type":"integer","description":"Rows waiting in the review step"},"kept_count":{"type":"integer","description":"Rows kept as testimonials"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_spreadsheet_imports_run","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm_count":{"type":"integer","description":"The number of rows you expect. The run is refused when the file has a different number"}}}}}}}},"/sites/{site_id}/testimonials/imports/spreadsheet/{id}.json":{"get":{"operationId":"testimonial_spreadsheet_imports_get","summary":"Get a spreadsheet's columns, samples, matching, options and counts","description":"Returns the file's columns with sample values, which field each column goes to, the options (default status, tags, collection, date format, what happens to duplicates) and, once it has run, how many rows wait in the review step and how many were kept.","tags":["Testimonial spreadsheet imports"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by the tools that list or create it","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The spreadsheet's id (src_...). Use it as the source id to review and keep"},"name":{"type":"string"},"state":{"type":"string"},"rows":{"type":"integer","description":"Rows in the file, without the header"},"columns":{"type":"array","items":{"type":"string"},"description":"The file's column names"},"samples":{"type":"object","description":"The first three values of each column. Empty for a caller without content.write"},"mapping":{"type":"object","description":"Column name to field key. An empty value means do not import"},"fields":{"type":"array","items":{"type":"string"},"description":"The field keys a column can go to"},"default_status":{"type":"string","description":"pending or approved"},"tags":{"type":"array","items":{"type":"string"}},"collection_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"default_source_name":{"anyOf":[{"type":"string"},{"type":"null"}]},"date_format":{"type":"string","description":"auto, ymd, dmy or mdy"},"duplicates":{"type":"string","description":"skip or queue"},"counts":{"type":"object","description":"What the last reading found: ready, already_here, likely_duplicate, kept, and skipped by reason"},"waiting_count":{"type":"integer","description":"Rows waiting in the review step"},"kept_count":{"type":"integer","description":"Rows kept as testimonials"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_spreadsheet_imports_get","x-permission":"analytics.read"},"patch":{"operationId":"testimonial_spreadsheet_imports_update","summary":"Save which column goes where, and the options for the file","description":"Steps 2 and 3 of a spreadsheet import. mapping is an object of column name to field, with an empty value for a column to leave out, and two columns cannot go to one field. The options are default_status (pending or approved), tags, collection_id (a manual collection), default_source_name, date_format (auto, ymd, dmy or mdy) and duplicates (skip or queue). Only what is sent changes, and nothing is imported until testimonial_spreadsheet_imports_run.","tags":["Testimonial spreadsheet imports"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by the tools that list or create it","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The spreadsheet's id (src_...). Use it as the source id to review and keep"},"name":{"type":"string"},"state":{"type":"string"},"rows":{"type":"integer","description":"Rows in the file, without the header"},"columns":{"type":"array","items":{"type":"string"},"description":"The file's column names"},"samples":{"type":"object","description":"The first three values of each column. Empty for a caller without content.write"},"mapping":{"type":"object","description":"Column name to field key. An empty value means do not import"},"fields":{"type":"array","items":{"type":"string"},"description":"The field keys a column can go to"},"default_status":{"type":"string","description":"pending or approved"},"tags":{"type":"array","items":{"type":"string"}},"collection_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"default_source_name":{"anyOf":[{"type":"string"},{"type":"null"}]},"date_format":{"type":"string","description":"auto, ymd, dmy or mdy"},"duplicates":{"type":"string","description":"skip or queue"},"counts":{"type":"object","description":"What the last reading found: ready, already_here, likely_duplicate, kept, and skipped by reason"},"waiting_count":{"type":"integer","description":"Rows waiting in the review step"},"kept_count":{"type":"integer","description":"Rows kept as testimonials"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_spreadsheet_imports_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mapping":{"type":"object","additionalProperties":true,"description":"Column name to field key, for example {\"Name\": \"person_name\", \"Review\": \"body\"}. An empty value means do not import. The field keys are in testimonial_spreadsheet_imports_get"},"default_status":{"type":"string","description":"pending (the default) or approved, for rows with no status of their own"},"tags":{"type":"array","items":{"type":"string"},"description":"Tag names added to every row"},"collection_id":{"type":"string","description":"A manual collection (col_...) every kept row is added to"},"default_source_name":{"type":"string","description":"The source name for rows with none"},"date_format":{"type":"string","description":"auto (the default), ymd, dmy or mdy"},"duplicates":{"type":"string","description":"skip (the default) or queue. Queue also keeps rows that look like one already stored and sends each pair to Duplicates"}}}}}}}},"/sites/{site_id}/testimonials/tags/{id}/apply_rules.json":{"post":{"operationId":"testimonial_tags_apply_rules","summary":"Run a tag's rules over the testimonials already stored","description":"dry_run true (the default) changes nothing and responds with the counts: how many would be tagged, of how many, and how many already have the tag. dry_run false tags them as one bulk action and responds with undo_id, which testimonials_bulk_undo takes for 7 days. More than 100 run in the background and the response has state running.","tags":["Testimonial tags"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_tags_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"dry_run":{"type":"boolean","description":"true when nothing was changed"},"state":{"type":"string","description":"dry_run, done or running (more than 100, in the background)"},"total":{"type":"integer","description":"How many testimonials the site holds, the trash left out"},"matching":{"type":"integer","description":"How many satisfy at least one rule of the tag"},"already_tagged":{"type":"integer","description":"How many of those already had the tag"},"to_tag":{"type":"integer","description":"How many did not have it, which is what a run tags"},"tagged":{"anyOf":[{"type":"integer","description":"How many this run has tagged so far. Null for a dry run"},{"type":"null"}]},"undo_id":{"anyOf":[{"type":"string","description":"The undo record (blk_...) that testimonials_bulk_undo takes. Null for a dry run and when nothing was tagged"},{"type":"null"}]},"undo_until":{"anyOf":[{"type":"string","format":"date-time","description":"Until when it can be undone"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_tags_apply_rules","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dry_run":{"type":"boolean","description":"true (the default) only counts. false tags the testimonials and responds with the undo id","default":true}}}}}}}},"/sites/{site_id}/testimonials/tags.json":{"post":{"operationId":"testimonial_tags_create","summary":"Create a tag, with auto-tag rules if you send them","description":"A rule is { match, conditions }. A testimonial that satisfies any one rule gets the tag at the moment it arrives. Rules only ever add a tag. To tag what is already stored, call testimonial_tags_apply_rules next.","tags":["Testimonial tags"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The tag id (tag_...)"},"name":{"type":"string","description":"Its name"},"color":{"type":"string","description":"rose, coral, amber, green, teal, blue, violet or gray"},"testimonials_count":{"type":"integer","description":"How many testimonials carry it, the trash left out"},"rules":{"type":"array","items":{"type":"object"},"description":"Its auto-tag rules, each as { match, conditions, summary, last_applied_at }. summary is the rule in plain English"},"rules_count":{"type":"integer","description":"How many rules it has"},"last_rule_applied_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a rule last added this tag. Null when none has"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null otherwise"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_tags_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Required. Up to 40 characters, unique on the site without regard to case"},"color":{"type":"string","description":"rose, coral, amber, green, teal, blue, violet or gray (the default)","enum":["rose","coral","amber","green","teal","blue","violet","gray"],"default":"gray"},"rules":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Up to 10 rules. Each is { match, conditions } with 1 to 10 conditions, e.g. [{\"match\": \"all\", \"conditions\": [{\"field\": \"words\", \"operator\": \"contain\", \"value\": [\"onboarding\"]}]}]. Fields: words, source, source_name, form, language, rating, url_param.<name> (a parameter passed to the form) and property.<key>. A testimonial that satisfies any one rule gets the tag on arrival"}},"required":["name"]}}}}},"get":{"operationId":"testimonial_tags_list","summary":"List the tags of a site with their rules","description":"Each tag comes with how many testimonials carry it, its auto-tag rules as structured conditions and in plain English, and when a rule last applied it. Tags in the trash are left out.","tags":["Testimonial tags"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Narrow the list to tags whose name contains this text"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"name (the default), used (most used first) or newest","enum":["name","used","newest"],"default":"name"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The tag id (tag_...)"},"name":{"type":"string","description":"Its name"},"color":{"type":"string","description":"rose, coral, amber, green, teal, blue, violet or gray"},"testimonials_count":{"type":"integer","description":"How many testimonials carry it, the trash left out"},"rules":{"type":"array","items":{"type":"object"},"description":"Its auto-tag rules, each as { match, conditions, summary, last_applied_at }. summary is the rule in plain English"},"rules_count":{"type":"integer","description":"How many rules it has"},"last_rule_applied_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a rule last added this tag. Null when none has"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null otherwise"},{"type":"null"}]}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_tags_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/tags/{id}.json":{"delete":{"operationId":"testimonial_tags_destroy","summary":"Move a tag to the trash for 30 days","description":"It leaves every testimonial, filter and picker. Restoring it with testimonial_trash_restore puts it back on every testimonial that had it. A smart collection whose rules name it matches nothing until then. Over MCP the tool changes nothing and responds with the page of the app where a person does it.","tags":["Testimonial tags"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_tags_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The tag id (tag_...)"},"name":{"type":"string","description":"Its name"},"color":{"type":"string","description":"rose, coral, amber, green, teal, blue, violet or gray"},"testimonials_count":{"type":"integer","description":"How many testimonials carry it, the trash left out"},"rules":{"type":"array","items":{"type":"object"},"description":"Its auto-tag rules, each as { match, conditions, summary, last_applied_at }. summary is the rule in plain English"},"rules_count":{"type":"integer","description":"How many rules it has"},"last_rule_applied_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a rule last added this tag. Null when none has"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null otherwise"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"patch":{"operationId":"testimonial_tags_update","summary":"Change a tag's name, color or rules","description":"Only what is sent changes. Sending rules replaces every rule of the tag, and an empty list removes them all.","tags":["Testimonial tags"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_tags_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The tag id (tag_...)"},"name":{"type":"string","description":"Its name"},"color":{"type":"string","description":"rose, coral, amber, green, teal, blue, violet or gray"},"testimonials_count":{"type":"integer","description":"How many testimonials carry it, the trash left out"},"rules":{"type":"array","items":{"type":"object"},"description":"Its auto-tag rules, each as { match, conditions, summary, last_applied_at }. summary is the rule in plain English"},"rules_count":{"type":"integer","description":"How many rules it has"},"last_rule_applied_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a rule last added this tag. Null when none has"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null otherwise"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_tags_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Up to 40 characters, unique on the site without regard to case"},"color":{"type":"string","description":"rose, coral, amber, green, teal, blue, violet or gray","enum":["rose","coral","amber","green","teal","blue","violet","gray"]},"rules":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Replaces every rule of the tag. Up to 10 rules of { match, conditions }, as in testimonial_tags_create. An empty list removes them all"}}}}}}}},"/sites/{site_id}/testimonials/tags/{id}/merge.json":{"post":{"operationId":"testimonial_tags_merge","summary":"Merge a tag into another one","description":"Every testimonial that had this tag gets the other, every rule moves to the other, every smart collection, saved view, widget and wall that named this tag names the other, and this tag goes to the trash, empty. Responds with the tag that is kept.","tags":["Testimonial tags"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_tags_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The tag id (tag_...)"},"name":{"type":"string","description":"Its name"},"color":{"type":"string","description":"rose, coral, amber, green, teal, blue, violet or gray"},"testimonials_count":{"type":"integer","description":"How many testimonials carry it, the trash left out"},"rules":{"type":"array","items":{"type":"object"},"description":"Its auto-tag rules, each as { match, conditions, summary, last_applied_at }. summary is the rule in plain English"},"rules_count":{"type":"integer","description":"How many rules it has"},"last_rule_applied_at":{"anyOf":[{"type":"string","format":"date-time","description":"When a rule last added this tag. Null when none has"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null otherwise"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_tags_merge","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"into_id":{"type":"string","description":"The tag that is kept (tag_...). It must be another tag of this site that is not in the trash"}},"required":["into_id"]}}}}}},"/sites/{site_id}/testimonials/translations.json":{"post":{"operationId":"testimonial_translations_create","summary":"Translate testimonials into the languages a site offers","description":"Call testimonial_translations_estimate first. This sends the body, title and highlight of the chosen testimonials to Google Cloud Translation (never a name, an email or a company), and the member is emailed that an assistant started it. The translating happens in the background, and a row that is already stored is never fetched again. At the month's character quota the rest are stored as waiting and continue on the 1st. Responds with 402 plan_limit below Business, and with 422 not_configured while translation is not set up.","tags":["Testimonial translations"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"testimonials":{"type":"integer","description":"Testimonials in the selection"},"languages":{"type":"array","items":{"type":"string"},"description":"The target languages"},"characters":{"type":"integer","description":"Characters that would be sent (or were queued)"},"stored_characters":{"type":"integer","description":"Characters of the selection that are already stored and will not be sent"},"pairs":{"type":"integer","description":"Translations to make, one per testimonial and language"},"quota":{"type":"integer","description":"The month's character quota"},"quota_used":{"type":"integer","description":"Characters used this month"},"quota_left":{"type":"integer","description":"Characters left this month"},"fits":{"type":"boolean","description":"false when the run is larger than what is left. The rest waits for the 1st"},"available":{"type":"boolean","description":"The plan includes translation (Business and up)"},"configured":{"type":"boolean","description":"Translation is set up at Privatus Analytics"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_translations_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"Up to 100 testimonials (tm_...). One of testimonial_ids, collection_id and all_approved","default":[]},"collection_id":{"type":"string","description":"Every approved testimonial of this collection (col_...)","examples":["col_7Q2K9XH3AB"]},"all_approved":{"type":"boolean","description":"true for every approved testimonial of the site","default":false},"languages":{"type":"array","items":{"type":"string","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]},"description":"The target languages, from the languages the site offers. Empty means all of them","default":[]},"overwrite_edited":{"type":"boolean","description":"true replaces translations a member edited by hand. Default false, which leaves them alone","default":false}}}}}}},"get":{"operationId":"testimonial_translations_list","summary":"List the stored translations of a site","description":"One row per testimonial and language, most recently changed first, 25 a page. Filter by language, state, origin or testimonial_id. Works on every plan, so translations made before a downgrade can still be read.","tags":["Testimonial translations"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"language","in":"query","required":false,"schema":{"type":"string","description":"Only translations into this language","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]}},{"name":"state","in":"query","required":false,"schema":{"type":"string","description":"ready (stored), waiting (held at the quota) or out_of_date (the original changed since)","enum":["ready","waiting","out_of_date"]}},{"name":"origin","in":"query","required":false,"schema":{"type":"string","description":"machine (fetched) or edited (written or corrected by a member)","enum":["machine","edited"]}},{"name":"testimonial_id","in":"query","required":false,"schema":{"type":"string","description":"Only translations of this testimonial (tm_...)","examples":["tm_7Q2K9XH3AB"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"testimonial_id":{"type":"string","description":"The testimonial it translates (tm_...)"},"language":{"type":"string","description":"The language of the translation"},"body":{"anyOf":[{"type":"string","description":"The translated words. null while it waits for quota"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"The translated title, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The translated highlight, or null"},{"type":"null"}]},"origin":{"type":"string","description":"machine (fetched) or edited (written or corrected by a member)"},"state":{"type":"string","description":"ready, or waiting (held at the month's quota, continued on the 1st)"},"out_of_date":{"type":"boolean","description":"true when the original changed after this was made. It keeps showing until it is translated again"},"edited_by":{"anyOf":[{"type":"string","description":"The name of the member who edited it, or null"},{"type":"null"}]},"characters":{"type":"integer","description":"Characters that were sent to make it"},"updated_at":{"type":"string","format":"date-time","description":"When it was last changed"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_translations_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/translations/{testimonial_id}/{language}.json":{"delete":{"operationId":"testimonial_translations_delete","summary":"Remove one stored translation","description":"The testimonial is shown in its own words again wherever that language was used. Characters already spent on it are not returned. Works on every plan. Over MCP the tool changes nothing and responds with the page of the app where a person does it.","tags":["Testimonial translations"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"testimonial_id","in":"path","required":true,"description":"The testimonial the translation belongs to (tm_...), from testimonial_translations_list","schema":{"type":"string"}},{"name":"language","in":"path","required":true,"description":"The language of the translation to remove, as testimonial_translations_list returns it","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"testimonial_id":{"type":"string","description":"The testimonial it translates (tm_...)"},"language":{"type":"string","description":"The language of the translation"},"body":{"anyOf":[{"type":"string","description":"The translated words. null while it waits for quota"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"The translated title, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The translated highlight, or null"},{"type":"null"}]},"origin":{"type":"string","description":"machine (fetched) or edited (written or corrected by a member)"},"state":{"type":"string","description":"ready, or waiting (held at the month's quota, continued on the 1st)"},"out_of_date":{"type":"boolean","description":"true when the original changed after this was made. It keeps showing until it is translated again"},"edited_by":{"anyOf":[{"type":"string","description":"The name of the member who edited it, or null"},{"type":"null"}]},"characters":{"type":"integer","description":"Characters that were sent to make it"},"updated_at":{"type":"string","format":"date-time","description":"When it was last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"patch":{"operationId":"testimonial_translations_update","summary":"Write or correct one translation by hand","description":"The row is marked as edited, and a later run does not overwrite it unless overwrite_edited is sent. Nothing is fetched and nothing counts toward the quota. The original is never changed. Business and up (402 plan_limit elsewhere).","tags":["Testimonial translations"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"testimonial_id","in":"path","required":true,"description":"The testimonial the translation belongs to (tm_...)","schema":{"type":"string","examples":["tm_7Q2K9XH3AB"]}},{"name":"language","in":"path","required":true,"description":"The language of the translation","schema":{"type":"string","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"testimonial_id":{"type":"string","description":"The testimonial it translates (tm_...)"},"language":{"type":"string","description":"The language of the translation"},"body":{"anyOf":[{"type":"string","description":"The translated words. null while it waits for quota"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"The translated title, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The translated highlight, or null"},{"type":"null"}]},"origin":{"type":"string","description":"machine (fetched) or edited (written or corrected by a member)"},"state":{"type":"string","description":"ready, or waiting (held at the month's quota, continued on the 1st)"},"out_of_date":{"type":"boolean","description":"true when the original changed after this was made. It keeps showing until it is translated again"},"edited_by":{"anyOf":[{"type":"string","description":"The name of the member who edited it, or null"},{"type":"null"}]},"characters":{"type":"integer","description":"Characters that were sent to make it"},"updated_at":{"type":"string","format":"date-time","description":"When it was last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_translations_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"testimonial_id":{"type":"string","description":"The testimonial the translation belongs to (tm_...)","examples":["tm_7Q2K9XH3AB"]},"language":{"type":"string","description":"The language of the translation","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]},"body":{"type":"string","description":"The translated words"},"title":{"type":"string","description":"The translated title"},"highlight":{"type":"string","description":"The translated highlight"}},"required":["testimonial_id","language"]}}}}}},"/sites/{site_id}/testimonials/translations/estimate.json":{"get":{"operationId":"testimonial_translations_estimate","summary":"Count the characters a translation run would send, before running it","description":"Say which testimonials one way: testimonial_ids, collection_id or all_approved. The response gives the testimonials, the characters that would be sent, the characters already stored and what is left of the month. It states characters, never a price. Nothing is fetched.","tags":["Testimonial translations"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"testimonial_ids","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Up to 100 testimonials (tm_...). One of testimonial_ids, collection_id and all_approved","default":[]}},{"name":"collection_id","in":"query","required":false,"schema":{"type":"string","description":"Every approved testimonial of this collection (col_...)","examples":["col_7Q2K9XH3AB"]}},{"name":"all_approved","in":"query","required":false,"schema":{"type":"boolean","description":"true for every approved testimonial of the site","default":false}},{"name":"languages","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]},"description":"The target languages, from the languages the site offers. Empty means all of them","default":[]}},{"name":"overwrite_edited","in":"query","required":false,"schema":{"type":"boolean","description":"true counts translations a member edited by hand as well. Default false","default":false}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"testimonials":{"type":"integer","description":"Testimonials in the selection"},"languages":{"type":"array","items":{"type":"string"},"description":"The target languages"},"characters":{"type":"integer","description":"Characters that would be sent (or were queued)"},"stored_characters":{"type":"integer","description":"Characters of the selection that are already stored and will not be sent"},"pairs":{"type":"integer","description":"Translations to make, one per testimonial and language"},"quota":{"type":"integer","description":"The month's character quota"},"quota_used":{"type":"integer","description":"Characters used this month"},"quota_left":{"type":"integer","description":"Characters left this month"},"fits":{"type":"boolean","description":"false when the run is larger than what is left. The rest waits for the 1st"},"available":{"type":"boolean","description":"The plan includes translation (Business and up)"},"configured":{"type":"boolean","description":"Translation is set up at Privatus Analytics"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_translations_estimate","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/trash/permanent.json":{"delete":{"operationId":"testimonial_trash_delete_permanently","summary":"Delete up to 100 items in the trash for good","description":"This cannot be undone. confirm is the name of the item (the person's name for a testimonial) or its id for one item, and the name of the site for several. Only items in the trash are accepted.","tags":["Testimonial trash"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"anyOf":[{"type":"string","description":"The undo record id (blk_...). Null for a dry run and for delete_permanently"},{"type":"null"}]},"action":{"type":"string","description":"The action that ran"},"state":{"type":"string","description":"done, running (in the background), dry_run, undone, failed or expired"},"total":{"type":"integer","description":"How many testimonials the selection held"},"changed":{"type":"integer","description":"How many were changed"},"skipped":{"type":"integer","description":"How many were left as they were"},"skipped_reasons":{"type":"object","description":"Why, with a count each: already_in_state, waiting_for_allowance, in_trash, not_in_trash"},"undoable":{"type":"boolean","description":"It can be undone now"},"undo_until":{"anyOf":[{"type":"string","format":"date-time","description":"Until when it can be undone"},{"type":"null"}]},"reverted":{"anyOf":[{"type":"integer","description":"After an undo, how many went back"},{"type":"null"}]},"left":{"anyOf":[{"type":"object","description":"After an undo, how many were left alone and why: changed_since, deleted"},{"type":"null"}]},"created_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the run began"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"},"description":"Up to 100 ids of one kind (tm_, frm_, wdg_, wal_, col_ or tag_). All of them must be in the trash"},"confirm":{"type":"string","description":"One item: its name (the person's name for a testimonial) or its id. Several: the name of the site"}},"required":["ids"]}}}}}},"/sites/{site_id}/testimonials/trash/empty.json":{"delete":{"operationId":"testimonial_trash_empty","summary":"Delete everything in the trash for good","description":"This cannot be undone. confirm is the name of the site. Up to 100 items are deleted at once. A bigger trash is emptied in the background and the response has state running.","tags":["Testimonial trash"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"state":{"type":"string","description":"done, or running when the trash is being emptied in the background"},"total":{"type":"integer","description":"How many items were deleted, or are being deleted"},"counts":{"type":"object","description":"The number per kind, e.g. { \"testimonial\": 12, \"tag\": 1 }"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"string","description":"The name of the site"}}}}}}}},"/sites/{site_id}/testimonials/trash.json":{"get":{"operationId":"testimonial_trash_list","summary":"List what is in the trash, one kind at a time","description":"Responds with the items of one kind (testimonial by default) and, in meta.counts, how many of every kind are in the trash. Each item says what it returns to, what showed it, who trashed it and when it leaves.","tags":["Testimonial trash"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","description":"testimonial (the default), form, widget, wall, collection or tag","enum":["testimonial","form","widget","wall","collection","tag"],"default":"testimonial"}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Part of the name. For a testimonial: part of the person's name, the title or the words"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"trashed_desc (the default, the latest first) or leaving_first (what is deleted soonest)","enum":["trashed_desc","leaving_first"],"default":"trashed_desc"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The id of the item (tm_, frm_, wdg_, wal_, col_ or tag_)"},"kind":{"type":"string","description":"testimonial, form, widget, wall, collection or tag"},"name":{"anyOf":[{"type":"string","description":"The name of the item. For a testimonial the person's name, null when it has no person"},{"type":"null"}]},"excerpt":{"anyOf":[{"type":"string","description":"A testimonial only. The start of the words"},{"type":"null"}]},"was":{"type":"string","description":"What it returns to. A testimonial: pending, approved, rejected or waiting. A widget: installed or not_installed. A collection: manual or smart. A tag: applied or unused. A form or wall: live"},"used_by":{"type":"array","items":{"type":"object"},"description":"The widgets and walls that showed it, each { type, id, name }"},"trashed_at":{"type":"string","format":"date-time","description":"When it was moved to the trash"},"trashed_by":{"anyOf":[{"type":"string","description":"The name of the member who trashed it"},{"type":"null"}]},"leaves_at":{"type":"string","format":"date-time","description":"When it is deleted for good, 30 days after it was trashed"},"days_left":{"type":"integer","description":"Whole days until then"},"leaving_soon":{"type":"boolean","description":"true when 7 days or fewer are left"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_trash_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/trash/restore.json":{"post":{"operationId":"testimonial_trash_restore","summary":"Restore up to 100 items from the trash, exactly as they were","description":"The ids must be of one kind. Restoring testimonials responds with an undo id (data.id and meta.undo_id) that testimonial_undo_records_undo takes for 7 days. A restore never counts as a new testimonial.","tags":["Testimonial trash"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"anyOf":[{"type":"string","description":"The undo record id (blk_...). Null for a dry run and for delete_permanently"},{"type":"null"}]},"action":{"type":"string","description":"The action that ran"},"state":{"type":"string","description":"done, running (in the background), dry_run, undone, failed or expired"},"total":{"type":"integer","description":"How many testimonials the selection held"},"changed":{"type":"integer","description":"How many were changed"},"skipped":{"type":"integer","description":"How many were left as they were"},"skipped_reasons":{"type":"object","description":"Why, with a count each: already_in_state, waiting_for_allowance, in_trash, not_in_trash"},"undoable":{"type":"boolean","description":"It can be undone now"},"undo_until":{"anyOf":[{"type":"string","format":"date-time","description":"Until when it can be undone"},{"type":"null"}]},"reverted":{"anyOf":[{"type":"integer","description":"After an undo, how many went back"},{"type":"null"}]},"left":{"anyOf":[{"type":"object","description":"After an undo, how many were left alone and why: changed_since, deleted"},{"type":"null"}]},"created_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the run began"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_trash_restore","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"},"description":"Up to 100 ids of one kind (tm_, frm_, wdg_, wal_, col_ or tag_)"}},"required":["ids"]}}}}}},"/sites/{site_id}/testimonials/settings/undo.json":{"get":{"operationId":"testimonial_undo_records_list","summary":"List what was changed in the last 7 days and can be undone","description":"Newest first. Each record says what ran, who ran it, how many it changed and skipped and why, and until when it can be undone.","tags":["Testimonial undo list"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","description":"Only records in this state: running, done, failed, undone or expired","enum":["running","done","failed","undone","expired"]}},{"name":"action","in":"query","required":false,"schema":{"type":"string","description":"Only records of this action, e.g. approve, add_tags, trash, merge","enum":["approve","reject","mark_pending","add_tags","remove_tags","add_to_collection","remove_from_collection","set_property","pin","unpin","permalink_on","permalink_off","translate","export","trash","restore","merge","merge_people","apply_rules","import","make_images"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"anyOf":[{"type":"string","description":"The undo record id (blk_...). Null for a dry run and for delete_permanently"},{"type":"null"}]},"action":{"type":"string","description":"The action that ran"},"state":{"type":"string","description":"done, running (in the background), dry_run, undone, failed or expired"},"total":{"type":"integer","description":"How many testimonials the selection held"},"changed":{"type":"integer","description":"How many were changed"},"skipped":{"type":"integer","description":"How many were left as they were"},"skipped_reasons":{"type":"object","description":"Why, with a count each: already_in_state, waiting_for_allowance, in_trash, not_in_trash"},"undoable":{"type":"boolean","description":"It can be undone now"},"undo_until":{"anyOf":[{"type":"string","format":"date-time","description":"Until when it can be undone"},{"type":"null"}]},"reverted":{"anyOf":[{"type":"integer","description":"After an undo, how many went back"},{"type":"null"}]},"left":{"anyOf":[{"type":"object","description":"After an undo, how many were left alone and why: changed_since, deleted"},{"type":"null"}]},"created_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the run began"},{"type":"null"}]},"processed":{"type":"integer","description":"How many testimonials the run has gone through so far"},"by":{"anyOf":[{"type":"string","description":"The name of the member who ran it"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the run finished"},{"type":"null"}]},"undone_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was undone"},{"type":"null"}]}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_undo_records_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/settings/undo/{id}.json":{"get":{"operationId":"testimonial_undo_records_get","summary":"Read one undo record","description":"For a run in the background, state is running and processed says how far it is.","tags":["Testimonial undo list"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_undo_records_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"anyOf":[{"type":"string","description":"The undo record id (blk_...). Null for a dry run and for delete_permanently"},{"type":"null"}]},"action":{"type":"string","description":"The action that ran"},"state":{"type":"string","description":"done, running (in the background), dry_run, undone, failed or expired"},"total":{"type":"integer","description":"How many testimonials the selection held"},"changed":{"type":"integer","description":"How many were changed"},"skipped":{"type":"integer","description":"How many were left as they were"},"skipped_reasons":{"type":"object","description":"Why, with a count each: already_in_state, waiting_for_allowance, in_trash, not_in_trash"},"undoable":{"type":"boolean","description":"It can be undone now"},"undo_until":{"anyOf":[{"type":"string","format":"date-time","description":"Until when it can be undone"},{"type":"null"}]},"reverted":{"anyOf":[{"type":"integer","description":"After an undo, how many went back"},{"type":"null"}]},"left":{"anyOf":[{"type":"object","description":"After an undo, how many were left alone and why: changed_since, deleted"},{"type":"null"}]},"created_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the run began"},{"type":"null"}]},"processed":{"type":"integer","description":"How many testimonials the run has gone through so far"},"by":{"anyOf":[{"type":"string","description":"The name of the member who ran it"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the run finished"},{"type":"null"}]},"undone_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was undone"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_undo_records_get","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/settings/undo/{id}/undo.json":{"post":{"operationId":"testimonial_undo_records_undo","summary":"Undo a bulk action or a single change within 7 days","description":"Puts the earlier value back on everything the run changed. What was changed again since is left alone and counted in left. A merge of people or of duplicates is undone the same way. Over MCP an undo that would delete or move to the trash is not run (the undo of a restore, of a translate run and of a make images run): the tool responds with human_only and the page of the app where a person does it.","tags":["Testimonial undo list"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_undo_records_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"anyOf":[{"type":"string","description":"The undo record id (blk_...). Null for a dry run and for delete_permanently"},{"type":"null"}]},"action":{"type":"string","description":"The action that ran"},"state":{"type":"string","description":"done, running (in the background), dry_run, undone, failed or expired"},"total":{"type":"integer","description":"How many testimonials the selection held"},"changed":{"type":"integer","description":"How many were changed"},"skipped":{"type":"integer","description":"How many were left as they were"},"skipped_reasons":{"type":"object","description":"Why, with a count each: already_in_state, waiting_for_allowance, in_trash, not_in_trash"},"undoable":{"type":"boolean","description":"It can be undone now"},"undo_until":{"anyOf":[{"type":"string","format":"date-time","description":"Until when it can be undone"},{"type":"null"}]},"reverted":{"anyOf":[{"type":"integer","description":"After an undo, how many went back"},{"type":"null"}]},"left":{"anyOf":[{"type":"object","description":"After an undo, how many were left alone and why: changed_since, deleted"},{"type":"null"}]},"created_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the run began"},{"type":"null"}]},"processed":{"type":"integer","description":"How many testimonials the run has gone through so far"},"by":{"anyOf":[{"type":"string","description":"The name of the member who ran it"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the run finished"},{"type":"null"}]},"undone_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was undone"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_undo_records_undo","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials/overview.json":{"get":{"operationId":"testimonials_overview","summary":"Read the numbers of a site, what needs attention and what happened lately","description":"stats holds the five numbers of the Overview page: approved testimonials, pending, new this month, average rating and in use. attention lists what needs a decision with its count. activity is the latest 10 events and latest_approved testimonials the three most recently approved.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_overview","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/setup.json":{"get":{"operationId":"testimonials_setup_get","summary":"Get the setup checklist of a site","description":"Returns the items import, testimonials, approve, ask, widget and teammate, each with done and dismissed. An item is done from what the site holds, never by a click. hidden is true once every item is done or dismissed, which is when the Inbox stops showing the card.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string","description":"The site"},"items":{"type":"array","items":{"type":"object"},"description":"The checklist: key, done, dismissed"},"done_count":{"type":"integer","description":"Items done"},"total":{"type":"integer","description":"Items in all"},"finished":{"type":"boolean","description":"Every item is done"},"hidden":{"type":"boolean","description":"The card is no longer shown"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_setup_get","x-permission":"analytics.read"},"patch":{"operationId":"testimonials_setup_update","summary":"Dismiss one item of the setup checklist, or the whole card","description":"dismiss is one item key (import, testimonials, approve, ask, widget or teammate) or all for the whole card. Dismissing hides the item and never marks it done, and it cannot be brought back through the API.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string","description":"The site"},"items":{"type":"array","items":{"type":"object"},"description":"The checklist: key, done, dismissed"},"done_count":{"type":"integer","description":"Items done"},"total":{"type":"integer","description":"Items in all"},"finished":{"type":"boolean","description":"Every item is done"},"hidden":{"type":"boolean","description":"The card is no longer shown"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_setup_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dismiss":{"type":"string","description":"A checklist item (create, testimonials, approve, ask, widget, teammate) or all"}},"required":["dismiss"]}}}}}},"/sites/{site_id}/testimonials/{id}/approve.json":{"post":{"operationId":"testimonials_approve","summary":"Approve a testimonial so it may be shown","description":"A testimonial waiting for allowance cannot be approved: the server responds with 422 and the code waiting_for_allowance. The response carries meta.undo_id.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonials_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_approve","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials/bulk.json":{"post":{"operationId":"testimonials_bulk","summary":"Run one action over a selection of testimonials, or over everything a filter matches","description":"Send ids (up to 100, run at once, all or none) or filters with confirm_count (the whole result). More than 100 run in the background and the response has state running. Actions: approve, reject, mark_pending, pin, unpin, add_tags, remove_tags, add_to_collection, remove_from_collection, set_property, trash, restore. Each responds with an undo id that testimonials_bulk_undo takes for 7 days. delete_permanently is the one action that cannot be undone: it needs sites.manage and its response says undoable false. Over MCP the two actions that delete, trash and delete_permanently, are not run: the tool responds with human_only and the page of the app where a person does it, and every other action runs. Over the API, action export (with ids or filters, and an optional format of csv, json, ndjson or xlsx) changes nothing: it needs analytics.export and responds with 202 and the export to download.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"anyOf":[{"type":"string","description":"The undo record id (blk_...). Null for a dry run and for delete_permanently"},{"type":"null"}]},"action":{"type":"string","description":"The action that ran"},"state":{"type":"string","description":"done, running (in the background), dry_run, undone, failed or expired"},"total":{"type":"integer","description":"How many testimonials the selection held"},"changed":{"type":"integer","description":"How many were changed"},"skipped":{"type":"integer","description":"How many were left as they were"},"skipped_reasons":{"type":"object","description":"Why, with a count each: already_in_state, waiting_for_allowance, in_trash, not_in_trash"},"undoable":{"type":"boolean","description":"It can be undone now"},"undo_until":{"anyOf":[{"type":"string","format":"date-time","description":"Until when it can be undone"},{"type":"null"}]},"reverted":{"anyOf":[{"type":"integer","description":"After an undo, how many went back"},{"type":"null"}]},"left":{"anyOf":[{"type":"object","description":"After an undo, how many were left alone and why: changed_since, deleted"},{"type":"null"}]},"created_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the run began"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","description":"approve, reject, mark_pending, pin, unpin, add_tags, remove_tags, add_to_collection, remove_from_collection, set_property, trash, restore or delete_permanently","enum":["approve","reject","mark_pending","pin","unpin","add_tags","remove_tags","add_to_collection","remove_from_collection","set_property","trash","restore","permalink_on","permalink_off","translate","make_images","delete_permanently"]},"ids":{"type":"array","items":{"type":"string"},"description":"A selection of up to 100 testimonial ids (tm_...). Run at once, all or none. Send this or filters, not both"},"filters":{"type":"object","additionalProperties":true,"description":"The whole result: the same inputs as testimonials_list, e.g. {\"q\": \"rating:5 is:unused\"}. Needs confirm_count"},"confirm_count":{"type":"integer","description":"Required with filters. The number of testimonials you expect it to touch. If it has changed, nothing runs and the error count_changed says the new number"},"dry_run":{"type":"boolean","description":"true responds with what would change and what would be skipped, and changes nothing","default":false},"tags":{"type":"array","items":{"type":"string"},"description":"For add_tags and remove_tags. Names or ids. A new name is created when adding"},"collection_id":{"type":"string","description":"For add_to_collection and remove_from_collection. A manual collection (col_...)"},"property":{"type":"string","description":"For set_property. The key of the custom property"},"value":{"type":"string","description":"For set_property. An empty value clears it"},"languages":{"type":"array","items":{"type":"string"},"description":"For translate (Business and up). The target languages, from the languages the site offers. Empty means all of them. Call testimonial_translations_estimate first to see the characters it will send"},"confirm":{"type":"string","description":"For delete_permanently. The name of the site"}},"required":["action"]}}}}}},"/sites/{site_id}/testimonials/bulk/{id}/undo.json":{"post":{"operationId":"testimonials_bulk_undo","summary":"Undo a bulk action within 7 days","description":"Puts the earlier value back on every testimonial the run changed. One changed again since is left alone and counted in left. Over MCP an undo that would delete or move to the trash is not run (the undo of a restore, of a translate run and of a make images run): the tool responds with human_only and the page of the app where a person does it.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonials_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"anyOf":[{"type":"string","description":"The undo record id (blk_...). Null for a dry run and for delete_permanently"},{"type":"null"}]},"action":{"type":"string","description":"The action that ran"},"state":{"type":"string","description":"done, running (in the background), dry_run, undone, failed or expired"},"total":{"type":"integer","description":"How many testimonials the selection held"},"changed":{"type":"integer","description":"How many were changed"},"skipped":{"type":"integer","description":"How many were left as they were"},"skipped_reasons":{"type":"object","description":"Why, with a count each: already_in_state, waiting_for_allowance, in_trash, not_in_trash"},"undoable":{"type":"boolean","description":"It can be undone now"},"undo_until":{"anyOf":[{"type":"string","format":"date-time","description":"Until when it can be undone"},{"type":"null"}]},"reverted":{"anyOf":[{"type":"integer","description":"After an undo, how many went back"},{"type":"null"}]},"left":{"anyOf":[{"type":"object","description":"After an undo, how many were left alone and why: changed_since, deleted"},{"type":"null"}]},"created_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the run began"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_bulk_undo","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials.json":{"post":{"operationId":"testimonials_create","summary":"Add a testimonial by hand or through the API","description":"Stored through the one intake every route uses. It counts toward the plan's monthly allowance of new testimonials, and at the allowance the server responds with 422 and the code allowance_reached (only a customer's form submission is held as waiting instead). The same person saying the same words again is refused with the code duplicate unless allow_duplicate is true. The same external_id again returns the one already stored.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","description":"text (the default), video or audio","enum":["text","video","audio"],"default":"text"},"body":{"type":"string","description":"The words. Required for text, an optional caption for video and audio. Up to 10,000 characters"},"media_id":{"type":"string","description":"The uploaded video or audio file (med_...). Required for video and audio"},"image_media_ids":{"type":"array","items":{"type":"string"},"description":"Up to 4 uploaded images kept with the testimonial (med_...)","default":[]},"title":{"type":"string","description":"Optional, up to 200 characters"},"rating":{"type":"integer","description":"1 to 5. Leave out for no rating"},"highlight":{"type":"string","description":"The best sentence. Must be an exact part of body"},"person_id":{"type":"string","description":"A person already on the site (per_...). Or give the person fields"},"person_name":{"type":"string","description":"Required when there is no person_id"},"person_title":{"type":"string","description":"Their job title"},"person_company":{"type":"string","description":"Their company"},"person_company_url":{"type":"string","description":"The company's website"},"person_email":{"type":"string","description":"Their email. Never public. An address already on the site links to that person"},"person_social_url":{"type":"string","description":"A link to their profile"},"person_avatar_media_id":{"type":"string","description":"Their uploaded photo (med_...)"},"received_at":{"type":"string","format":"date-time","description":"When they gave it. Defaults to now. A day alone (2026-10-10) is that day by the site's clock"},"source_name":{"type":"string","description":"Where it came from, e.g. Email, Chat or a review site"},"source_url":{"type":"string","description":"A public link to it"},"language":{"type":"string","description":"Language code. Defaults to the site's language"},"status":{"type":"string","description":"pending (the default) or approved","enum":["pending","approved"],"default":"pending"},"tags":{"type":"array","items":{"type":"string"},"description":"Tag names or ids. A new name is created","default":[]},"collection_ids":{"type":"array","items":{"type":"string"},"description":"Manual collections to add it to (col_...)","default":[]},"properties":{"type":"object","additionalProperties":true,"description":"Custom property values by key, checked against the site's schema","default":{}},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed","default":false},"external_id":{"type":"string","description":"Your own id for it. The same one sent again returns the testimonial already stored"},"allow_duplicate":{"type":"boolean","description":"true saves it even though this person already said these words","default":false},"via":{"type":"string","description":"For an API token. api (the default) or extension, which stores the source as captured from a web page. Ignored for a signed-in member, whose source is always manual","enum":["api","extension"]}}}}}}},"get":{"operationId":"testimonials_list","summary":"List the testimonials of a site, filtered and sorted","description":"Three ways to say which, and they add up: the facet inputs (status, tag_id, has_video and the rest), q (the search box with its operators, for example rating:5 has:video tag:onboarding \"saved us\") and conditions with match (structured rows). Send facets as true for the live count behind every facet value in meta.facets. Nothing in the trash is listed unless trashed is true, which lists only the trash.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"view_id","in":"query","required":false,"schema":{"type":"string","description":"A saved view to apply (vw_...). Its filters, search text, sort, layout and columns are used, and any other input given beside it overrides the view's value for that input"}},{"name":"layout","in":"query","required":false,"schema":{"type":"string","description":"list, cards, board or highlights. Returned in meta.layout. It changes nothing about which testimonials are listed","enum":["list","cards","board","highlights"]}},{"name":"columns","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Columns of the list layout. Returned in meta.columns"}},{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"The search box. Words and \"quoted phrases\" search the text, title, person and company. Operators: status: kind: source: from: form: tag: collection: lang: has: is: consent: received: person: company: email: used: mentions: rating: and prop.<key>:. A comma means any of, a leading minus excludes, and terms are joined with and. Example: rating:5 has:video tag:onboarding \"saved us\""}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"received_desc (the default), received_asc, added_desc, added_asc, rating_desc, rating_asc, person_asc, length_desc, length_asc, used_desc, used_asc, or relevance (the default when q has words, and only allowed then)","enum":["received_desc","received_asc","added_desc","added_asc","rating_desc","rating_asc","person_asc","length_desc","length_asc","used_desc","used_asc","relevance"]}},{"name":"status","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["pending","approved","rejected"]},"description":"Any of pending, approved, rejected"}},{"name":"kind","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["text","video","audio"]},"description":"Any of text, video, audio"}},{"name":"rating","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["1","2","3","4","5","none"]},"description":"Any of 1 to 5 (as strings), and none for no rating"}},{"name":"source","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["form","import","manual","extension","api","migration"]},"description":"Any of form, import, manual, extension, api, migration"}},{"name":"source_name","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Platform or source names as stored, e.g. Google"}},{"name":"form_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Form ids (frm_...) or form names"}},{"name":"tag_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Tag ids (tag_...) or tag names"}},{"name":"tag_match","in":"query","required":false,"schema":{"type":"string","description":"any (the default) matches any of the tags, all needs every one","enum":["any","all"],"default":"any"}},{"name":"untagged","in":"query","required":false,"schema":{"type":"string","description":"yes for testimonials with no tag. With tag_id, either matches","enum":["yes"]}},{"name":"collection_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Collection ids (col_...) or names. A smart collection is read as its rules"}},{"name":"no_collection","in":"query","required":false,"schema":{"type":"string","description":"yes for testimonials in no manual collection","enum":["yes"]}},{"name":"language","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Language codes, e.g. de"}},{"name":"has_photo","in":"query","required":false,"schema":{"type":"string","description":"yes or no. The person has a photo","enum":["yes","no"]}},{"name":"has_video","in":"query","required":false,"schema":{"type":"string","description":"yes or no. A video file is attached","enum":["yes","no"]}},{"name":"has_image","in":"query","required":false,"schema":{"type":"string","description":"yes or no. An image is attached","enum":["yes","no"]}},{"name":"consent","in":"query","required":false,"schema":{"type":"string","description":"granted for consent on record, source_only for a source record","enum":["granted","source_only"]}},{"name":"consent_permission","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["show_name","show_photo","show_video","marketing"]},"description":"Permissions that must all be granted"}},{"name":"verified","in":"query","required":false,"schema":{"type":"string","description":"yes or no","enum":["yes","no"]}},{"name":"received","in":"query","required":false,"schema":{"type":"string","description":"A preset: today, 7d, 30d, 90d, this_year, last_year","enum":["today","7d","30d","90d","this_year","last_year"]}},{"name":"received_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day received (YYYY-MM-DD), on the site's clock"}},{"name":"received_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day received (YYYY-MM-DD)"}},{"name":"age","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["0_6m","6_12m","1_2y","over_2y"]},"description":"Freshness: any of 0_6m, 6_12m, 1_2y, over_2y"}},{"name":"person_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Person ids (per_...)"}},{"name":"company","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Company names or website hosts"}},{"name":"properties","in":"query","required":false,"schema":{"type":"object","additionalProperties":true,"description":"Custom property values by key, e.g. {\"plan\": [\"Team\"]}. A number range is \"10..50\", yes or no is \"yes\" or \"no\", and \"none\" means not filled"}},{"name":"usage","in":"query","required":false,"schema":{"type":"string","description":"unused, used, or used_3_plus","enum":["unused","used","used_3_plus"]}},{"name":"used_by","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Ids of the widgets (wdg_...) or walls (wal_...) that show it"}},{"name":"mention","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Recurring terms to search for"}},{"name":"has_highlight","in":"query","required":false,"schema":{"type":"string","description":"yes or no","enum":["yes","no"]}},{"name":"pinned","in":"query","required":false,"schema":{"type":"string","description":"yes or no","enum":["yes","no"]}},{"name":"edited","in":"query","required":false,"schema":{"type":"string","description":"yes or no","enum":["yes","no"]}},{"name":"waiting","in":"query","required":false,"schema":{"type":"string","description":"yes or no. Waiting for allowance","enum":["yes","no"]}},{"name":"duplicate","in":"query","required":false,"schema":{"type":"string","description":"yes or no. In the duplicates queue","enum":["yes","no"]}},{"name":"match","in":"query","required":false,"schema":{"type":"string","description":"How the conditions are joined, all (the default) or any","enum":["all","any"],"default":"all"}},{"name":"conditions","in":"query","required":false,"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Structured rows, each {\"field\", \"operator\", \"value\"}, e.g. [{\"field\": \"rating\", \"operator\": \"is_at_least\", \"value\": 4}]. Fields and operators are listed in the docs"}},{"name":"trashed","in":"query","required":false,"schema":{"type":"boolean","description":"true lists the trash and nothing else","default":false}},{"name":"facets","in":"query","required":false,"schema":{"type":"boolean","description":"true adds the live count behind every facet value as meta.facets","default":false}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/{id}/permanent.json":{"delete":{"operationId":"testimonials_delete","summary":"Delete a testimonial permanently, with its history, consent record and files","description":"This cannot be undone. It works on a testimonial in the trash or out of it, needs confirm and the sites.manage permission. Over MCP the tool deletes nothing and responds with the page where a person does it.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonials_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The id of what was deleted"},"deleted":{"type":"boolean","description":"Always true"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"string","description":"The name of the item (the person's name for a testimonial), or its id"}}}}}}}},"/sites/{site_id}/testimonials/{id}.json":{"delete":{"operationId":"testimonials_trash","summary":"Move a testimonial to the trash for 30 days","description":"The testimonial keeps its state, tags, collections and files, is shown nowhere and is deleted permanently after 30 days. testimonials_restore puts it back exactly as it was. The response carries meta.undo_id. Trashing one already in the trash changes nothing. Over MCP the tool changes nothing and responds with the page of the app where a person does it.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonials_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"testimonials_get","summary":"Get one testimonial with its person, files, consent record, tags and where it is used","description":"Returns one testimonial of the site by its id (tm_...), in the trash or not. person.email is null unless the caller holds content.write, and has_email says whether one is on record. media lists the files with their processing state. used_in lists every widget, wall and image that shows it.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonials_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_get","x-permission":"analytics.read"},"patch":{"operationId":"testimonials_update","summary":"Edit a testimonial. Changes to the words, title, rating and highlight are kept in its history","description":"Only the inputs sent are changed. A change to body, title, rating or highlight adds a version to the history with edit_note, and never changes the verified mark. rating null clears it. highlight must be an exact part of the words, and an empty one clears it. properties changes only the keys sent. add_tags and remove_tags take names or ids. State, pin and trash have their own tools. A testimonial in the trash cannot be edited.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonials_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","description":"The words. A change is kept in the history"},"title":{"type":"string","description":"Up to 200 characters. A change is kept in the history"},"rating":{"type":"integer","description":"1 to 5, or null to clear it. A change is kept in the history"},"highlight":{"type":"string","description":"An exact part of the words. Empty clears it"},"language":{"type":"string","description":"Language code"},"received_at":{"type":"string","format":"date-time","description":"When they gave it. A day alone (2026-10-10) is that day by the site's clock"},"source_name":{"type":"string","description":"The platform or place it came from"},"source_url":{"type":"string","description":"A public link to it"},"properties":{"type":"object","additionalProperties":true,"description":"Custom property values to change, by key. An empty value clears one"},"person_id":{"type":"string","description":"Link it to another person of the site (per_...)"},"edit_note":{"type":"string","description":"A line kept with the history entry, up to 280 characters"},"add_tags":{"type":"array","items":{"type":"string"},"description":"Tag names or ids to add. A name that is new is created"},"remove_tags":{"type":"array","items":{"type":"string"},"description":"Tag names or ids to remove"},"permalink":{"type":"boolean","description":"Switches its public page (/t/<tm_id>) on or off. The page responds only while the testimonial is approved, not in the trash and allowed by its consent record"}}}}}}}},"/sites/{site_id}/testimonials/facets.json":{"get":{"operationId":"testimonials_facets","summary":"Count the testimonials behind every filter value, for the same inputs as the list","description":"The shape of the library without reading any testimonial. Each facet counts its values with its own choice left out and every other filter applied. meta carries the total and the filter in words.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"view_id","in":"query","required":false,"schema":{"type":"string","description":"A saved view to apply (vw_...). Its filters, search text, sort, layout and columns are used, and any other input given beside it overrides the view's value for that input"}},{"name":"layout","in":"query","required":false,"schema":{"type":"string","description":"list, cards, board or highlights. Returned in meta.layout. It changes nothing about which testimonials are listed","enum":["list","cards","board","highlights"]}},{"name":"columns","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Columns of the list layout. Returned in meta.columns"}},{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"The search box. Words and \"quoted phrases\" search the text, title, person and company. Operators: status: kind: source: from: form: tag: collection: lang: has: is: consent: received: person: company: email: used: mentions: rating: and prop.<key>:. A comma means any of, a leading minus excludes, and terms are joined with and. Example: rating:5 has:video tag:onboarding \"saved us\""}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"received_desc (the default), received_asc, added_desc, added_asc, rating_desc, rating_asc, person_asc, length_desc, length_asc, used_desc, used_asc, or relevance (the default when q has words, and only allowed then)","enum":["received_desc","received_asc","added_desc","added_asc","rating_desc","rating_asc","person_asc","length_desc","length_asc","used_desc","used_asc","relevance"]}},{"name":"status","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["pending","approved","rejected"]},"description":"Any of pending, approved, rejected"}},{"name":"kind","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["text","video","audio"]},"description":"Any of text, video, audio"}},{"name":"rating","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["1","2","3","4","5","none"]},"description":"Any of 1 to 5 (as strings), and none for no rating"}},{"name":"source","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["form","import","manual","extension","api","migration"]},"description":"Any of form, import, manual, extension, api, migration"}},{"name":"source_name","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Platform or source names as stored, e.g. Google"}},{"name":"form_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Form ids (frm_...) or form names"}},{"name":"tag_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Tag ids (tag_...) or tag names"}},{"name":"tag_match","in":"query","required":false,"schema":{"type":"string","description":"any (the default) matches any of the tags, all needs every one","enum":["any","all"],"default":"any"}},{"name":"untagged","in":"query","required":false,"schema":{"type":"string","description":"yes for testimonials with no tag. With tag_id, either matches","enum":["yes"]}},{"name":"collection_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Collection ids (col_...) or names. A smart collection is read as its rules"}},{"name":"no_collection","in":"query","required":false,"schema":{"type":"string","description":"yes for testimonials in no manual collection","enum":["yes"]}},{"name":"language","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Language codes, e.g. de"}},{"name":"has_photo","in":"query","required":false,"schema":{"type":"string","description":"yes or no. The person has a photo","enum":["yes","no"]}},{"name":"has_video","in":"query","required":false,"schema":{"type":"string","description":"yes or no. A video file is attached","enum":["yes","no"]}},{"name":"has_image","in":"query","required":false,"schema":{"type":"string","description":"yes or no. An image is attached","enum":["yes","no"]}},{"name":"consent","in":"query","required":false,"schema":{"type":"string","description":"granted for consent on record, source_only for a source record","enum":["granted","source_only"]}},{"name":"consent_permission","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["show_name","show_photo","show_video","marketing"]},"description":"Permissions that must all be granted"}},{"name":"verified","in":"query","required":false,"schema":{"type":"string","description":"yes or no","enum":["yes","no"]}},{"name":"received","in":"query","required":false,"schema":{"type":"string","description":"A preset: today, 7d, 30d, 90d, this_year, last_year","enum":["today","7d","30d","90d","this_year","last_year"]}},{"name":"received_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day received (YYYY-MM-DD), on the site's clock"}},{"name":"received_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day received (YYYY-MM-DD)"}},{"name":"age","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["0_6m","6_12m","1_2y","over_2y"]},"description":"Freshness: any of 0_6m, 6_12m, 1_2y, over_2y"}},{"name":"person_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Person ids (per_...)"}},{"name":"company","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Company names or website hosts"}},{"name":"properties","in":"query","required":false,"schema":{"type":"object","additionalProperties":true,"description":"Custom property values by key, e.g. {\"plan\": [\"Team\"]}. A number range is \"10..50\", yes or no is \"yes\" or \"no\", and \"none\" means not filled"}},{"name":"usage","in":"query","required":false,"schema":{"type":"string","description":"unused, used, or used_3_plus","enum":["unused","used","used_3_plus"]}},{"name":"used_by","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Ids of the widgets (wdg_...) or walls (wal_...) that show it"}},{"name":"mention","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Recurring terms to search for"}},{"name":"has_highlight","in":"query","required":false,"schema":{"type":"string","description":"yes or no","enum":["yes","no"]}},{"name":"pinned","in":"query","required":false,"schema":{"type":"string","description":"yes or no","enum":["yes","no"]}},{"name":"edited","in":"query","required":false,"schema":{"type":"string","description":"yes or no","enum":["yes","no"]}},{"name":"waiting","in":"query","required":false,"schema":{"type":"string","description":"yes or no. Waiting for allowance","enum":["yes","no"]}},{"name":"duplicate","in":"query","required":false,"schema":{"type":"string","description":"yes or no. In the duplicates queue","enum":["yes","no"]}},{"name":"match","in":"query","required":false,"schema":{"type":"string","description":"How the conditions are joined, all (the default) or any","enum":["all","any"],"default":"all"}},{"name":"conditions","in":"query","required":false,"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Structured rows, each {\"field\", \"operator\", \"value\"}, e.g. [{\"field\": \"rating\", \"operator\": \"is_at_least\", \"value\": 4}]. Fields and operators are listed in the docs"}},{"name":"trashed","in":"query","required":false,"schema":{"type":"boolean","description":"true lists the trash and nothing else","default":false}},{"name":"facets","in":"query","required":false,"schema":{"type":"boolean","description":"true adds the live count behind every facet value as meta.facets","default":false}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_facets","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/{id}/highlight.json":{"patch":{"operationId":"testimonials_highlight","summary":"Mark the best sentence of a testimonial, or clear it","description":"highlight must be an exact part of the testimonial's words, or the server responds with 422. An empty highlight clears it. Each change is a version in the history.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonials_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_highlight","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"highlight":{"type":"string","description":"An exact part of the words. Empty clears the highlight","default":""}}}}}}}},"/sites/{site_id}/testimonials/{id}/history.json":{"get":{"operationId":"testimonials_history","summary":"List every version of a testimonial's words, title, rating and highlight","description":"Newest first. Version 1 is the testimonial as it was received and has no author. Each later version has the member who made it, when, the note they left and, for a restore, the version it put back. Paginated with page and per_page.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonials_list","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"number":{"type":"integer","description":"Version number. 1 is \"As received\""},"event":{"type":"string","description":"received, edited or restored"},"as_received":{"type":"boolean","description":"This is the version as it was received"},"body":{"anyOf":[{"type":"string","description":"The words at this version"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"The title at this version"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"The rating at this version"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The highlight at this version"},{"type":"null"}]},"edit_note":{"anyOf":[{"type":"string","description":"The note left with the edit"},{"type":"null"}]},"restored_from":{"anyOf":[{"type":"integer","description":"The version this one put back"},{"type":"null"}]},"edited_by":{"anyOf":[{"type":"string","description":"The member who made the change. Null for the giver"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When this version was made"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_history","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/{id}/pend.json":{"post":{"operationId":"testimonials_pend","summary":"Put a testimonial back to pending","description":"Takes an approved or rejected testimonial back to pending, so it is shown nowhere until it is decided again. The response carries meta.undo_id. A testimonial in the trash is refused with the code in_trash.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonials_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_pend","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials/{id}/pin.json":{"post":{"operationId":"testimonials_pin","summary":"Pin a testimonial so it is shown first, or unpin it","description":"A pinned testimonial is shown first wherever it is displayed. Send pinned false to unpin. The response carries meta.undo_id when something changed.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonials_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_pin","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"pinned":{"type":"boolean","description":"true to pin (the default), false to unpin","default":true}}}}}}}},"/sites/{site_id}/testimonials/{id}/reject.json":{"post":{"operationId":"testimonials_reject","summary":"Reject a testimonial. It is kept and shown nowhere","description":"The testimonial keeps everything it has and is shown nowhere. Rejecting one that is already rejected changes nothing. The response carries meta.undo_id, which testimonials_bulk_undo takes for 7 days. A testimonial in the trash is refused with the code in_trash.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonials_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_reject","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials/{id}/restore.json":{"post":{"operationId":"testimonials_restore","summary":"Restore a testimonial from the trash, exactly as it was","description":"Returns a trashed testimonial to its state, tags, collections and the places that showed it. It never counts as a new testimonial. One that is not in the trash is refused with the code not_in_trash.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonials_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_restore","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials/{id}/restore_version.json":{"post":{"operationId":"testimonials_restore_version","summary":"Put back the words, title, rating and highlight of an earlier version","description":"Nothing is removed from the history. The restore is a new version that says which one it came from. version 1 returns the testimonial to the words as received. An unknown version number is a 422.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonials_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_restore_version","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"integer","description":"The number of the version to put back. 1 is \"As received\""}},"required":["version"]}}}}}},"/sites/{site_id}/testimonials/showable.json":{"get":{"operationId":"testimonials_showable","summary":"List the testimonials the public may see, as the public may see them","description":"The newest approved testimonials of a site that may be shown in public, for a display of your own outside the widgets and walls. Each one carries only what its consent record allows: a person whose name may not be shown reads A customer, and a photo or a recording is left out unless it was allowed. A pending, rejected or trashed testimonial, or one waiting for the allowance, is never listed. There is no email in the response.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"How many to return, newest first. 12 by default, 50 at most","default":12}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"kind":{"type":"string","description":"text, video or audio. video and audio only when the recording may be shown"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"language":{"type":"string","description":"Language code of the words"},"date":{"anyOf":[{"type":"string","format":"date","description":"The day it was received"},{"type":"null"}]},"name":{"type":"string","description":"The person's name, or A customer when the name may not be shown"},"role":{"anyOf":[{"type":"string","description":"Title and company, when the name may be shown"},{"type":"null"}]},"photo_url":{"anyOf":[{"type":"string","description":"Address of the person's photo, when it may be shown"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The review platform it came from, if any"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Address of the original review, if any"},{"type":"null"}]},"verified":{"type":"boolean","description":"Whether the giver was verified"},"poster_url":{"anyOf":[{"type":"string","description":"Address of the still image of a video, when the recording may be shown"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Address of the testimonial's public page, when that page is on"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_showable","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/triage.json":{"get":{"operationId":"testimonials_triage","summary":"Get the next testimonial of a triage queue","description":"With no filter the queue is Pending, not waiting for allowance, oldest received first. With the inbox filters it is that result in its sort. Send after with the id just handled to get the one that follows. data is null when the queue is done. meta carries remaining and total.","tags":["Testimonials"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"view_id","in":"query","required":false,"schema":{"type":"string","description":"A saved view to apply (vw_...). Its filters, search text, sort, layout and columns are used, and any other input given beside it overrides the view's value for that input"}},{"name":"layout","in":"query","required":false,"schema":{"type":"string","description":"list, cards, board or highlights. Returned in meta.layout. It changes nothing about which testimonials are listed","enum":["list","cards","board","highlights"]}},{"name":"columns","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Columns of the list layout. Returned in meta.columns"}},{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"The search box. Words and \"quoted phrases\" search the text, title, person and company. Operators: status: kind: source: from: form: tag: collection: lang: has: is: consent: received: person: company: email: used: mentions: rating: and prop.<key>:. A comma means any of, a leading minus excludes, and terms are joined with and. Example: rating:5 has:video tag:onboarding \"saved us\""}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"received_desc (the default), received_asc, added_desc, added_asc, rating_desc, rating_asc, person_asc, length_desc, length_asc, used_desc, used_asc, or relevance (the default when q has words, and only allowed then)","enum":["received_desc","received_asc","added_desc","added_asc","rating_desc","rating_asc","person_asc","length_desc","length_asc","used_desc","used_asc","relevance"]}},{"name":"status","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["pending","approved","rejected"]},"description":"Any of pending, approved, rejected"}},{"name":"kind","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["text","video","audio"]},"description":"Any of text, video, audio"}},{"name":"rating","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["1","2","3","4","5","none"]},"description":"Any of 1 to 5 (as strings), and none for no rating"}},{"name":"source","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["form","import","manual","extension","api","migration"]},"description":"Any of form, import, manual, extension, api, migration"}},{"name":"source_name","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Platform or source names as stored, e.g. Google"}},{"name":"form_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Form ids (frm_...) or form names"}},{"name":"tag_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Tag ids (tag_...) or tag names"}},{"name":"tag_match","in":"query","required":false,"schema":{"type":"string","description":"any (the default) matches any of the tags, all needs every one","enum":["any","all"],"default":"any"}},{"name":"untagged","in":"query","required":false,"schema":{"type":"string","description":"yes for testimonials with no tag. With tag_id, either matches","enum":["yes"]}},{"name":"collection_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Collection ids (col_...) or names. A smart collection is read as its rules"}},{"name":"no_collection","in":"query","required":false,"schema":{"type":"string","description":"yes for testimonials in no manual collection","enum":["yes"]}},{"name":"language","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Language codes, e.g. de"}},{"name":"has_photo","in":"query","required":false,"schema":{"type":"string","description":"yes or no. The person has a photo","enum":["yes","no"]}},{"name":"has_video","in":"query","required":false,"schema":{"type":"string","description":"yes or no. A video file is attached","enum":["yes","no"]}},{"name":"has_image","in":"query","required":false,"schema":{"type":"string","description":"yes or no. An image is attached","enum":["yes","no"]}},{"name":"consent","in":"query","required":false,"schema":{"type":"string","description":"granted for consent on record, source_only for a source record","enum":["granted","source_only"]}},{"name":"consent_permission","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["show_name","show_photo","show_video","marketing"]},"description":"Permissions that must all be granted"}},{"name":"verified","in":"query","required":false,"schema":{"type":"string","description":"yes or no","enum":["yes","no"]}},{"name":"received","in":"query","required":false,"schema":{"type":"string","description":"A preset: today, 7d, 30d, 90d, this_year, last_year","enum":["today","7d","30d","90d","this_year","last_year"]}},{"name":"received_from","in":"query","required":false,"schema":{"type":"string","format":"date","description":"First day received (YYYY-MM-DD), on the site's clock"}},{"name":"received_to","in":"query","required":false,"schema":{"type":"string","format":"date","description":"Last day received (YYYY-MM-DD)"}},{"name":"age","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["0_6m","6_12m","1_2y","over_2y"]},"description":"Freshness: any of 0_6m, 6_12m, 1_2y, over_2y"}},{"name":"person_id","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Person ids (per_...)"}},{"name":"company","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Company names or website hosts"}},{"name":"properties","in":"query","required":false,"schema":{"type":"object","additionalProperties":true,"description":"Custom property values by key, e.g. {\"plan\": [\"Team\"]}. A number range is \"10..50\", yes or no is \"yes\" or \"no\", and \"none\" means not filled"}},{"name":"usage","in":"query","required":false,"schema":{"type":"string","description":"unused, used, or used_3_plus","enum":["unused","used","used_3_plus"]}},{"name":"used_by","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Ids of the widgets (wdg_...) or walls (wal_...) that show it"}},{"name":"mention","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Recurring terms to search for"}},{"name":"has_highlight","in":"query","required":false,"schema":{"type":"string","description":"yes or no","enum":["yes","no"]}},{"name":"pinned","in":"query","required":false,"schema":{"type":"string","description":"yes or no","enum":["yes","no"]}},{"name":"edited","in":"query","required":false,"schema":{"type":"string","description":"yes or no","enum":["yes","no"]}},{"name":"waiting","in":"query","required":false,"schema":{"type":"string","description":"yes or no. Waiting for allowance","enum":["yes","no"]}},{"name":"duplicate","in":"query","required":false,"schema":{"type":"string","description":"yes or no. In the duplicates queue","enum":["yes","no"]}},{"name":"match","in":"query","required":false,"schema":{"type":"string","description":"How the conditions are joined, all (the default) or any","enum":["all","any"],"default":"all"}},{"name":"conditions","in":"query","required":false,"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Structured rows, each {\"field\", \"operator\", \"value\"}, e.g. [{\"field\": \"rating\", \"operator\": \"is_at_least\", \"value\": 4}]. Fields and operators are listed in the docs"}},{"name":"trashed","in":"query","required":false,"schema":{"type":"boolean","description":"true lists the trash and nothing else","default":false}},{"name":"facets","in":"query","required":false,"schema":{"type":"boolean","description":"true adds the live count behind every facet value as meta.facets","default":false}},{"name":"after","in":"query","required":false,"schema":{"type":"string","description":"The id of the testimonial just handled or skipped (tm_...). The response is the one that follows it in the queue. Leave out for the first"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Testimonial id, e.g. tm_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"kind":{"type":"string","description":"text, video or audio"},"body":{"anyOf":[{"type":"string","description":"The words. May be empty for video and audio"},{"type":"null"}]},"title":{"anyOf":[{"type":"string","description":"Optional title"},{"type":"null"}]},"rating":{"anyOf":[{"type":"integer","description":"1 to 5, or null"},{"type":"null"}]},"highlight":{"anyOf":[{"type":"string","description":"The marked sentence, an exact part of body"},{"type":"null"}]},"language":{"type":"string","description":"Language code"},"status":{"type":"string","description":"pending, approved or rejected"},"pinned":{"type":"boolean","description":"Shown first wherever it is displayed"},"received_at":{"type":"string","format":"date-time","description":"When the person gave it"},"created_at":{"type":"string","format":"date-time","description":"When it was stored"},"source":{"type":"string","description":"form, import, manual, extension, api or migration"},"source_platform":{"anyOf":[{"type":"string","description":"The key of the platform it was imported from"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"The platform or place, as shown"},{"type":"null"}]},"source_url":{"anyOf":[{"type":"string","description":"Its public link"},{"type":"null"}]},"external_id":{"anyOf":[{"type":"string","description":"The source's own id, used for dedupe"},{"type":"null"}]},"verified":{"type":"boolean","description":"It arrived with evidence of who gave it"},"verified_reason":{"anyOf":[{"type":"string","description":"request_link or platform_profile"},{"type":"null"}]},"properties":{"type":"object","description":"Custom property values by key"},"waiting_for_allowance":{"type":"boolean","description":"Stored and held because the month's allowance of new testimonials was used. It cannot be approved until it is released, on the 1st or when the plan changes"},"edited":{"type":"boolean","description":"The words or title differ from \"As received\""},"possible_duplicate":{"type":"boolean","description":"It is in the duplicates queue"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Person id, e.g. per_7Q2K9XH3AB"},"name":{"type":"string","description":"Their name"},"title":{"anyOf":[{"type":"string","description":"Their job title"},{"type":"null"}]},"company":{"anyOf":[{"type":"string","description":"Their company"},{"type":"null"}]},"company_url":{"anyOf":[{"type":"string","description":"The company's website"},{"type":"null"}]},"social_url":{"anyOf":[{"type":"string","description":"A link to their profile"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","description":"Their email. Null unless the caller holds content.write. Never public"},{"type":"null"}]},"has_email":{"type":"boolean","description":"An email is on record"},"photo":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}},"description":"Their photo"},{"type":"null"}]},"testimonials_count":{"type":"integer","description":"Testimonials of theirs that are not in the trash"},"last_received_at":{"anyOf":[{"type":"string","format":"date-time","description":"When their newest testimonial was received"},{"type":"null"}]}},"description":"Who said it. The email is only returned to callers with content.write"},{"type":"null"}]},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"File id, e.g. med_7Q2K9XH3AB"},"kind":{"type":"string","description":"image, video or audio"},"role":{"type":"string","description":"recording, attachment, avatar, logo or share_image"},"state":{"type":"string","description":"uploading, processing, ready or failed"},"filename":{"anyOf":[{"type":"string","description":"The name of the uploaded file"},{"type":"null"}]},"content_type":{"anyOf":[{"type":"string","description":"The media type of the finished file"},{"type":"null"}]},"byte_size":{"anyOf":[{"type":"integer","description":"Size in bytes"},{"type":"null"}]},"duration_seconds":{"anyOf":[{"type":"integer","description":"Length of a video or audio file"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","description":"Width in pixels"},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","description":"Height in pixels"},{"type":"null"}]},"position":{"type":"integer","description":"Order among the files of a testimonial"},"error":{"anyOf":[{"type":"string","description":"Why processing failed, as a code: unreadable, too_long, too_large, unsupported_type, missing_file, fetch_failed, unsafe_url, processing_failed or abandoned"},{"type":"null"}]},"error_message":{"anyOf":[{"type":"string","description":"The same reason as a sentence"},{"type":"null"}]},"url":{"anyOf":[{"type":"string","description":"Where to load the file: the processed video or audio, or the image, on the media host. Null until it is ready"},{"type":"null"}]},"poster_url":{"anyOf":[{"type":"string","description":"The still picture of a video"},{"type":"null"}]},"thumbnail_url":{"anyOf":[{"type":"string","description":"A small version of an image"},{"type":"null"}]},"shareable":{"type":"boolean","description":"True when the address may be given to people outside the site (a file of an approved testimonial, a logo, a share image). The address itself is the same either way and is not signed"},"upload":{"anyOf":[{"type":"object","description":"Only in the response of testimonial_media_uploads_create: how to send the file. url, method and headers for one request, parts and part_size for a large file sent in pieces, expires_at, and max_seconds (the longest recording the plan takes)"},{"type":"null"}]}}},"description":"The files kept with it"},"consent":{"anyOf":[{"type":"object","properties":{"basis":{"type":"string","description":"consent (given on a form) or source (where it came from)"},"consent_text":{"anyOf":[{"type":"string","description":"The exact consent text the giver saw"},{"type":"null"}]},"show_name":{"type":"boolean","description":"May show the name"},"show_photo":{"type":"boolean","description":"May show the photo"},"show_video":{"type":"boolean","description":"May show the video"},"marketing":{"type":"boolean","description":"May be used in marketing"},"granted":{"type":"array","items":{"type":"string"},"description":"The permissions granted, as names"},"given_via":{"anyOf":[{"type":"string","description":"form or request_link"},{"type":"null"}]},"form_version":{"anyOf":[{"type":"integer","description":"The version of the form it was given on"},{"type":"null"}]},"reward_offered":{"type":"boolean","description":"A reward was offered for the submission"},"source":{"anyOf":[{"type":"string","description":"For a source record, the route it arrived by"},{"type":"null"}]},"source_name":{"anyOf":[{"type":"string","description":"For a source record, the platform or place"},{"type":"null"}]},"recorded_by":{"anyOf":[{"type":"string","description":"The member who added it, for a source record"},{"type":"null"}]},"recorded_at":{"type":"string","format":"date-time","description":"When it was recorded"}},"description":"The consent record, or the source record"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object"},"description":"Its tags (id, name, color)"},"collections":{"type":"array","items":{"type":"object"},"description":"The manual collections it is in (id, name)"},"used_in":{"type":"array","items":{"type":"object"},"description":"Every widget, wall and image that shows it (type, id, name)"},"used_count":{"type":"integer","description":"How many places show it"},"permalink":{"type":"boolean","description":"Its public page is switched on"},"permalink_url":{"anyOf":[{"type":"string","description":"The public page, while it is approved and switched on"},{"type":"null"}]},"form_id":{"anyOf":[{"type":"string","description":"The form it came through"},{"type":"null"}]},"request_id":{"anyOf":[{"type":"string","description":"The request it came through"},{"type":"null"}]},"import_source_id":{"anyOf":[{"type":"string","description":"The import source it came from"},{"type":"null"}]},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash. Null outside the trash"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonials_triage","x-permission":"analytics.read"}},"/sites/{site_id}/tracking/ingest_key.json":{"post":{"operationId":"tracking_ingest_key_rotate","summary":"Create or rotate the crawler log key (shown once)","description":"Creates a new secret crawler log key (it starts with pik_) for a site and replaces any existing key. The key authenticates uploads of server access logs for the AI crawlers report (POST /api/logs). Use it both to create the first key and to rotate. The new key works at once and the old one stops working at once, so deploy the new key right away to avoid 401s on log uploads. The full key is returned only in this response, in the key field, so store it in a secret store. Afterwards only a short prefix is kept and shown (prefix here, ingest_key_prefix on the site). Returns site_id, key and prefix. Requires sites.manage. Use tracking_ingest_key_revoke to remove the key without replacing it.","tags":["Tracking"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_id":{"type":"string","description":"Site id"},"key":{"type":"string","description":"The crawler log key. Shown once: store it now. Send it as a Bearer token to POST /api/logs"},"prefix":{"type":"string","description":"Key prefix shown in settings"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"delete":{"operationId":"tracking_ingest_key_revoke","summary":"Revoke the crawler log key","description":"Removes a site's crawler log key. From then on every log upload sent with that key is rejected with 401 until you create a new one with tracking_ingest_key_rotate. Browser tracking with the public site id is not affected. The key cannot be restored. Requires sites.manage. Returns the site object (see sites_get), where ingest_key_prefix is now null.","tags":["Tracking"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Site id used in the tracking snippet"},"workspace_id":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string"},"extra_domains":{"type":"array","items":{"type":"string"}},"multi_domain_mode":{"type":"string"},"timezone":{"type":"string"},"currency":{"type":"string"},"labels":{"type":"array","items":{"type":"string"}},"honor_dnt":{"type":"boolean"},"honor_gpc":{"type":"boolean"},"pii_scrubber":{"type":"boolean"},"redaction_rules":{"type":"array"},"allowed_params":{"type":"array","items":{"type":"string"}},"path_masks":{"type":"array"},"retention_months":{"anyOf":[{"type":"integer"},{"type":"null"}]},"bot_filtering":{"type":"boolean"},"traffic_rule_modes":{"type":"object"},"vitals_sample_rate":{"type":"integer"},"conversion_denominator":{"type":"string"},"public_dashboard":{"type":"boolean"},"public_indexable":{"type":"boolean"},"ingest_key_prefix":{"anyOf":[{"type":"string","description":"Start of the crawler log key"},{"type":"null"}]},"verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"first_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_event_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"domain_rating":{"anyOf":[{"type":"integer","description":"Domain Rating from 0 to 100, our own estimate of the strength of the domain's link profile. Null until the first check"},{"type":"null"}]},"snippet":{"type":"string","description":"HTML tracking snippet"},"favorite":{"type":"boolean","description":"Starred by you"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/tracking/verify.json":{"post":{"operationId":"tracking_verify","summary":"Check the tracker is installed on the site (script tag, site id, CSP and referrer policy)","description":"Fetches the site's page and checks that the Privatus Analytics tracking script is installed correctly, and marks the site as verified when the script with this site's id is found. By default it requests the homepage (https://domain/) and url can name another page, but only on the site's own domain, extra domains or their subdomains. The result (under data) has url, status (HTTP status), script_found, site_ids (every data-site id found on the page), installed (true when this site's id is among them), csp and csp_ok (whether the page's Content-Security-Policy lets the tracker load and send), referrer_policy and referrer_ok (a no-referrer policy means every visit shows as direct), and checked_at. It fetches over the public internet, reads at most 2 MB, and is rate limited per workspace and per host, so it responds with 429 when called too often. If the page is unreachable it returns a validation error. Use sites_setup_get to see whether events have arrived. Requires sites.manage.","tags":["Tracking"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"tracking_verify","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Page to fetch and check, a full http or https URL. Must be on the site's own domain, an extra domain or a subdomain of them. Defaults to https://<domain>/."}}}}}}}},"/sites/{site_id}/tracking/snippet.json":{"get":{"operationId":"tracking_snippet","summary":"Build the tracking snippet for chosen options","description":"Builds the HTML script tag to install tracking on a site and returns it with the site id as data.site_id and data.snippet. Choose this over sites_setup_get when you need to customize it, and use tracking_verify afterwards to check the live page. By default every tracker module is loaded and pageviews are automatic. modules narrows it to a subset of engage (time and scroll), auto (outbound links, downloads, forms, 404s), vitals (Web Vitals), clicks (click maps) and ask (on-site surveys). manual true disables the automatic pageview so you send them yourself. spa sets single-page-app navigation tracking to auto, history, hash or off. domains limits tracking to those hostnames, exclude lists path globs to skip, query_params lists extra query parameters to keep and mask lists client-side path masks written as /u/*->/u/:id. Nothing is saved, the snippet is generated from the inputs each time. Requires analytics.read.","tags":["Tracking"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"modules","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["engage","auto","vitals","clicks","ask"]},"description":"Tracker modules to load: engage (time and scroll), auto (outbound links, downloads, forms, 404s, counted as events), vitals (Web Vitals), clicks (click maps), ask (on-site surveys). All of them by default"}},{"name":"manual","in":"query","required":false,"schema":{"type":"boolean","description":"Turn off the automatic pageview","default":false}},{"name":"spa","in":"query","required":false,"schema":{"type":"string","description":"Single-page app navigation tracking, one of auto (default), history, hash or off.","enum":["auto","history","hash","off"],"default":"auto"}},{"name":"domains","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Only track on these hostnames","default":[]}},{"name":"exclude","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Path globs not to track, e.g. /admin/*","default":[]}},{"name":"query_params","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Extra query parameters to keep, e.g. page","default":[]}},{"name":"mask","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"description":"Client-side path masks, e.g. /u/*->/u/:id","default":[]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"tracking_snippet","x-permission":"analytics.read"}},"/sites/{site_id}/traffic_rules.json":{"post":{"operationId":"traffic_rules_create","summary":"Add a traffic rule","description":"Adds a pattern to one of the site's block or allow lists. list is one of hostnames, paths, referrers, countries, ip_ranges, user_agents or events. pattern uses * as a wildcard and matching is case-insensitive, for example /admin/*, a hostname, a referrer host such as spam.example, a two-letter country code (stored uppercase), a browser name with major version as the user agent is reduced (for example Chrome 120), or a custom event name. ip_ranges take an IPv4 or IPv6 address or CIDR (203.0.113.0/24), which must be valid. A pattern can exist once per list, and a site can have up to 500 rules. Whether the list blocks or allows matches depends on its mode, which defaults to block and is changed with sites_update. Matching hits are dropped at collection and not stored, and the rule applies within minutes to new hits only. Needs sites.manage. Needs the Pro plan or above (402 plan_limit otherwise).","tags":["Traffic rules"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Rule id"},"list":{"type":"string","description":"hostnames, paths, referrers, countries, ip_ranges, user_agents or events"},"pattern":{"type":"string","description":"Pattern (* wildcards, CIDR for ip_ranges)"},"label":{"anyOf":[{"type":"string"},{"type":"null"}]},"mode":{"type":"string","description":"block or allow (the mode of its list)"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"traffic_rules_create","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"list":{"type":"string","description":"Which list the pattern goes in: hostnames (the site hostname of the hit), paths (page path), referrers (referrer hostname), countries (two-letter code), ip_ranges (IPv4 or IPv6 address or CIDR), user_agents (browser name and major version, e.g. Chrome 120) or events (custom event name)","enum":["hostnames","paths","referrers","countries","ip_ranges","user_agents","events"]},"pattern":{"type":"string","description":"Value to match, up to 255 characters. * is a wildcard and matching is case-insensitive, e.g. /admin/*. ip_ranges take an IP or CIDR such as 203.0.113.0/24. countries take a two-letter ISO code such as DE (stored uppercase). A pattern can exist once per list","examples":["/admin/*"]},"label":{"type":"string","description":"Optional note for people, up to 100 characters, e.g. Office"}},"required":["list","pattern"]}}}}},"get":{"operationId":"traffic_rules_list","summary":"List traffic rules","description":"Lists the site's traffic rules, which are block or allow lists applied at collection time to decide which hits count. Each rule has id (a UUID for update and delete), list (hostnames, paths, referrers, countries, ip_ranges, user_agents or events), pattern, label (optional note), mode (block or allow, the mode of that whole list) and created_at. In block mode a hit matching any pattern of the list is dropped, in allow mode a hit matching none is dropped, and an empty list filters nothing. Filter with list. The mode of a list is not set here, it is set with sites_update using traffic_rule_modes. Use traffic_rules_test to check a sample hit. Needs analytics.read.","tags":["Traffic rules"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"list","in":"query","required":false,"schema":{"type":"string","description":"Only rules in this list: hostnames, paths, referrers, countries, ip_ranges, user_agents or events","enum":["hostnames","paths","referrers","countries","ip_ranges","user_agents","events"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Rule id"},"list":{"type":"string","description":"hostnames, paths, referrers, countries, ip_ranges, user_agents or events"},"pattern":{"type":"string","description":"Pattern (* wildcards, CIDR for ip_ranges)"},"label":{"anyOf":[{"type":"string"},{"type":"null"}]},"mode":{"type":"string","description":"block or allow (the mode of its list)"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"traffic_rules_list","x-permission":"analytics.read"}},"/sites/{site_id}/traffic_rules/{id}.json":{"delete":{"operationId":"traffic_rules_delete","summary":"Delete a traffic rule","description":"Deletes a traffic rule, found by its id from traffic_rules_list. Hits it was dropping are counted again from then on, and hits already dropped are gone for good. Note that deleting the last pattern of an allow-mode list makes that list stop filtering. Returns the deleted rule. Needs sites.manage.","tags":["Traffic rules"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by traffic_rules_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Rule id"},"list":{"type":"string","description":"hostnames, paths, referrers, countries, ip_ranges, user_agents or events"},"pattern":{"type":"string","description":"Pattern (* wildcards, CIDR for ip_ranges)"},"label":{"anyOf":[{"type":"string"},{"type":"null"}]},"mode":{"type":"string","description":"block or allow (the mode of its list)"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"traffic_rules_delete","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"patch":{"operationId":"traffic_rules_update","summary":"Change a traffic rule","description":"Changes the pattern or label of a traffic rule, found by its id from traffic_rules_list. Only inputs you send change. The list cannot be changed, delete and recreate the rule to move it to another list. The pattern must stay valid for its list (a CIDR for ip_ranges) and unique within it. Send an empty label to clear it. Applies to new hits only. Needs sites.manage. Needs the Pro plan or above (402 plan_limit otherwise).","tags":["Traffic rules"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by traffic_rules_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Rule id"},"list":{"type":"string","description":"hostnames, paths, referrers, countries, ip_ranges, user_agents or events"},"pattern":{"type":"string","description":"Pattern (* wildcards, CIDR for ip_ranges)"},"label":{"anyOf":[{"type":"string"},{"type":"null"}]},"mode":{"type":"string","description":"block or allow (the mode of its list)"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"traffic_rules_update","x-permission":"sites.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"pattern":{"type":"string","description":"New pattern, with the same format rules as the rule's list (a valid IP or CIDR for ip_ranges). Leave out to keep it"},"label":{"type":"string","description":"New note, up to 100 characters. Send an empty string to clear it"}}}}}}}},"/sites/{site_id}/traffic_rules/test.json":{"post":{"operationId":"traffic_rules_test","summary":"Test whether a hit would be counted with the site's current rules","description":"Dry run that tells you whether a sample hit would be counted under the site's current traffic rules. Nothing is stored. Send any of url (a full page URL, its host and path are checked), referrer (URL or hostname), country (two-letter code), ip (checked against ip_ranges, never stored), user_agent (a full User-Agent string, reduced to browser and major version) and event (a custom event name). Values you leave out are not checked. The result has counted (true if the hit would be recorded), blocked_by (the list that dropped it, or null), mode (block or allow for that list, or null) and values (the normalized values that were checked). Rules are read live so a new rule shows at once. Needs analytics.read. Needs the Pro plan or above (402 plan_limit otherwise).","tags":["Traffic rules"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"traffic_rules_test","x-permission":"analytics.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Full page URL of the sample hit, e.g. https://example.com/admin/users. Its host is checked against hostnames and its path against paths"},"referrer":{"type":"string","description":"Referrer URL or hostname of the sample hit, e.g. spam.example (www and m prefixes are ignored)"},"country":{"type":"string","description":"Two-letter ISO country code of the sample hit, e.g. US"},"ip":{"type":"string","description":"IP address to check against ip_ranges, e.g. 203.0.113.9. Not stored"},"user_agent":{"type":"string","description":"Full User-Agent string of the sample hit. It is reduced to browser name and major version before matching, like at collection"},"event":{"type":"string","description":"Custom event name of the sample hit, checked against the events list"}}}}}}}},"/sites/{site_id}/uptime.json":{"post":{"operationId":"uptime_checks_create","summary":"Add an uptime check for a site","description":"Adds an uptime check tied to one site. Use workspace_uptime_checks_create for a check that belongs to no site. kind decides the target. http checks the status code of url, keyword checks that the response body of url contains keyword, tcp connects to host and port, and dns checks that host resolves. Fields for other kinds are ignored. url defaults to the site's home page for http checks. expected_status (100 to 599, default 200), http_method (GET or HEAD) and timeout_seconds (1 to 30, default 20) apply to http and keyword checks. interval_seconds is the time between probes, it must be at least the plan minimum (Free 300, Pro 60, Business 30) and defaults to 300 or the minimum if that is higher. public true lets the check appear on a status page. Private and internal addresses are refused, and the plan limits the number of checks per workspace (Free 3, Pro 20, Business 100). The first probe runs within moments, status starts as pending. Needs the uptime.manage permission. Returns the check with id (upc_...).","tags":["Uptime"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Check id (upc_…)"},"workspace_id":{"type":"string"},"site_id":{"anyOf":[{"type":"string","description":"Site the check belongs to"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"http, keyword, tcp or dns"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"host":{"anyOf":[{"type":"string"},{"type":"null"}]},"port":{"anyOf":[{"type":"integer"},{"type":"null"}]},"keyword":{"anyOf":[{"type":"string"},{"type":"null"}]},"expected_status":{"type":"integer"},"http_method":{"type":"string"},"interval_seconds":{"type":"integer"},"timeout_seconds":{"type":"integer"},"status":{"type":"string","description":"up, down, pending or paused"},"enabled":{"type":"boolean"},"public":{"type":"boolean","description":"May appear on status pages"},"last_checked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_check_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_response_ms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"ssl_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"ssl_issuer":{"anyOf":[{"type":"string"},{"type":"null"}]},"domain_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"uptime":{"type":"object","description":"Uptime % for the last 24h, 7d and 30d: {\"24h\", \"7d\", \"30d\"}, each null until the first probe has run"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"uptime_checks_create","x-permission":"uptime.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Display name, max 100 characters. Defaults to the target hostname"},"kind":{"type":"string","description":"What to check. http requires a response with the expected status from url. keyword also requires keyword in the body. tcp connects to host and port. dns requires host to resolve","enum":["http","keyword","tcp","dns"],"default":"http"},"url":{"type":"string","description":"Full URL including https://, for http and keyword checks. Defaults to the site's home page for site checks. Private addresses are refused","examples":["https://example.com/health"]},"host":{"type":"string","description":"Hostname without scheme, like example.com, for tcp and dns checks. Private addresses are refused"},"port":{"type":"integer","description":"TCP port from 1 to 65535, required for tcp checks"},"keyword":{"type":"string","description":"Text the response body must contain, case sensitive, max 200 characters. Required for keyword checks"},"expected_status":{"type":"integer","description":"HTTP status code that counts as up, from 100 to 599. Default 200. For http and keyword checks","default":200},"http_method":{"type":"string","description":"HTTP method used to probe: GET (default) or HEAD. For http and keyword checks","enum":["GET","HEAD"],"default":"GET"},"interval_seconds":{"type":"integer","description":"Seconds between probes, from 30 to 86400, and at least your plan minimum (Free 300, Pro 60, Business 30). Default 300 or the plan minimum if higher"},"timeout_seconds":{"type":"integer","description":"Seconds before a probe counts as failed, from 1 to 30. Default 20","default":20},"public":{"type":"boolean","description":"Allow this check to be shown on public status pages. Default false","default":false}}}}}}},"get":{"operationId":"uptime_checks_list","summary":"List a site's uptime checks","description":"Lists the uptime checks of one site, including workspace wide checks that probe the site's domain or a subdomain of it. Sorted by name. Use workspace_uptime_checks_list for every check in the workspace. Filter with status (up, down, pending or paused) or query (part of name, url or host). Paginated with page and per_page (up to 100). Each check has id (upc_...), workspace_id, site_id (null for workspace wide checks), name, kind, url, host, port, keyword, expected_status, http_method, interval_seconds, timeout_seconds, status (up, down, pending or paused), enabled, public, last_checked_at, next_check_at, last_response_ms (milliseconds), ssl_expires_at, ssl_issuer, domain_expires_at, created_at and uptime (percentages for the last 24h, 7d and 30d, null until the first probe has run). Use uptime_checks_get for response times and incidents.","tags":["Uptime"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Only checks in this state: up, down, pending (no result yet) or paused","enum":["up","down","pending","paused"]}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Case insensitive text matched against name, url and host"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Check id (upc_…)"},"workspace_id":{"type":"string"},"site_id":{"anyOf":[{"type":"string","description":"Site the check belongs to"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"http, keyword, tcp or dns"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"host":{"anyOf":[{"type":"string"},{"type":"null"}]},"port":{"anyOf":[{"type":"integer"},{"type":"null"}]},"keyword":{"anyOf":[{"type":"string"},{"type":"null"}]},"expected_status":{"type":"integer"},"http_method":{"type":"string"},"interval_seconds":{"type":"integer"},"timeout_seconds":{"type":"integer"},"status":{"type":"string","description":"up, down, pending or paused"},"enabled":{"type":"boolean"},"public":{"type":"boolean","description":"May appear on status pages"},"last_checked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_check_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_response_ms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"ssl_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"ssl_issuer":{"anyOf":[{"type":"string"},{"type":"null"}]},"domain_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"uptime":{"type":"object","description":"Uptime % for the last 24h, 7d and 30d: {\"24h\", \"7d\", \"30d\"}, each null until the first probe has run"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"uptime_checks_list","x-permission":"analytics.read"}},"/uptime/checks/{id}.json":{"delete":{"operationId":"uptime_checks_delete","summary":"Delete an uptime check and its history","description":"Permanently deletes an uptime check with its results and incident history, and removes it from any status page that shows it. This cannot be undone. Use uptime_checks_pause to stop probing but keep history. The id comes from uptime_checks_list. Needs the uptime.manage permission. Returns the deleted check.","tags":["Uptime"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by uptime_checks_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Check id (upc_…)"},"workspace_id":{"type":"string"},"site_id":{"anyOf":[{"type":"string","description":"Site the check belongs to"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"http, keyword, tcp or dns"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"host":{"anyOf":[{"type":"string"},{"type":"null"}]},"port":{"anyOf":[{"type":"integer"},{"type":"null"}]},"keyword":{"anyOf":[{"type":"string"},{"type":"null"}]},"expected_status":{"type":"integer"},"http_method":{"type":"string"},"interval_seconds":{"type":"integer"},"timeout_seconds":{"type":"integer"},"status":{"type":"string","description":"up, down, pending or paused"},"enabled":{"type":"boolean"},"public":{"type":"boolean","description":"May appear on status pages"},"last_checked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_check_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_response_ms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"ssl_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"ssl_issuer":{"anyOf":[{"type":"string"},{"type":"null"}]},"domain_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"uptime":{"type":"object","description":"Uptime % for the last 24h, 7d and 30d: {\"24h\", \"7d\", \"30d\"}, each null until the first probe has run"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"uptime_checks_delete","x-permission":"uptime.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"uptime_checks_get","summary":"Get an uptime check: uptime 24h/7d/30d, response times and incidents","description":"Returns one uptime check with its history, not just its settings. Choose range (24h default, 7d or 30d) for the response time chart. The response has check (settings and live state, see uptime_checks_list), uptime (percent for 24h, 7d and 30d, null until the first probe has run), range, response_times (unit hour or day, labels as ISO 8601 times, and series of average response time in milliseconds per location with null for gaps) and incidents (the 50 most recent with started_at, resolved_at null while still open, duration_seconds, cause and failed_locations). Only successful probes count toward response times. The id comes from uptime_checks_list.","tags":["Uptime"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by uptime_checks_list","schema":{"type":"string"}},{"name":"range","in":"query","required":false,"schema":{"type":"string","description":"Window for the response time chart: 24h (default, hourly points), 7d (hourly points) or 30d (daily points)","enum":["24h","7d","30d"],"default":"24h"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"check":{"type":"object","properties":{"id":{"type":"string","description":"Check id (upc_…)"},"workspace_id":{"type":"string"},"site_id":{"anyOf":[{"type":"string","description":"Site the check belongs to"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"http, keyword, tcp or dns"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"host":{"anyOf":[{"type":"string"},{"type":"null"}]},"port":{"anyOf":[{"type":"integer"},{"type":"null"}]},"keyword":{"anyOf":[{"type":"string"},{"type":"null"}]},"expected_status":{"type":"integer"},"http_method":{"type":"string"},"interval_seconds":{"type":"integer"},"timeout_seconds":{"type":"integer"},"status":{"type":"string","description":"up, down, pending or paused"},"enabled":{"type":"boolean"},"public":{"type":"boolean","description":"May appear on status pages"},"last_checked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_check_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_response_ms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"ssl_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"ssl_issuer":{"anyOf":[{"type":"string"},{"type":"null"}]},"domain_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"uptime":{"type":"object","description":"Uptime % for the last 24h, 7d and 30d: {\"24h\", \"7d\", \"30d\"}, each null until the first probe has run"}}},"uptime":{"type":"object","description":"Uptime % for 24h, 7d and 30d"},"range":{"type":"string","description":"Window of response_times"},"response_times":{"type":"object","description":"Average response ms per bucket: {unit, labels, series: {location: [ms…]}}"},"incidents":{"type":"array","items":{"type":"object","properties":{"started_at":{"type":"string","format":"date-time"},"resolved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"duration_seconds":{"type":"integer","description":"So far, if still open"},"cause":{"anyOf":[{"type":"string","description":"Most common error, e.g. timeout or status_503"},{"type":"null"}]},"failed_locations":{"type":"array","items":{"type":"string"}}}}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"uptime_checks_get","x-permission":"analytics.read"},"patch":{"operationId":"uptime_checks_update","summary":"Change an uptime check","description":"Changes an uptime check. Only the inputs you send change. Rules and limits are the same as in uptime_checks_create (the interval must be at least the plan minimum, private addresses are refused). Changing kind clears the target fields that no longer apply. Changing interval_seconds schedules the next probe immediately. The id comes from uptime_checks_list. Needs the uptime.manage permission. Returns the updated check.","tags":["Uptime"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by uptime_checks_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Check id (upc_…)"},"workspace_id":{"type":"string"},"site_id":{"anyOf":[{"type":"string","description":"Site the check belongs to"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"http, keyword, tcp or dns"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"host":{"anyOf":[{"type":"string"},{"type":"null"}]},"port":{"anyOf":[{"type":"integer"},{"type":"null"}]},"keyword":{"anyOf":[{"type":"string"},{"type":"null"}]},"expected_status":{"type":"integer"},"http_method":{"type":"string"},"interval_seconds":{"type":"integer"},"timeout_seconds":{"type":"integer"},"status":{"type":"string","description":"up, down, pending or paused"},"enabled":{"type":"boolean"},"public":{"type":"boolean","description":"May appear on status pages"},"last_checked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_check_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_response_ms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"ssl_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"ssl_issuer":{"anyOf":[{"type":"string"},{"type":"null"}]},"domain_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"uptime":{"type":"object","description":"Uptime % for the last 24h, 7d and 30d: {\"24h\", \"7d\", \"30d\"}, each null until the first probe has run"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"uptime_checks_update","x-permission":"uptime.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New display name, max 100 characters"},"kind":{"type":"string","description":"New check type: http, keyword, tcp or dns. Fields that do not apply to the type are cleared","enum":["http","keyword","tcp","dns"]},"url":{"type":"string","description":"Full URL including https://, for http and keyword checks. Private addresses are refused","examples":["https://example.com/health"]},"host":{"type":"string","description":"Hostname without scheme, like example.com, for tcp and dns checks. Private addresses are refused"},"port":{"type":"integer","description":"TCP port from 1 to 65535, for tcp checks"},"keyword":{"type":"string","description":"Text the response body must contain, case sensitive, max 200 characters. For keyword checks"},"expected_status":{"type":"integer","description":"HTTP status code that counts as up, from 100 to 599. For http and keyword checks"},"http_method":{"type":"string","description":"HTTP method used to probe: GET or HEAD. For http and keyword checks","enum":["GET","HEAD"]},"interval_seconds":{"type":"integer","description":"Seconds between probes, from 30 to 86400, and at least your plan minimum (Free 300, Pro 60, Business 30)"},"timeout_seconds":{"type":"integer","description":"Seconds before a probe counts as failed, from 1 to 30"},"public":{"type":"boolean","description":"Allow this check to be shown on public status pages"}}}}}}}},"/uptime/checks/{id}/pause.json":{"post":{"operationId":"uptime_checks_pause","summary":"Pause an uptime check","description":"Pauses an uptime check so it is no longer probed. Any open incident is closed at once and no down or up alerts are sent while it is paused. History is kept and its status shows as paused. Resume it with uptime_checks_resume. The id comes from uptime_checks_list. Needs the uptime.manage permission. Returns the check.","tags":["Uptime"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by uptime_checks_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Check id (upc_…)"},"workspace_id":{"type":"string"},"site_id":{"anyOf":[{"type":"string","description":"Site the check belongs to"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"http, keyword, tcp or dns"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"host":{"anyOf":[{"type":"string"},{"type":"null"}]},"port":{"anyOf":[{"type":"integer"},{"type":"null"}]},"keyword":{"anyOf":[{"type":"string"},{"type":"null"}]},"expected_status":{"type":"integer"},"http_method":{"type":"string"},"interval_seconds":{"type":"integer"},"timeout_seconds":{"type":"integer"},"status":{"type":"string","description":"up, down, pending or paused"},"enabled":{"type":"boolean"},"public":{"type":"boolean","description":"May appear on status pages"},"last_checked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_check_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_response_ms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"ssl_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"ssl_issuer":{"anyOf":[{"type":"string"},{"type":"null"}]},"domain_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"uptime":{"type":"object","description":"Uptime % for the last 24h, 7d and 30d: {\"24h\", \"7d\", \"30d\"}, each null until the first probe has run"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"uptime_checks_pause","x-permission":"uptime.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/uptime/checks/{id}/resume.json":{"post":{"operationId":"uptime_checks_resume","summary":"Resume a paused uptime check","description":"Resumes a paused uptime check. It is probed on the next scheduler tick and its status is pending until the first result comes in. The id comes from uptime_checks_list. Needs the uptime.manage permission. Returns the check.","tags":["Uptime"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by uptime_checks_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Check id (upc_…)"},"workspace_id":{"type":"string"},"site_id":{"anyOf":[{"type":"string","description":"Site the check belongs to"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"http, keyword, tcp or dns"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"host":{"anyOf":[{"type":"string"},{"type":"null"}]},"port":{"anyOf":[{"type":"integer"},{"type":"null"}]},"keyword":{"anyOf":[{"type":"string"},{"type":"null"}]},"expected_status":{"type":"integer"},"http_method":{"type":"string"},"interval_seconds":{"type":"integer"},"timeout_seconds":{"type":"integer"},"status":{"type":"string","description":"up, down, pending or paused"},"enabled":{"type":"boolean"},"public":{"type":"boolean","description":"May appear on status pages"},"last_checked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_check_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_response_ms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"ssl_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"ssl_issuer":{"anyOf":[{"type":"string"},{"type":"null"}]},"domain_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"uptime":{"type":"object","description":"Uptime % for the last 24h, 7d and 30d: {\"24h\", \"7d\", \"30d\"}, each null until the first probe has run"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"uptime_checks_resume","x-permission":"uptime.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/uptime/probes.json":{"get":{"operationId":"uptime_probes_list","summary":"Probe datacenter, User-Agent and egress IP ranges (for allowlisting our uptime probes)","tags":["Uptime"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/uptime/probes/results.json":{"post":{"operationId":"uptime_probes_results","summary":"Submit results from an external probe agent (Bearer uptime probe token)","tags":["Uptime"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"check_id":{"type":"string"},"location":{"type":"string"},"ok":{"type":"boolean"},"status_code":{"type":"integer"},"response_ms":{"type":"integer"},"error":{"type":"string"},"checked_at":{"type":"string","format":"date-time"}}},"description":"Probe results: [{check_id, location, ok, status_code, response_ms, error, checked_at}]"}},"required":["results"]}}}},"security":[]}},"/workspaces/{workspace_id}/uptime.json":{"post":{"operationId":"workspace_uptime_checks_create","summary":"Add a workspace uptime check (not tied to a site)","description":"Adds an uptime check that belongs to the whole workspace instead of one site. Use uptime_checks_create to tie a check to a site. Inputs, plan limits and rules are the same, see uptime_checks_create. kind is http, keyword, tcp or dns and decides which of url, keyword, host and port apply. Because there is no site, an http check needs an explicit url. Callers limited to some sites cannot create workspace wide checks. Needs the workspace_id from workspaces_list and the uptime.manage permission. Returns the check with id (upc_...) and site_id null.","tags":["Uptime"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Check id (upc_…)"},"workspace_id":{"type":"string"},"site_id":{"anyOf":[{"type":"string","description":"Site the check belongs to"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"http, keyword, tcp or dns"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"host":{"anyOf":[{"type":"string"},{"type":"null"}]},"port":{"anyOf":[{"type":"integer"},{"type":"null"}]},"keyword":{"anyOf":[{"type":"string"},{"type":"null"}]},"expected_status":{"type":"integer"},"http_method":{"type":"string"},"interval_seconds":{"type":"integer"},"timeout_seconds":{"type":"integer"},"status":{"type":"string","description":"up, down, pending or paused"},"enabled":{"type":"boolean"},"public":{"type":"boolean","description":"May appear on status pages"},"last_checked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_check_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_response_ms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"ssl_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"ssl_issuer":{"anyOf":[{"type":"string"},{"type":"null"}]},"domain_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"uptime":{"type":"object","description":"Uptime % for the last 24h, 7d and 30d: {\"24h\", \"7d\", \"30d\"}, each null until the first probe has run"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"workspace_uptime_checks_create","x-permission":"uptime.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Display name, max 100 characters. Defaults to the target hostname"},"kind":{"type":"string","description":"What to check. http requires a response with the expected status from url. keyword also requires keyword in the body. tcp connects to host and port. dns requires host to resolve","enum":["http","keyword","tcp","dns"],"default":"http"},"url":{"type":"string","description":"Full URL including https://, for http and keyword checks. Defaults to the site's home page for site checks. Private addresses are refused","examples":["https://example.com/health"]},"host":{"type":"string","description":"Hostname without scheme, like example.com, for tcp and dns checks. Private addresses are refused"},"port":{"type":"integer","description":"TCP port from 1 to 65535, required for tcp checks"},"keyword":{"type":"string","description":"Text the response body must contain, case sensitive, max 200 characters. Required for keyword checks"},"expected_status":{"type":"integer","description":"HTTP status code that counts as up, from 100 to 599. Default 200. For http and keyword checks","default":200},"http_method":{"type":"string","description":"HTTP method used to probe: GET (default) or HEAD. For http and keyword checks","enum":["GET","HEAD"],"default":"GET"},"interval_seconds":{"type":"integer","description":"Seconds between probes, from 30 to 86400, and at least your plan minimum (Free 300, Pro 60, Business 30). Default 300 or the plan minimum if higher"},"timeout_seconds":{"type":"integer","description":"Seconds before a probe counts as failed, from 1 to 30. Default 20","default":20},"public":{"type":"boolean","description":"Allow this check to be shown on public status pages. Default false","default":false}}}}}}},"get":{"operationId":"workspace_uptime_checks_list","summary":"List all uptime checks in a workspace","description":"Lists every uptime check of a workspace, including checks tied to no site, sorted by name. A caller limited to some sites only sees checks of those sites. Use uptime_checks_list for the checks of one site. Filter with status (up, down, pending or paused) or query (part of name, url or host). Paginated with page and per_page (up to 100). Each item has the fields described in uptime_checks_list. Needs the workspace_id from workspaces_list.","tags":["Uptime"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Only checks in this state: up, down, pending (no result yet) or paused","enum":["up","down","pending","paused"]}},{"name":"query","in":"query","required":false,"schema":{"type":"string","description":"Case insensitive text matched against name, url and host"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Check id (upc_…)"},"workspace_id":{"type":"string"},"site_id":{"anyOf":[{"type":"string","description":"Site the check belongs to"},{"type":"null"}]},"name":{"type":"string"},"kind":{"type":"string","description":"http, keyword, tcp or dns"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"host":{"anyOf":[{"type":"string"},{"type":"null"}]},"port":{"anyOf":[{"type":"integer"},{"type":"null"}]},"keyword":{"anyOf":[{"type":"string"},{"type":"null"}]},"expected_status":{"type":"integer"},"http_method":{"type":"string"},"interval_seconds":{"type":"integer"},"timeout_seconds":{"type":"integer"},"status":{"type":"string","description":"up, down, pending or paused"},"enabled":{"type":"boolean"},"public":{"type":"boolean","description":"May appear on status pages"},"last_checked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_check_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_response_ms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"ssl_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"ssl_issuer":{"anyOf":[{"type":"string"},{"type":"null"}]},"domain_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"uptime":{"type":"object","description":"Uptime % for the last 24h, 7d and 30d: {\"24h\", \"7d\", \"30d\"}, each null until the first probe has run"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"workspace_uptime_checks_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/walls.json":{"post":{"operationId":"testimonial_walls_create","summary":"Create a Wall of Love","description":"A hosted page at https://privatus.page/w/<slug>. Anything left out starts from a default: the title Wall of Love, the masonry layout, the slug from the name.","tags":["Walls of Love"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Wall id, e.g. wal_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"slug":{"type":"string","description":"The last part of its address"},"url":{"type":"string","description":"The address of the page"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the wall's public page responds 404"},"language":{"type":"string","description":"Language code of the page's own words"},"layout":{"type":"string","description":"masonry, grid or list"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"show_logo":{"type":"boolean","description":"The logo is in the header"},"show_summary":{"type":"boolean","description":"The average rating and the count are in the header"},"indexable":{"type":"boolean","description":"The stored switch. Not used at present: a hosted wall always asks search engines not to list it"},"title":{"anyOf":[{"type":"string","description":"The heading"},{"type":"null"}]},"subtitle":{"anyOf":[{"type":"string","description":"The line under the heading"},{"type":"null"}]},"cta_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"cta_url":{"anyOf":[{"type":"string","description":"Where the button goes"},{"type":"null"}]},"seo_title":{"anyOf":[{"type":"string","description":"Title for search results"},{"type":"null"}]},"seo_description":{"anyOf":[{"type":"string","description":"Description for search results"},{"type":"null"}]},"collect_form_id":{"anyOf":[{"type":"string","description":"The form the Add yours button opens"},{"type":"null"}]},"share_image_id":{"anyOf":[{"type":"string","description":"The uploaded image shown when the page is shared"},{"type":"null"}]},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_walls_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Internal name, 1 to 100 characters. Required on create"},"source_kind":{"type":"string","description":"What feeds it: collection, view, tags or picked. Nothing is shown until one is chosen","enum":["collection","view","tags","picked"]},"collection_id":{"type":"string","description":"The collection that feeds it (col_...), manual or smart"},"view_id":{"type":"string","description":"The shared saved view that feeds it (vw_...)"},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it (tag_...)"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"Hand-picked testimonials (tm_...), in the order to show them, up to 100"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark","enum":["auto","light","dark"]},"font_size":{"type":"string","description":"small, medium or large","enum":["small","medium","large"]},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts","enum":["inherit","stars","hearts"]},"sort":{"type":"string","description":"source keeps the collection's or the picked order. newest, oldest and rating put pinned testimonials first","enum":["source","newest","oldest","rating"]},"tag_match":{"type":"string","description":"any (a testimonial with any of the tags) or all","enum":["any","all"]},"schema_type":{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization","enum":["Product","SoftwareApplication","Course","Book","Event","Recipe","LocalBusiness","Organization"]},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts. Default true"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown. Default true"},"show_company":{"type":"boolean","description":"Show the person's title and company. Default true"},"show_date":{"type":"boolean","description":"Show the date it was received. Default false"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address. Default true"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one. Default false"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason. Default true"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page. Default true"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on. Default false"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20. Default 8"},"accent_color":{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},"card_color":{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},"text_color":{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},"border_color":{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},"rating_color":{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},"background_color":{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},"radius":{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono","enum":["inherit_page","brand","system","system_serif","system_mono"]},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font","enum":["inherit_page","brand","system","system_serif","system_mono"]},"show_badge":{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},"custom_css":{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_name":{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},"per_view":{"type":"integer","description":"Carousel: cards in view, 1 to 4. Default 3"},"autoplay":{"type":"boolean","description":"Carousel: move by itself. A pause button is then always shown. Default false"},"interval_seconds":{"type":"integer","description":"Carousel and single quote: seconds per step, 3 to 15. Default 6"},"arrows":{"type":"boolean","description":"Carousel: previous and next buttons. Default true"},"dots":{"type":"boolean","description":"Carousel: position dots. Default true"},"loop":{"type":"boolean","description":"Carousel: go back to the start after the last card. Default true"},"columns":{"type":"integer","description":"Grid (1 to 5) and masonry (2 to 5): columns at full width. Default 3"},"gap":{"type":"string","description":"Grid and masonry: space between cards, small, medium or large","enum":["small","medium","large"]},"equal_height":{"type":"boolean","description":"Grid: cards of one row share a height. Default false"},"load_more":{"type":"boolean","description":"Grid, masonry and list: show a Load more button. Default true"},"page_size":{"type":"integer","description":"Grid, masonry and list: cards before Load more, 3 to 30. Default 9"},"avatar_position":{"type":"string","description":"List: the person left of the words, or top","enum":["left","top"]},"dividers":{"type":"boolean","description":"List: lines between testimonials in place of boxes. Default true"},"size":{"type":"string","description":"Single quote: medium, large or extra_large","enum":["medium","large","extra_large"]},"align":{"type":"string","description":"Single quote: left or center","enum":["left","center"]},"rotate":{"type":"boolean","description":"Single quote: step through up to 5 testimonials. Default false"},"rows":{"type":"integer","description":"Marquee: rows, 1 to 3. Default 1"},"speed":{"type":"string","description":"Marquee: slow, medium or fast","enum":["slow","medium","fast"]},"direction":{"type":"string","description":"Marquee: left or right","enum":["left","right"]},"avatars":{"type":"integer","description":"Avatar strip: faces shown, 1 to 8. Default 5"},"text":{"type":"string","description":"Avatar strip and rating badge: the line of text, up to 80 characters. {count} and {average} are filled in from the testimonials"},"link_url":{"type":"string","description":"Avatar strip and rating badge: an https address the whole thing links to"},"shape":{"type":"string","description":"Rating badge: compact or wide","enum":["compact","wide"]},"position":{"type":"string","description":"Corner popup: bottom_left or bottom_right","enum":["bottom_left","bottom_right"]},"delay_seconds":{"type":"integer","description":"Corner popup: seconds before the first one, 0 to 60. Default 5"},"display_seconds":{"type":"integer","description":"Corner popup: seconds each one stays, 4 to 30. Default 8"},"hide_on_phones":{"type":"boolean","description":"Corner popup: not shown on a narrow screen. Default false"},"slug":{"type":"string","description":"The address is /w/<slug>. 3 to 60 characters: a to z, 0 to 9 and hyphens. Unique across Privatus Analytics. The default comes from the name"},"layout":{"type":"string","description":"masonry (the default), grid or list","enum":["masonry","grid","list"]},"language":{"type":"string","description":"One of the site's languages: the page's own words","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]},"title":{"type":"string","description":"The heading, up to 120 characters. Default Wall of Love"},"subtitle":{"type":"string","description":"The line under the heading, up to 300 characters"},"cta_label":{"type":"string","description":"Text of the button, up to 40 characters"},"cta_url":{"type":"string","description":"Where the button goes. Must be https"},"seo_title":{"type":"string","description":"Title for search results, up to 70 characters. The default is the title"},"seo_description":{"type":"string","description":"Description for search results, up to 160 characters. The default is the subtitle"},"show_logo":{"type":"boolean","description":"Show the site's logo in the header. Default true"},"show_summary":{"type":"boolean","description":"Show the average rating and the count, computed from the wall's testimonials. Default true"},"indexable":{"type":"boolean","description":"Stored with the wall and not used at present: a hosted wall always asks search engines not to list it, whatever this is"},"collect_form_id":{"type":"string","description":"A form (frm_...) that an Add yours button opens. Empty for none"},"share_image_id":{"type":"string","description":"An uploaded image (med_...) shown when the page is shared. Empty uses the logo"}}}}}}},"get":{"operationId":"testimonial_walls_list","summary":"List the Walls of Love of a site","description":"Every Wall of Love of the site that is not in the trash, with its address, what feeds it and how many testimonials it shows. Use q to search by name or slug and sort to order by name or by newest.","tags":["Walls of Love"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"Searches the name and the slug"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"name (the default) or created","enum":["name","created"],"default":"name"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Wall id, e.g. wal_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"slug":{"type":"string","description":"The last part of its address"},"url":{"type":"string","description":"The address of the page"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the wall's public page responds 404"},"language":{"type":"string","description":"Language code of the page's own words"},"layout":{"type":"string","description":"masonry, grid or list"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"show_logo":{"type":"boolean","description":"The logo is in the header"},"show_summary":{"type":"boolean","description":"The average rating and the count are in the header"},"indexable":{"type":"boolean","description":"The stored switch. Not used at present: a hosted wall always asks search engines not to list it"},"title":{"anyOf":[{"type":"string","description":"The heading"},{"type":"null"}]},"subtitle":{"anyOf":[{"type":"string","description":"The line under the heading"},{"type":"null"}]},"cta_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"cta_url":{"anyOf":[{"type":"string","description":"Where the button goes"},{"type":"null"}]},"seo_title":{"anyOf":[{"type":"string","description":"Title for search results"},{"type":"null"}]},"seo_description":{"anyOf":[{"type":"string","description":"Description for search results"},{"type":"null"}]},"collect_form_id":{"anyOf":[{"type":"string","description":"The form the Add yours button opens"},{"type":"null"}]},"share_image_id":{"anyOf":[{"type":"string","description":"The uploaded image shown when the page is shared"},{"type":"null"}]},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_walls_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/walls/{id}.json":{"delete":{"operationId":"testimonial_walls_trash","summary":"Move a wall to the trash","description":"Its page responds that it has been taken down until it is restored, and an embedded copy renders nothing. Restoring brings it back at the same address. It is deleted for good after 30 days. Over MCP the tool changes nothing and responds with the page of the app where a person does it.","tags":["Walls of Love"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_walls_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Wall id, e.g. wal_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"slug":{"type":"string","description":"The last part of its address"},"url":{"type":"string","description":"The address of the page"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the wall's public page responds 404"},"language":{"type":"string","description":"Language code of the page's own words"},"layout":{"type":"string","description":"masonry, grid or list"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"show_logo":{"type":"boolean","description":"The logo is in the header"},"show_summary":{"type":"boolean","description":"The average rating and the count are in the header"},"indexable":{"type":"boolean","description":"The stored switch. Not used at present: a hosted wall always asks search engines not to list it"},"title":{"anyOf":[{"type":"string","description":"The heading"},{"type":"null"}]},"subtitle":{"anyOf":[{"type":"string","description":"The line under the heading"},{"type":"null"}]},"cta_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"cta_url":{"anyOf":[{"type":"string","description":"Where the button goes"},{"type":"null"}]},"seo_title":{"anyOf":[{"type":"string","description":"Title for search results"},{"type":"null"}]},"seo_description":{"anyOf":[{"type":"string","description":"Description for search results"},{"type":"null"}]},"collect_form_id":{"anyOf":[{"type":"string","description":"The form the Add yours button opens"},{"type":"null"}]},"share_image_id":{"anyOf":[{"type":"string","description":"The uploaded image shown when the page is shared"},{"type":"null"}]},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"testimonial_walls_get","summary":"Get one wall with every setting","description":"Everything the builder stores: the address (/w/<slug>), the header and the button, the layout, what feeds the wall, what each card shows, the style, and the search engine settings. A wall in the trash responds with 404.","tags":["Walls of Love"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_walls_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Wall id, e.g. wal_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"slug":{"type":"string","description":"The last part of its address"},"url":{"type":"string","description":"The address of the page"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the wall's public page responds 404"},"language":{"type":"string","description":"Language code of the page's own words"},"layout":{"type":"string","description":"masonry, grid or list"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"show_logo":{"type":"boolean","description":"The logo is in the header"},"show_summary":{"type":"boolean","description":"The average rating and the count are in the header"},"indexable":{"type":"boolean","description":"The stored switch. Not used at present: a hosted wall always asks search engines not to list it"},"title":{"anyOf":[{"type":"string","description":"The heading"},{"type":"null"}]},"subtitle":{"anyOf":[{"type":"string","description":"The line under the heading"},{"type":"null"}]},"cta_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"cta_url":{"anyOf":[{"type":"string","description":"Where the button goes"},{"type":"null"}]},"seo_title":{"anyOf":[{"type":"string","description":"Title for search results"},{"type":"null"}]},"seo_description":{"anyOf":[{"type":"string","description":"Description for search results"},{"type":"null"}]},"collect_form_id":{"anyOf":[{"type":"string","description":"The form the Add yours button opens"},{"type":"null"}]},"share_image_id":{"anyOf":[{"type":"string","description":"The uploaded image shown when the page is shared"},{"type":"null"}]},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_walls_get","x-permission":"analytics.read"},"patch":{"operationId":"testimonial_walls_update","summary":"Change a wall","description":"Only the inputs sent change. A changed slug leaves the old address redirecting.","tags":["Walls of Love"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_walls_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Wall id, e.g. wal_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"slug":{"type":"string","description":"The last part of its address"},"url":{"type":"string","description":"The address of the page"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the wall's public page responds 404"},"language":{"type":"string","description":"Language code of the page's own words"},"layout":{"type":"string","description":"masonry, grid or list"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"show_logo":{"type":"boolean","description":"The logo is in the header"},"show_summary":{"type":"boolean","description":"The average rating and the count are in the header"},"indexable":{"type":"boolean","description":"The stored switch. Not used at present: a hosted wall always asks search engines not to list it"},"title":{"anyOf":[{"type":"string","description":"The heading"},{"type":"null"}]},"subtitle":{"anyOf":[{"type":"string","description":"The line under the heading"},{"type":"null"}]},"cta_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"cta_url":{"anyOf":[{"type":"string","description":"Where the button goes"},{"type":"null"}]},"seo_title":{"anyOf":[{"type":"string","description":"Title for search results"},{"type":"null"}]},"seo_description":{"anyOf":[{"type":"string","description":"Description for search results"},{"type":"null"}]},"collect_form_id":{"anyOf":[{"type":"string","description":"The form the Add yours button opens"},{"type":"null"}]},"share_image_id":{"anyOf":[{"type":"string","description":"The uploaded image shown when the page is shared"},{"type":"null"}]},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_walls_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Internal name, 1 to 100 characters. Required on create"},"source_kind":{"type":"string","description":"What feeds it: collection, view, tags or picked. Nothing is shown until one is chosen","enum":["collection","view","tags","picked"]},"collection_id":{"type":"string","description":"The collection that feeds it (col_...), manual or smart"},"view_id":{"type":"string","description":"The shared saved view that feeds it (vw_...)"},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it (tag_...)"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"Hand-picked testimonials (tm_...), in the order to show them, up to 100"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark","enum":["auto","light","dark"]},"font_size":{"type":"string","description":"small, medium or large","enum":["small","medium","large"]},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts","enum":["inherit","stars","hearts"]},"sort":{"type":"string","description":"source keeps the collection's or the picked order. newest, oldest and rating put pinned testimonials first","enum":["source","newest","oldest","rating"]},"tag_match":{"type":"string","description":"any (a testimonial with any of the tags) or all","enum":["any","all"]},"schema_type":{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization","enum":["Product","SoftwareApplication","Course","Book","Event","Recipe","LocalBusiness","Organization"]},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts. Default true"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown. Default true"},"show_company":{"type":"boolean","description":"Show the person's title and company. Default true"},"show_date":{"type":"boolean","description":"Show the date it was received. Default false"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address. Default true"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one. Default false"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason. Default true"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page. Default true"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on. Default false"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20. Default 8"},"accent_color":{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},"card_color":{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},"text_color":{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},"border_color":{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},"rating_color":{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},"background_color":{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},"radius":{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono","enum":["inherit_page","brand","system","system_serif","system_mono"]},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font","enum":["inherit_page","brand","system","system_serif","system_mono"]},"show_badge":{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},"custom_css":{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_name":{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},"per_view":{"type":"integer","description":"Carousel: cards in view, 1 to 4. Default 3"},"autoplay":{"type":"boolean","description":"Carousel: move by itself. A pause button is then always shown. Default false"},"interval_seconds":{"type":"integer","description":"Carousel and single quote: seconds per step, 3 to 15. Default 6"},"arrows":{"type":"boolean","description":"Carousel: previous and next buttons. Default true"},"dots":{"type":"boolean","description":"Carousel: position dots. Default true"},"loop":{"type":"boolean","description":"Carousel: go back to the start after the last card. Default true"},"columns":{"type":"integer","description":"Grid (1 to 5) and masonry (2 to 5): columns at full width. Default 3"},"gap":{"type":"string","description":"Grid and masonry: space between cards, small, medium or large","enum":["small","medium","large"]},"equal_height":{"type":"boolean","description":"Grid: cards of one row share a height. Default false"},"load_more":{"type":"boolean","description":"Grid, masonry and list: show a Load more button. Default true"},"page_size":{"type":"integer","description":"Grid, masonry and list: cards before Load more, 3 to 30. Default 9"},"avatar_position":{"type":"string","description":"List: the person left of the words, or top","enum":["left","top"]},"dividers":{"type":"boolean","description":"List: lines between testimonials in place of boxes. Default true"},"size":{"type":"string","description":"Single quote: medium, large or extra_large","enum":["medium","large","extra_large"]},"align":{"type":"string","description":"Single quote: left or center","enum":["left","center"]},"rotate":{"type":"boolean","description":"Single quote: step through up to 5 testimonials. Default false"},"rows":{"type":"integer","description":"Marquee: rows, 1 to 3. Default 1"},"speed":{"type":"string","description":"Marquee: slow, medium or fast","enum":["slow","medium","fast"]},"direction":{"type":"string","description":"Marquee: left or right","enum":["left","right"]},"avatars":{"type":"integer","description":"Avatar strip: faces shown, 1 to 8. Default 5"},"text":{"type":"string","description":"Avatar strip and rating badge: the line of text, up to 80 characters. {count} and {average} are filled in from the testimonials"},"link_url":{"type":"string","description":"Avatar strip and rating badge: an https address the whole thing links to"},"shape":{"type":"string","description":"Rating badge: compact or wide","enum":["compact","wide"]},"position":{"type":"string","description":"Corner popup: bottom_left or bottom_right","enum":["bottom_left","bottom_right"]},"delay_seconds":{"type":"integer","description":"Corner popup: seconds before the first one, 0 to 60. Default 5"},"display_seconds":{"type":"integer","description":"Corner popup: seconds each one stays, 4 to 30. Default 8"},"hide_on_phones":{"type":"boolean","description":"Corner popup: not shown on a narrow screen. Default false"},"slug":{"type":"string","description":"The address is /w/<slug>. 3 to 60 characters: a to z, 0 to 9 and hyphens. Unique across Privatus Analytics. The default comes from the name"},"layout":{"type":"string","description":"masonry (the default), grid or list","enum":["masonry","grid","list"]},"language":{"type":"string","description":"One of the site's languages: the page's own words","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]},"title":{"type":"string","description":"The heading, up to 120 characters. Default Wall of Love"},"subtitle":{"type":"string","description":"The line under the heading, up to 300 characters"},"cta_label":{"type":"string","description":"Text of the button, up to 40 characters"},"cta_url":{"type":"string","description":"Where the button goes. Must be https"},"seo_title":{"type":"string","description":"Title for search results, up to 70 characters. The default is the title"},"seo_description":{"type":"string","description":"Description for search results, up to 160 characters. The default is the subtitle"},"show_logo":{"type":"boolean","description":"Show the site's logo in the header. Default true"},"show_summary":{"type":"boolean","description":"Show the average rating and the count, computed from the wall's testimonials. Default true"},"indexable":{"type":"boolean","description":"Stored with the wall and not used at present: a hosted wall always asks search engines not to list it, whatever this is"},"collect_form_id":{"type":"string","description":"A form (frm_...) that an Add yours button opens. Empty for none"},"share_image_id":{"type":"string","description":"An uploaded image (med_...) shown when the page is shared. Empty uses the logo"}}}}}}}},"/sites/{site_id}/testimonials/walls/{id}/duplicate.json":{"post":{"operationId":"testimonial_walls_duplicate","summary":"Copy a wall under a new name and address","description":"Makes a copy with a new id, the name ending in \"copy\" and a slug of its own, so it has its own address. The original and its address are not changed.","tags":["Walls of Love"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_walls_list","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Wall id, e.g. wal_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"slug":{"type":"string","description":"The last part of its address"},"url":{"type":"string","description":"The address of the page"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the wall's public page responds 404"},"language":{"type":"string","description":"Language code of the page's own words"},"layout":{"type":"string","description":"masonry, grid or list"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"show_logo":{"type":"boolean","description":"The logo is in the header"},"show_summary":{"type":"boolean","description":"The average rating and the count are in the header"},"indexable":{"type":"boolean","description":"The stored switch. Not used at present: a hosted wall always asks search engines not to list it"},"title":{"anyOf":[{"type":"string","description":"The heading"},{"type":"null"}]},"subtitle":{"anyOf":[{"type":"string","description":"The line under the heading"},{"type":"null"}]},"cta_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"cta_url":{"anyOf":[{"type":"string","description":"Where the button goes"},{"type":"null"}]},"seo_title":{"anyOf":[{"type":"string","description":"Title for search results"},{"type":"null"}]},"seo_description":{"anyOf":[{"type":"string","description":"Description for search results"},{"type":"null"}]},"collect_form_id":{"anyOf":[{"type":"string","description":"The form the Add yours button opens"},{"type":"null"}]},"share_image_id":{"anyOf":[{"type":"string","description":"The uploaded image shown when the page is shared"},{"type":"null"}]},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_walls_duplicate","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Name of the copy. The default adds (copy)"},"slug":{"type":"string","description":"Slug of the copy. The default comes from its name"}}}}}}}},"/sites/{site_id}/testimonials/walls/{id}/embed.json":{"get":{"operationId":"testimonial_walls_embed","summary":"Get the link to a wall and the code to place it inside another page","description":"The public address of the wall, and the script, frame and plain link snippets that place it inside another page. The snippets never change when the wall is edited.","tags":["Walls of Love"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_walls_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"wall_id":{"type":"string","description":"The wall"},"url":{"type":"string","description":"The address of the page"},"script":{"type":"string","description":"One element and the loader script: the wall inside another page, with its header"},"script_bare":{"type":"string","description":"The same without the header and the call to action"},"iframe":{"type":"string","description":"Frame code: the cards without the header"},"fragment_url":{"type":"string","description":"The address the loader fetches"},"loader_url":{"type":"string","description":"The address of the loader script"},"showing":{"type":"integer","description":"How many testimonials qualify right now"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_walls_embed","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/walls/{id}/restore.json":{"post":{"operationId":"testimonial_walls_restore","summary":"Restore a wall from the trash","description":"Takes a wall out of the trash. Its page responds again at the same address, and every embedded copy shows it again without a change to the code that was pasted.","tags":["Walls of Love"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_walls_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Wall id, e.g. wal_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"name":{"type":"string","description":"Internal name"},"slug":{"type":"string","description":"The last part of its address"},"url":{"type":"string","description":"The address of the page"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the wall's public page responds 404"},"language":{"type":"string","description":"Language code of the page's own words"},"layout":{"type":"string","description":"masonry, grid or list"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"show_logo":{"type":"boolean","description":"The logo is in the header"},"show_summary":{"type":"boolean","description":"The average rating and the count are in the header"},"indexable":{"type":"boolean","description":"The stored switch. Not used at present: a hosted wall always asks search engines not to list it"},"title":{"anyOf":[{"type":"string","description":"The heading"},{"type":"null"}]},"subtitle":{"anyOf":[{"type":"string","description":"The line under the heading"},{"type":"null"}]},"cta_label":{"anyOf":[{"type":"string","description":"Text of the button"},{"type":"null"}]},"cta_url":{"anyOf":[{"type":"string","description":"Where the button goes"},{"type":"null"}]},"seo_title":{"anyOf":[{"type":"string","description":"Title for search results"},{"type":"null"}]},"seo_description":{"anyOf":[{"type":"string","description":"Description for search results"},{"type":"null"}]},"collect_form_id":{"anyOf":[{"type":"string","description":"The form the Add yours button opens"},{"type":"null"}]},"share_image_id":{"anyOf":[{"type":"string","description":"The uploaded image shown when the page is shared"},{"type":"null"}]},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_walls_restore","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/workspaces/{workspace_id}/warehouses.json":{"post":{"operationId":"warehouse_destinations_create","summary":"Add a warehouse destination","description":"Adds a warehouse destination that receives each day's raw events (Business plan only). Daily at 02:00 UTC the previous UTC day is uploaded, the first run is at the next 02:00 UTC, and a failed run is retried an hour later. kind must be given and decides the required settings. s3 (also GCS, R2 and MinIO through endpoint) needs bucket, access_key_id and secret_access_key, with optional region, prefix and endpoint (https, public hosts only). bigquery needs service_account_json, dataset and table, with optional project_id. snowflake needs account, user, private_key (PEM RSA), database, schema and table, with optional warehouse and role. azure needs sas_url (an https blob container SAS link with write permission), with optional prefix. Secrets (secret_access_key, service_account_json, private_key, sas_url) are write only and are never returned. site_ids limits the sites (pa_... ids), empty means every site, and a member or token limited to some sites must name them. Event properties are only sent when marked safe to export (see event_properties_list). Needs the workspace.manage permission. Returns the destination with id (whd_...), a masked target and configured (the names of the filled in settings).","tags":["Warehouse sync"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Destination id, e.g. whd_7Q2K9XH3AB"},"kind":{"type":"string","description":"s3, bigquery, snowflake or azure"},"name":{"type":"string"},"target":{"type":"string","description":"Where data goes: s3://bucket/prefix, project.dataset.table, account/database.schema.table or the Azure container"},"configured":{"type":"array","items":{"type":"string"},"description":"Setting names that are filled in (values are never returned)"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Sites sent (pa_…). Empty means all sites"},"schedule":{"type":"string","description":"daily: 02:00 UTC, sends the previous UTC day"},"schema_version":{"type":"string","description":"Row schema sent"},"last_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Display name, max 100 characters, like Data lake"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Ids of the sites to send, like pa_7Q2K9XH3AB (from sites_list). Empty sends every site. Required for callers limited to some sites"},"bucket":{"type":"string","description":"s3 only: bucket name, required for s3"},"region":{"type":"string","description":"s3: region, e.g. us-east-1 (auto for R2)"},"prefix":{"type":"string","description":"s3 and azure: folder path prefix inside the bucket or container, like privatus/events"},"endpoint":{"type":"string","description":"s3: https endpoint for S3-compatible storage (GCS interoperability, R2, MinIO)"},"access_key_id":{"type":"string","description":"s3 only: access key id, required for s3"},"secret_access_key":{"type":"string","description":"s3 only: secret access key, required for s3. Write only, blank keeps the stored key on update"},"service_account_json":{"type":"string","description":"bigquery only: full service account JSON key text with BigQuery Data Editor access, required for bigquery. Write only, blank keeps the stored key on update"},"project_id":{"type":"string","description":"bigquery: project id (default: from the key)"},"dataset":{"type":"string","description":"bigquery only: dataset id, required for bigquery"},"table":{"type":"string","description":"bigquery and snowflake: table name, required. Snowflake may use database.schema.table"},"account":{"type":"string","description":"snowflake only: account identifier like xy12345.us-east-1 or myorg-myaccount, required for snowflake"},"user":{"type":"string","description":"snowflake only: user name that authenticates with the private key, required for snowflake"},"private_key":{"type":"string","description":"snowflake only: PEM encoded RSA private key, required for snowflake. Write only, blank keeps the stored key on update"},"database":{"type":"string","description":"snowflake only: database name, required for snowflake"},"schema":{"type":"string","description":"snowflake only: schema name, required for snowflake"},"warehouse":{"type":"string","description":"snowflake: virtual warehouse"},"role":{"type":"string","description":"snowflake: role (optional)"},"sas_url":{"type":"string","description":"azure only: https blob container SAS URL on a blob.core.windows.net host with create and write permission, required for azure. Write only, blank keeps the stored value on update"},"kind":{"type":"string","description":"Destination type, cannot be changed later. s3 (also GCS, R2 and MinIO through endpoint), bigquery, snowflake or azure","enum":["s3","bigquery","snowflake","azure"]}},"required":["kind"]}}}}},"get":{"operationId":"warehouse_destinations_list","summary":"List warehouse destinations","description":"Lists the warehouse destinations of a workspace sorted by name, optionally only one kind (s3, bigquery, snowflake or azure). A member or token limited to some sites only sees destinations whose sites are all among theirs, and destinations that send every site are hidden from them. Paginated with page and per_page (up to 100). Each item has the fields described in warehouse_destinations_get. Needs the workspace_id from workspaces_list and the workspace.manage permission.","tags":["Warehouse sync"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","description":"Only destinations of this kind","enum":["s3","bigquery","snowflake","azure"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Destination id, e.g. whd_7Q2K9XH3AB"},"kind":{"type":"string","description":"s3, bigquery, snowflake or azure"},"name":{"type":"string"},"target":{"type":"string","description":"Where data goes: s3://bucket/prefix, project.dataset.table, account/database.schema.table or the Azure container"},"configured":{"type":"array","items":{"type":"string"},"description":"Setting names that are filled in (values are never returned)"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Sites sent (pa_…). Empty means all sites"},"schedule":{"type":"string","description":"daily: 02:00 UTC, sends the previous UTC day"},"schema_version":{"type":"string","description":"Row schema sent"},"last_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"warehouse_destinations_list","x-permission":"workspace.manage"}},"/warehouses/{id}.json":{"delete":{"operationId":"warehouse_destinations_delete","summary":"Delete a warehouse destination","description":"Deletes a warehouse destination so nothing more is sent. Data that was already uploaded stays in your bucket or warehouse, and this cannot be undone, although you can add the destination again (history is not resent automatically). Any manual sync still queued is not recalled. The id comes from warehouse_destinations_list. Needs the workspace.manage permission. Returns the deleted destination.","tags":["Warehouse sync"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by warehouse_destinations_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Destination id, e.g. whd_7Q2K9XH3AB"},"kind":{"type":"string","description":"s3, bigquery, snowflake or azure"},"name":{"type":"string"},"target":{"type":"string","description":"Where data goes: s3://bucket/prefix, project.dataset.table, account/database.schema.table or the Azure container"},"configured":{"type":"array","items":{"type":"string"},"description":"Setting names that are filled in (values are never returned)"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Sites sent (pa_…). Empty means all sites"},"schedule":{"type":"string","description":"daily: 02:00 UTC, sends the previous UTC day"},"schema_version":{"type":"string","description":"Row schema sent"},"last_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"warehouse_destinations_get","summary":"Get a warehouse destination (no secrets)","description":"Returns one warehouse destination without credentials. Fields are id (whd_...), kind (s3, bigquery, snowflake or azure), name, target (a masked summary like s3://bucket/prefix), configured (names of the settings that are filled in, secrets show only by name), site_ids (empty means every site), schedule (daily), schema_version (the row layout sent), last_run_at, next_run_at, last_error (null when the last run worked) and created_at. The id comes from warehouse_destinations_list. Check last_error after warehouse_destinations_sync to see how a sync went.","tags":["Warehouse sync"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by warehouse_destinations_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Destination id, e.g. whd_7Q2K9XH3AB"},"kind":{"type":"string","description":"s3, bigquery, snowflake or azure"},"name":{"type":"string"},"target":{"type":"string","description":"Where data goes: s3://bucket/prefix, project.dataset.table, account/database.schema.table or the Azure container"},"configured":{"type":"array","items":{"type":"string"},"description":"Setting names that are filled in (values are never returned)"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Sites sent (pa_…). Empty means all sites"},"schedule":{"type":"string","description":"daily: 02:00 UTC, sends the previous UTC day"},"schema_version":{"type":"string","description":"Row schema sent"},"last_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"warehouse_destinations_get","x-permission":"workspace.manage"},"patch":{"operationId":"warehouse_destinations_update","summary":"Update a warehouse destination (blank secrets are kept)","description":"Changes a warehouse destination (Business plan only). Only the inputs you send change and the kind cannot be changed. A blank secret keeps the stored value, so you can edit other settings without sending credentials again. Settings are validated for the destination's kind as in warehouse_destinations_create. Sending site_ids replaces the list of sites. When the target changes (another bucket, dataset, table, database or similar) the progress of unfinished days starts over, so those days are sent again to the new place. The id comes from warehouse_destinations_list. Needs the workspace.manage permission. Returns the updated destination.","tags":["Warehouse sync"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by warehouse_destinations_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Destination id, e.g. whd_7Q2K9XH3AB"},"kind":{"type":"string","description":"s3, bigquery, snowflake or azure"},"name":{"type":"string"},"target":{"type":"string","description":"Where data goes: s3://bucket/prefix, project.dataset.table, account/database.schema.table or the Azure container"},"configured":{"type":"array","items":{"type":"string"},"description":"Setting names that are filled in (values are never returned)"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Sites sent (pa_…). Empty means all sites"},"schedule":{"type":"string","description":"daily: 02:00 UTC, sends the previous UTC day"},"schema_version":{"type":"string","description":"Row schema sent"},"last_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Display name, e.g. Data lake"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Ids of the sites to send, like pa_7Q2K9XH3AB (from sites_list). Empty sends every site. Required for callers limited to some sites"},"bucket":{"type":"string","description":"s3 only: bucket name, required for s3"},"region":{"type":"string","description":"s3: region, e.g. us-east-1 (auto for R2)"},"prefix":{"type":"string","description":"s3 and azure: folder path prefix inside the bucket or container, like privatus/events"},"endpoint":{"type":"string","description":"s3: https endpoint for S3-compatible storage (GCS interoperability, R2, MinIO)"},"access_key_id":{"type":"string","description":"s3 only: access key id, required for s3"},"secret_access_key":{"type":"string","description":"s3 only: secret access key, required for s3. Write only, blank keeps the stored key on update"},"service_account_json":{"type":"string","description":"bigquery only: full service account JSON key text with BigQuery Data Editor access, required for bigquery. Write only, blank keeps the stored key on update"},"project_id":{"type":"string","description":"bigquery: project id (default: from the key)"},"dataset":{"type":"string","description":"bigquery only: dataset id, required for bigquery"},"table":{"type":"string","description":"bigquery and snowflake: table name, required. Snowflake may use database.schema.table"},"account":{"type":"string","description":"snowflake only: account identifier like xy12345.us-east-1 or myorg-myaccount, required for snowflake"},"user":{"type":"string","description":"snowflake only: user name that authenticates with the private key, required for snowflake"},"private_key":{"type":"string","description":"snowflake only: PEM encoded RSA private key, required for snowflake. Write only, blank keeps the stored key on update"},"database":{"type":"string","description":"snowflake only: database name, required for snowflake"},"schema":{"type":"string","description":"snowflake only: schema name, required for snowflake"},"warehouse":{"type":"string","description":"snowflake: virtual warehouse"},"role":{"type":"string","description":"snowflake: role (optional)"},"sas_url":{"type":"string","description":"azure only: https blob container SAS URL on a blob.core.windows.net host with create and write permission, required for azure. Write only, blank keeps the stored value on update"}}}}}}}},"/warehouses/{id}/sync.json":{"post":{"operationId":"warehouse_destinations_sync","summary":"Queue a sync of one day now","description":"Queues an immediate upload of one UTC day of raw events to a destination, outside the daily schedule. Business plan only. date (YYYY-MM-DD) must be before today in UTC and defaults to yesterday. It uploads that day for every site of the destination, so avoid syncing a day that was already sent, and manual syncs are rate limited to 30 per hour per workspace. The call returns 202 with the destination at once and the upload runs in the background. Poll warehouse_destinations_get and read last_run_at and last_error to see the result. The id comes from warehouse_destinations_list. Needs the workspace.manage permission.","tags":["Warehouse sync"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by warehouse_destinations_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Destination id, e.g. whd_7Q2K9XH3AB"},"kind":{"type":"string","description":"s3, bigquery, snowflake or azure"},"name":{"type":"string"},"target":{"type":"string","description":"Where data goes: s3://bucket/prefix, project.dataset.table, account/database.schema.table or the Azure container"},"configured":{"type":"array","items":{"type":"string"},"description":"Setting names that are filled in (values are never returned)"},"site_ids":{"type":"array","items":{"type":"string"},"description":"Sites sent (pa_…). Empty means all sites"},"schedule":{"type":"string","description":"daily: 02:00 UTC, sends the previous UTC day"},"schema_version":{"type":"string","description":"Row schema sent"},"last_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"next_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"date":{"type":"string","format":"date","description":"UTC day to send, YYYY-MM-DD, before today in UTC. Default is yesterday"}}}}}}}},"/workspaces/{workspace_id}/webhooks/{webhook_id}/deliveries.json":{"get":{"operationId":"webhook_deliveries_list","summary":"List deliveries for a webhook","description":"Lists the deliveries sent to one webhook (path takes webhook_id), newest first and paginated. Each has id (whd_...), event, status (pending, succeeded for any 2xx response, or failed), status_code (null when no response came), error (a short reason such as a timeout, otherwise null), attempt (how many tries so far), duration_ms, payload (the JSON data that was sent), response_body (first 2000 characters of the response) and delivered_at and created_at. Filter with status succeeded or failed. Use it to debug an endpoint and webhook_deliveries_redeliver to send one again.","tags":["Webhooks"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"webhook_id","in":"path","required":true,"description":"Webhook id, from webhooks_list","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"succeeded (any 2xx response) or failed (an error or a non-2xx response). Pending deliveries are only in the unfiltered list","enum":["succeeded","failed"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Delivery id, e.g. whd_123"},"event":{"type":"string"},"status":{"type":"string","description":"pending, succeeded or failed"},"status_code":{"anyOf":[{"type":"integer","description":"HTTP status of the last attempt"},{"type":"null"}]},"error":{"anyOf":[{"type":"string","description":"Connection error of the last attempt"},{"type":"null"}]},"attempt":{"type":"integer"},"duration_ms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"payload":{"type":"object"},"response_body":{"anyOf":[{"type":"string","description":"First 2,000 characters"},{"type":"null"}]},"delivered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"webhook_deliveries_list","x-permission":"workspace.manage"}},"/workspaces/{workspace_id}/webhooks/{webhook_id}/deliveries/{id}/redeliver.json":{"post":{"operationId":"webhook_deliveries_redeliver","summary":"Send a delivery again","description":"Sends the payload of a past delivery again as a new delivery to the same endpoint (id whd_..., from webhook_deliveries_list). This makes an HTTP request to the customer's URL, so the receiver may process the same event twice. It is rate limited per workspace (shared with webhooks_test). It is queued, so the response is a new delivery with status pending, read webhook_deliveries_list to see the outcome.","tags":["Webhooks"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"webhook_id","in":"path","required":true,"description":"Webhook id, from webhooks_list","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by webhook_deliveries_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Delivery id, e.g. whd_123"},"event":{"type":"string"},"status":{"type":"string","description":"pending, succeeded or failed"},"status_code":{"anyOf":[{"type":"integer","description":"HTTP status of the last attempt"},{"type":"null"}]},"error":{"anyOf":[{"type":"string","description":"Connection error of the last attempt"},{"type":"null"}]},"attempt":{"type":"integer"},"duration_ms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"payload":{"type":"object"},"response_body":{"anyOf":[{"type":"string","description":"First 2,000 characters"},{"type":"null"}]},"delivered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"webhook_deliveries_redeliver","x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/workspaces/{workspace_id}/webhooks.json":{"post":{"operationId":"webhooks_create","summary":"Add a webhook endpoint","description":"Adds an endpoint that receives POSTed JSON for workspace events (path takes workspace_id). url must be a public https address, private and internal addresses are refused. events is a required list chosen from alert.triggered, alert.resolved, goal.completed_threshold, uptime.down, uptime.up, export.ready, import.completed, import.failed, site.created, site.deleted, member.added, usage.threshold and site_audit.completed. enabled defaults to true. A signing secret (whsec_...) is generated and returned in the response, and each delivery carries a Privatus-Signature header with a timestamp and an HMAC-SHA256 of the body made with it. Failed deliveries are retried with backoff and the endpoint is disabled after 20 failures in a row. Use webhooks_test to send a sample.","tags":["Webhooks"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Webhook id, e.g. wh_7Q2K9XH3AB"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"},"status":{"type":"string","description":"active, failing or disabled"},"secret":{"anyOf":[{"type":"string","description":"Signing secret for Privatus-Signature, null over MCP (a tool never returns a secret)"},{"type":"null"}]},"consecutive_failures":{"type":"integer"},"last_success_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_failure_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"webhooks_create","x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Public https endpoint that receives the JSON POSTs, up to 2000 characters. Private and internal addresses are refused","examples":["https://example.com/hooks/privatus"]},"events":{"type":"array","items":{"type":"string","enum":["alert.triggered","alert.resolved","goal.completed_threshold","uptime.down","uptime.up","export.ready","import.completed","import.failed","site.created","site.deleted","member.added","usage.threshold","site_audit.completed","experiment.ended","testimonial.received","testimonial.approved","testimonial.rejected","testimonial.trashed","testimonial.restored","testimonial.deleted","testimonial_import.finished","testimonial_sync.new_found","testimonial_form.submitted","testimonial_request.sent","testimonial_request.completed"]},"description":"Event names to send, at least one: alert.triggered, alert.resolved, goal.completed_threshold, uptime.down, uptime.up, export.ready, import.completed, import.failed, site.created, site.deleted, member.added, usage.threshold, site_audit.completed"},"enabled":{"type":"boolean","description":"Send deliveries (default true)","default":true}},"required":["url","events"]}}}}},"get":{"operationId":"webhooks_list","summary":"List webhooks","description":"Lists the outgoing webhook endpoints of a workspace (path takes workspace_id), oldest first. Each has id (wh_...), url, events (the event names it receives), enabled, status (active, failing after recent failures, or disabled), secret (the signing secret, treat it as sensitive), consecutive_failures, last_success_at, last_failure_at and created_at. Needs the workspace.manage permission. This is for sending raw events to your own server. To notify people use notification_channels_list. Use webhook_deliveries_list for what was sent.","tags":["Webhooks"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Webhook id, e.g. wh_7Q2K9XH3AB"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"},"status":{"type":"string","description":"active, failing or disabled"},"secret":{"anyOf":[{"type":"string","description":"Signing secret for Privatus-Signature, null over MCP (a tool never returns a secret)"},{"type":"null"}]},"consecutive_failures":{"type":"integer"},"last_success_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_failure_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"webhooks_list","x-permission":"workspace.manage"}},"/workspaces/{workspace_id}/webhooks/{id}.json":{"delete":{"operationId":"webhooks_delete","summary":"Delete a webhook","description":"Deletes a webhook endpoint and its whole delivery log. This cannot be undone and pending retries stop. To pause it instead use webhooks_update with enabled false. The id (wh_...) comes from webhooks_list. Returns the deleted webhook.","tags":["Webhooks"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by webhooks_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Webhook id, e.g. wh_7Q2K9XH3AB"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"},"status":{"type":"string","description":"active, failing or disabled"},"secret":{"anyOf":[{"type":"string","description":"Signing secret for Privatus-Signature, null over MCP (a tool never returns a secret)"},{"type":"null"}]},"consecutive_failures":{"type":"integer"},"last_success_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_failure_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"webhooks_delete","x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"webhooks_get","summary":"Get a webhook","description":"Returns one webhook endpoint by id (wh_..., from webhooks_list), including its signing secret (whsec_...), which is used to verify the Privatus-Signature header on each delivery. Fields are url, events, enabled, status (active, failing or disabled), secret, consecutive_failures, last_success_at, last_failure_at and created_at. Needs the workspace.manage permission.","tags":["Webhooks"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by webhooks_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Webhook id, e.g. wh_7Q2K9XH3AB"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"},"status":{"type":"string","description":"active, failing or disabled"},"secret":{"anyOf":[{"type":"string","description":"Signing secret for Privatus-Signature, null over MCP (a tool never returns a secret)"},{"type":"null"}]},"consecutive_failures":{"type":"integer"},"last_success_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_failure_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"webhooks_get","x-permission":"workspace.manage"},"patch":{"operationId":"webhooks_update","summary":"Update a webhook (events, URL, enabled, rotate secret)","description":"Changes a webhook (id from webhooks_list). Only the inputs you send change. Sending events replaces the whole list. Setting enabled true on a disabled endpoint resets its failure count, which is how you turn back on one that was disabled after repeated failures. Set rotate_secret true to generate a new signing secret, shown in the response, and the old one stops working at once so the receiver must be updated. The url rules are the same as webhooks_create. Returns the webhook.","tags":["Webhooks"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by webhooks_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Webhook id, e.g. wh_7Q2K9XH3AB"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"},"status":{"type":"string","description":"active, failing or disabled"},"secret":{"anyOf":[{"type":"string","description":"Signing secret for Privatus-Signature, null over MCP (a tool never returns a secret)"},{"type":"null"}]},"consecutive_failures":{"type":"integer"},"last_success_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"last_failure_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"webhooks_update","x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"New public https endpoint. Leave out to keep the current one"},"events":{"type":"array","items":{"type":"string","enum":["alert.triggered","alert.resolved","goal.completed_threshold","uptime.down","uptime.up","export.ready","import.completed","import.failed","site.created","site.deleted","member.added","usage.threshold","site_audit.completed","experiment.ended","testimonial.received","testimonial.approved","testimonial.rejected","testimonial.trashed","testimonial.restored","testimonial.deleted","testimonial_import.finished","testimonial_sync.new_found","testimonial_form.submitted","testimonial_request.sent","testimonial_request.completed"]},"description":"Replaces the whole list of event names to send"},"enabled":{"type":"boolean","description":"Send deliveries. Setting true on a disabled endpoint also resets its failure count"},"rotate_secret":{"type":"boolean","description":"true generates a new signing secret and the old one stops working immediately","default":false}}}}}}}},"/workspaces/{workspace_id}/webhooks/{id}/test.json":{"post":{"operationId":"webhooks_test","summary":"Send a test delivery","description":"Queues a webhook.test delivery with a sample message to one endpoint, even when it is disabled, which makes an HTTP request to the customer's URL. It is rate limited per workspace (shared with webhook_deliveries_redeliver) and a test is not retried. The delivery is sent in the background, so the response returns the queued delivery with status pending. Read webhook_deliveries_list a moment later to see status_code, error, duration_ms and response_body.","tags":["Webhooks"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by webhooks_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Delivery id, e.g. whd_123"},"event":{"type":"string"},"status":{"type":"string","description":"pending, succeeded or failed"},"status_code":{"anyOf":[{"type":"integer","description":"HTTP status of the last attempt"},{"type":"null"}]},"error":{"anyOf":[{"type":"string","description":"Connection error of the last attempt"},{"type":"null"}]},"attempt":{"type":"integer"},"duration_ms":{"anyOf":[{"type":"integer"},{"type":"null"}]},"payload":{"type":"object"},"response_body":{"anyOf":[{"type":"string","description":"First 2,000 characters"},{"type":"null"}]},"delivered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"webhooks_test","x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/blog.json":{"get":{"operationId":"blog_list","summary":"List blog posts","description":"Lists the posts of the Privatus Analytics blog, newest first, with slug, title, kicker, rubric (the one-sentence summary), description, path and dates, and no body. To read one use blog_get with its slug. Paginated with page and per_page (maximum 100). Public, no authentication needed.","tags":["Website"],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string","description":"The last part of the post's address, /blog/<slug>"},"title":{"type":"string","description":"Headline"},"kicker":{"type":"string","description":"The few words above the headline that name the subject"},"rubric":{"type":"string","description":"The one sentence under the headline that says what the post found"},"description":{"type":"string","description":"Meta description"},"path":{"type":"string","description":"Page path. Add .json for JSON"},"published_on":{"type":"string","format":"date","description":"The day the post was published"},"updated_on":{"type":"string","format":"date","description":"The day the post last changed (the publication day when it never did)"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"blog_list","security":[]}},"/blog/{slug}.json":{"get":{"operationId":"blog_get","summary":"Read a blog post (Markdown and HTML)","description":"Returns one blog post by its slug (from blog_list, the last part of /blog/<slug>) with its headings, its Markdown body and the rendered HTML. Posts are written in English. Public, no authentication needed.","tags":["Website"],"parameters":[{"name":"slug","in":"path","required":true,"description":"Post slug, the last part of /blog/<slug>, from blog_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"slug":{"type":"string","description":"The last part of the post's address, /blog/<slug>"},"title":{"type":"string","description":"Headline"},"kicker":{"type":"string","description":"The few words above the headline that name the subject"},"rubric":{"type":"string","description":"The one sentence under the headline that says what the post found"},"description":{"type":"string","description":"Meta description"},"path":{"type":"string","description":"Page path. Add .json for JSON"},"published_on":{"type":"string","format":"date","description":"The day the post was published"},"updated_on":{"type":"string","format":"date","description":"The day the post last changed (the publication day when it never did)"},"headings":{"type":"array","items":{"type":"object"},"description":"The H2 headings of the post, each with id (the anchor) and text"},"markdown":{"type":"string","description":"The body as Markdown, without its images"},"html":{"type":"string","description":"The body as HTML"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"blog_get","security":[]}},"/changelog.json":{"get":{"operationId":"changelog_list","summary":"List changelog entries","description":"Published product updates, newest first. Also available as RSS at /changelog.rss.","tags":["Website"],"parameters":[{"name":"area","in":"query","required":false,"schema":{"type":"string","description":"Only entries for this product area. One of the listed values, otherwise the request is rejected.","enum":["product","dashboard","tracker","privacy","api","integrations","billing","docs"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Entry id, e.g. chg_testimonials"},"title":{"type":"string","description":"Headline"},"area":{"type":"string","description":"Product area, e.g. dashboard, tracker, api"},"body":{"type":"string","description":"Markdown body"},"published_at":{"type":"string","format":"date-time","description":"Publication time"},"url":{"type":"string","description":"Permanent link"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"changelog_list","security":[]}},"/contact.json":{"post":{"operationId":"contact_create","summary":"Send a message to the Privatus Analytics team","description":"Browser clients send a Cloudflare Turnstile token as `cf-turnstile-response`. Requests with an API token need none.","tags":["Website"],"parameters":[],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"received":{"type":"boolean","description":"Always true when the submission was accepted"},"message":{"type":"string","description":"What happens next"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Your name","examples":["Ada Lovelace"]},"email":{"type":"string","description":"Where we should reply","examples":["ada@example.com"]},"company":{"type":"string","description":"Company or organization (optional)"},"topic":{"type":"string","description":"What the message is about","enum":["general","sales","support","privacy","security","partnerships","press"],"default":"general"},"message":{"type":"string","description":"Your message (10 to 5,000 characters)"},"website":{"type":"string","description":"Leave empty. Spam trap for bots. Filled-in submissions are discarded"}},"required":["name","email","message"]}}}},"security":[]}},"/newsletter/confirm.json":{"post":{"operationId":"newsletter_confirm","summary":"Confirm a newsletter subscription (signed token)","tags":["Website"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"received":{"type":"boolean","description":"Always true when the submission was accepted"},"message":{"type":"string","description":"What happens next"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Signed token from the confirmation email"}},"required":["token"]}}}},"security":[]}},"/newsletter.json":{"post":{"operationId":"newsletter_subscribe","summary":"Subscribe an email to the newsletter","description":"Browser clients send a Cloudflare Turnstile token as `cf-turnstile-response`. Requests with an API token need none.","tags":["Website"],"parameters":[],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"received":{"type":"boolean","description":"Always true when the submission was accepted"},"message":{"type":"string","description":"What happens next"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","description":"Email address to subscribe. A confirmation link is emailed to it","examples":["reader@example.com"]},"website":{"type":"string","description":"Leave empty. Spam trap for bots. Filled-in submissions are discarded"}},"required":["email"]}}}},"security":[]}},"/newsletter/unsubscribe.json":{"post":{"operationId":"newsletter_unsubscribe","summary":"Unsubscribe with a signed link token","tags":["Website"],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"received":{"type":"boolean","description":"Always true when the submission was accepted"},"message":{"type":"string","description":"What happens next"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Signed token from the unsubscribe link"},"list":{"type":"string","description":"newsletter (default: the list the link was for) or marketing (all marketing email)","enum":["newsletter","marketing"]}},"required":["token"]}}}},"security":[]}},"/pricing.json":{"get":{"operationId":"pricing_get","summary":"Get plans, prices and plan limits","description":"The same data as the pricing page: the events ladder, every plan limit and what counts as an event. Pass events to get the matching tier.","tags":["Website"],"parameters":[{"name":"events","in":"query","required":false,"schema":{"type":"integer","description":"Expected pageviews plus custom events a month. Returns the matching tier as `recommendation`","examples":[750000]}},{"name":"interval","in":"query","required":false,"schema":{"type":"string","description":"Billing interval for the prices shown: month, or year (10x the monthly price)","enum":["month","year"],"default":"month"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"currency":{"type":"string","description":"Currency of every price (USD)"},"tax_included":{"type":"boolean","description":"Always true. Prices include VAT or sales tax, so the price shown is the price paid"},"interval":{"type":"string","description":"month or year. Prices are for this interval"},"annual_multiplier":{"type":"integer","description":"Yearly price = monthly price x this (two months free)"},"free_events":{"type":"integer","description":"Events a month included in the Free plan"},"badge_bonus":{"type":"integer","description":"Extra free events a month when the optional badge is shown"},"tiers":{"type":"array","items":{"type":"object"},"description":"Events ladder: { events, pro, business } prices for the interval (pro is null where only Business is offered), plus the monthly prices"},"plans":{"type":"array","items":{"type":"object"},"description":"Plans with { id, name, from_price, limits }. Limits of null mean unlimited"},"counted":{"type":"array","items":{"type":"string"},"description":"What counts as a billable event"},"not_counted":{"type":"array","items":{"type":"string"},"description":"What never counts toward usage"},"recommendation":{"anyOf":[{"type":"object","description":"{ events, plan, tier_events, price } for the `events` input, or null when no volume was given"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"pricing_get","security":[]}},"/status.json":{"get":{"operationId":"status_get","summary":"Get the current system status","description":"Database, Redis and background-job health, checked at most every 15 seconds.","tags":["Website"],"parameters":[{"name":"fresh","in":"query","required":false,"schema":{"type":"boolean","description":"Skip the 15-second cache and check again now","default":false}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string","description":"Overall: operational, degraded or outage"},"checked_at":{"type":"string","format":"date-time","description":"When the checks ran (cached up to 15 s)"},"components":{"type":"array","items":{"type":"object"},"description":"Per component: { id, name, status, detail, latency_ms }, plus queue_latency_s and queue_depth for queues"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"status_get","security":[]}},"/tools/consent-gap.json":{"get":{"operationId":"tools_consent_gap","summary":"Estimate traffic missed by consent-based analytics","description":"Free calculator that estimates how much traffic a cookie-consent analytics tool misses compared with cookieless tracking. It is a simple model, not a measurement. Inputs are monthly_visitors (a whole number above 0), consent_rate (percent of visitors who accept the banner, 0 to 100) and adblock_share (percent whose blockers stop the script, 0 to 100, default 25). Returns the inputs plus measured_with_consent (visitors the consent tool sees), missed (visitors it does not see), missed_percent (one decimal), measured_cookieless (visitors reachable without a banner) and recovered_by_cookieless (visitors gained over consent tracking). All visitor counts are whole numbers. It makes no requests and uses no account data. Public, no authentication needed.","tags":["Website"],"parameters":[{"name":"monthly_visitors","in":"query","required":false,"schema":{"type":"integer","description":"Visitors a month (from your server logs or current analytics)","examples":[50000]}},{"name":"consent_rate","in":"query","required":false,"schema":{"type":"number","description":"Percent of visitors who accept analytics cookies in your banner (0-100)","examples":[55]}},{"name":"adblock_share","in":"query","required":false,"schema":{"type":"number","description":"Percent of visitors whose blockers stop analytics scripts (0-100)","default":25.0}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"monthly_visitors":{"type":"integer","description":"Input: visitors a month"},"consent_rate":{"type":"number","description":"Input: percent who accept analytics cookies"},"adblock_share":{"type":"number","description":"Input: percent whose blockers stop scripts"},"measured_with_consent":{"type":"integer","description":"Visitors a consent-based tool can measure"},"missed":{"type":"integer","description":"Visitors it misses"},"missed_percent":{"type":"number","description":"Share of visitors missed, in percent"},"measured_cookieless":{"type":"integer","description":"Visitors a cookieless tool without a banner can measure, if it is blocked at the same rate"},"recovered_by_cookieless":{"type":"integer","description":"Difference between the cookieless and consent-based estimates"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"tools_consent_gap","security":[]}},"/tools/header-checker.json":{"get":{"operationId":"tools_header_check","summary":"Check a page’s Referrer-Policy and CSP for analytics","description":"Fetches one public page and checks the response headers that affect analytics. Use it when tracking data is missing or referrers look wrong. It looks at Referrer-Policy, the Content-Security-Policy script-src and connect-src directives (whether Privatus Analytics may load and send data), Permissions-Policy and the number of Set-Cookie headers. Returns url (the final URL after up to 3 redirects), status (HTTP status) and findings, each with check, value (nullable), level (ok, warn or info) and a plain-language note. The URL must be http or https and public, private and internal addresses are refused, only the first 1 MB is read and the fetch times out after 5 seconds. Rate limited to 10 calls a minute per client. Public, no authentication needed.","tags":["Website"],"parameters":[{"name":"url","in":"query","required":false,"schema":{"type":"string","description":"Full public page URL including https://, at most 2,000 characters. Private and internal addresses are refused. At most 10 fetching tool calls a minute per client.","examples":["https://example.com"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"url":{"type":"string","description":"Final URL after redirects"},"status":{"type":"integer","description":"HTTP status of the final response"},"findings":{"type":"array","items":{"type":"object"},"description":"Checks: { check, value, level (ok, warn, info), note }"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"tools_header_check","security":[]}},"/tools/privacy-policy-generator.json":{"get":{"operationId":"tools_privacy_policy","summary":"Draft a privacy-policy paragraph for Privatus Analytics","description":"Drafts a privacy policy paragraph describing how Privatus Analytics collects data on the customer's site (cookieless, no personal data stored, country only location). It is a starting point, not legal advice. Inputs are site_name (up to 120 characters), contact_email (optional, adds a contact sentence) and honors_gpc (default true, adds a sentence saying Do Not Track and Global Privacy Control are honored). Returns site_name, paragraphs (array of strings), text (the paragraphs joined with blank lines, with the address of Privatus Analytics in brackets after its name) and html (the paragraphs as <p> elements, with the name as a plain link). The text is written in the language of the request, English by default. It makes no changes to any account. Public, no authentication needed.","tags":["Website"],"parameters":[{"name":"site_name","in":"query","required":false,"schema":{"type":"string","description":"Your website or company name as it should appear in the policy, at most 120 characters.","examples":["Example Books"]}},{"name":"contact_email","in":"query","required":false,"schema":{"type":"string","description":"Privacy contact to mention (optional)"}},{"name":"honors_gpc","in":"query","required":false,"schema":{"type":"boolean","description":"true (default) adds a sentence saying Do Not Track and Global Privacy Control signals are honored. Set false only if your site ignores them.","default":true}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"site_name":{"type":"string","description":"Input: site or company name"},"paragraphs":{"type":"array","items":{"type":"string"},"description":"The policy text, one paragraph per item"},"text":{"type":"string","description":"The paragraphs joined with blank lines"},"html":{"type":"string","description":"The same paragraphs as HTML, one <p> element each, with a plain link on the name Privatus Analytics (no rel attribute and no tracking parameters)"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"tools_privacy_policy","security":[]}},"/tools/qr-code.json":{"get":{"operationId":"tools_qr_code","summary":"Generate a QR code as SVG","description":"Generates a QR code as an SVG image for print or posters. Pair it with a link that has UTM parameters from tools_utm_builder. Inputs are text (the URL or text, up to 1,000 characters) and level (error correction l, m, q or h, default m, higher survives more damage but needs a denser code). Returns text, level, size (modules per side) and svg (a standalone SVG document, black on white). Text too long for the chosen level is rejected. For QR codes of tracked short links use links_qr instead. Public, no authentication needed.","tags":["Website"],"parameters":[{"name":"text","in":"query","required":false,"schema":{"type":"string","description":"URL or text to encode (up to 1,000 characters)","examples":["https://example.com/?utm_source=poster"]}},{"name":"level","in":"query","required":false,"schema":{"type":"string","description":"Error correction: l (7%), m (15%), q (25%), h (30%)","enum":["l","m","q","h"],"default":"m"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"text":{"type":"string","description":"The encoded text"},"level":{"type":"string","description":"Error correction level"},"size":{"type":"integer","description":"Modules per side"},"svg":{"type":"string","description":"Standalone SVG document"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"tools_qr_code","security":[]}},"/tools/tracker-scanner.json":{"get":{"operationId":"tools_tracker_scan","summary":"List cookies and known trackers on a page","description":"Fetches one public page and lists the cookies it sets and the known third-party trackers it references. Use it for a quick check of what a page loads before choosing a consent approach. It is a static scan of the HTML and response headers only, it does not run JavaScript, so cookies set by scripts and tags loaded later by a tag manager are missed. Returns url (final URL after up to 3 redirects), status, truncated (true when only the first 1 MB was read), cookies (name, domain, path, expires, secure, http_only and same_site, values are never returned), trackers (name, category, match and evidence, where category is advertising, analytics, session_recording, tag_manager, marketing or privacy_analytics) and third_party_hosts (sorted host names of other sites). The URL must be public http or https, with a 5 second fetch timeout, and calls are limited to 10 a minute per client. Public, no authentication needed.","tags":["Website"],"parameters":[{"name":"url","in":"query","required":false,"schema":{"type":"string","description":"Full public page URL including https://, at most 2,000 characters. Private and internal addresses are refused. At most 10 fetching tool calls a minute per client.","examples":["https://example.com"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"url":{"type":"string","description":"Final URL after redirects"},"status":{"type":"integer","description":"HTTP status of the final response"},"truncated":{"type":"boolean","description":"True when the page was over 1 MB and only the first 1 MB was scanned"},"cookies":{"type":"array","items":{"type":"object"},"description":"Cookies set by the HTTP response: { name, domain, path, expires, secure, http_only, same_site }. Values are never returned"},"trackers":{"type":"array","items":{"type":"object"},"description":"Known tools referenced by the page: { name, category, match, evidence }"},"third_party_hosts":{"type":"array","items":{"type":"string"},"description":"Other domains the page loads resources from"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"tools_tracker_scan","security":[]}},"/tools/utm-builder.json":{"get":{"operationId":"tools_utm_builder","summary":"Build a campaign URL with UTM parameters","description":"Builds a campaign URL with UTM parameters and flags common mistakes. Inputs are url (must be http or https), source, medium and campaign (all required) and optional term and content. Existing utm_ parameters on the URL are replaced and other query parameters are kept. Returns url (the finished link), params (the utm_ values that were added, blank ones left out) and warnings (strings for values with uppercase letters, spaces, or text that looks like an email address or a long number, which should never be in a URL). Use lowercase values with no spaces so the same campaign is not split into several rows in reports. It saves nothing. Public, no authentication needed.","tags":["Website"],"parameters":[{"name":"url","in":"query","required":false,"schema":{"type":"string","description":"Landing page URL including http:// or https://. Existing utm_ parameters on it are replaced and other query parameters are kept.","examples":["https://example.com/pricing"]}},{"name":"source","in":"query","required":false,"schema":{"type":"string","description":"utm_source, where the traffic comes from. Use lowercase and no spaces, for example newsletter or google.","examples":["newsletter"]}},{"name":"medium","in":"query","required":false,"schema":{"type":"string","description":"utm_medium, the channel. Use lowercase and no spaces, for example email, cpc or social.","examples":["email"]}},{"name":"campaign","in":"query","required":false,"schema":{"type":"string","description":"utm_campaign, the campaign name. Use lowercase and no spaces, for example fall_launch.","examples":["fall_launch"]}},{"name":"term","in":"query","required":false,"schema":{"type":"string","description":"utm_term: paid search keyword (optional)"}},{"name":"content","in":"query","required":false,"schema":{"type":"string","description":"utm_content: which link or creative (optional)"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"url":{"type":"string","description":"The landing page URL with UTM parameters"},"params":{"type":"object","description":"The UTM parameters that were added"},"warnings":{"type":"array","items":{"type":"string"},"description":"Problems worth fixing (case, spaces, personal data)"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"tools_utm_builder","security":[]}},"/waitlist.json":{"post":{"operationId":"waitlist_join","summary":"Join a waitlist (EU hosting)","description":"Browser clients send a Cloudflare Turnstile token as `cf-turnstile-response`. Requests with an API token need none.","tags":["Website"],"parameters":[],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"received":{"type":"boolean","description":"Always true when the submission was accepted"},"message":{"type":"string","description":"What happens next"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","description":"Email to notify","examples":["dpo@example.eu"]},"list":{"type":"string","description":"Which waitlist to join","enum":["eu_hosting"],"default":"eu_hosting"},"website":{"type":"string","description":"Leave empty. Spam trap for bots. Filled-in submissions are discarded"}},"required":["email"]}}}},"security":[]}},"/sites/{site_id}/testimonials/widgets/{id}/copied.json":{"post":{"operationId":"testimonial_widgets_mark_copied","summary":"Note that the pasted HTML embed of a widget was copied","description":"The pasted HTML does not update by itself. After this call, testimonial_widgets_embed reports how many times the widget changed since.","tags":["Widgets"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_widgets_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Widget id, e.g. wdg_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the widget's embed responds 410 and shows nothing"},"name":{"type":"string","description":"Internal name"},"layout":{"type":"string","description":"The layout"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"limit":{"type":"integer","description":"The most testimonials shown"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"language_mode":{"type":"string","description":"fixed or page"},"language":{"type":"string","description":"Language code of the widget's own words"},"show_translations":{"type":"boolean","description":"Stored translations are shown"},"count_views":{"type":"boolean","description":"Views and clicks are counted"},"revision":{"type":"integer","description":"Goes up with every change a visitor could see"},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"installed":{"type":"boolean","description":"It was seen live on a page"},"pages_seen":{"type":"integer","description":"How many pages it was seen live on"},"seen_on":{"anyOf":[{"type":"string","description":"The first page it was seen live on, as host and path"},{"type":"null"}]},"first_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was first seen live"},{"type":"null"}]},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last seen live"},{"type":"null"}]},"fragment_bytes":{"anyOf":[{"type":"integer","description":"Compressed size of the widget at its last render, in bytes"},{"type":"null"}]},"fragment_images":{"anyOf":[{"type":"integer","description":"Images among the cards a visitor sees before scrolling"},{"type":"null"}]},"embed_url":{"type":"string","description":"The address of the widget as a page, for a frame"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_widgets_mark_copied","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/sites/{site_id}/testimonials/widgets.json":{"post":{"operationId":"testimonial_widgets_create","summary":"Create a widget","description":"One call carries the whole widget: the layout and its options, what feeds it, what each card shows and how it looks. Anything left out starts from a default, and a blank style setting inherits the brand kit. Follow it with testimonial_widgets_embed to get the code to paste.","tags":["Widgets"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Widget id, e.g. wdg_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the widget's embed responds 410 and shows nothing"},"name":{"type":"string","description":"Internal name"},"layout":{"type":"string","description":"The layout"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"limit":{"type":"integer","description":"The most testimonials shown"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"language_mode":{"type":"string","description":"fixed or page"},"language":{"type":"string","description":"Language code of the widget's own words"},"show_translations":{"type":"boolean","description":"Stored translations are shown"},"count_views":{"type":"boolean","description":"Views and clicks are counted"},"revision":{"type":"integer","description":"Goes up with every change a visitor could see"},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"installed":{"type":"boolean","description":"It was seen live on a page"},"pages_seen":{"type":"integer","description":"How many pages it was seen live on"},"seen_on":{"anyOf":[{"type":"string","description":"The first page it was seen live on, as host and path"},{"type":"null"}]},"first_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was first seen live"},{"type":"null"}]},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last seen live"},{"type":"null"}]},"fragment_bytes":{"anyOf":[{"type":"integer","description":"Compressed size of the widget at its last render, in bytes"},{"type":"null"}]},"fragment_images":{"anyOf":[{"type":"integer","description":"Images among the cards a visitor sees before scrolling"},{"type":"null"}]},"embed_url":{"type":"string","description":"The address of the widget as a page, for a frame"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_widgets_create","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Internal name, 1 to 100 characters. Required on create"},"source_kind":{"type":"string","description":"What feeds it: collection, view, tags or picked. Nothing is shown until one is chosen","enum":["collection","view","tags","picked"]},"collection_id":{"type":"string","description":"The collection that feeds it (col_...), manual or smart"},"view_id":{"type":"string","description":"The shared saved view that feeds it (vw_...)"},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it (tag_...)"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"Hand-picked testimonials (tm_...), in the order to show them, up to 100"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark","enum":["auto","light","dark"]},"font_size":{"type":"string","description":"small, medium or large","enum":["small","medium","large"]},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts","enum":["inherit","stars","hearts"]},"sort":{"type":"string","description":"source keeps the collection's or the picked order. newest, oldest and rating put pinned testimonials first","enum":["source","newest","oldest","rating"]},"tag_match":{"type":"string","description":"any (a testimonial with any of the tags) or all","enum":["any","all"]},"schema_type":{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization","enum":["Product","SoftwareApplication","Course","Book","Event","Recipe","LocalBusiness","Organization"]},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts. Default true"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown. Default true"},"show_company":{"type":"boolean","description":"Show the person's title and company. Default true"},"show_date":{"type":"boolean","description":"Show the date it was received. Default false"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address. Default true"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one. Default false"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason. Default true"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page. Default true"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on. Default false"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20. Default 8"},"accent_color":{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},"card_color":{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},"text_color":{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},"border_color":{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},"rating_color":{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},"background_color":{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},"radius":{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono","enum":["inherit_page","brand","system","system_serif","system_mono"]},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font","enum":["inherit_page","brand","system","system_serif","system_mono"]},"show_badge":{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},"custom_css":{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_name":{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},"per_view":{"type":"integer","description":"Carousel: cards in view, 1 to 4. Default 3"},"autoplay":{"type":"boolean","description":"Carousel: move by itself. A pause button is then always shown. Default false"},"interval_seconds":{"type":"integer","description":"Carousel and single quote: seconds per step, 3 to 15. Default 6"},"arrows":{"type":"boolean","description":"Carousel: previous and next buttons. Default true"},"dots":{"type":"boolean","description":"Carousel: position dots. Default true"},"loop":{"type":"boolean","description":"Carousel: go back to the start after the last card. Default true"},"columns":{"type":"integer","description":"Grid (1 to 5) and masonry (2 to 5): columns at full width. Default 3"},"gap":{"type":"string","description":"Grid and masonry: space between cards, small, medium or large","enum":["small","medium","large"]},"equal_height":{"type":"boolean","description":"Grid: cards of one row share a height. Default false"},"load_more":{"type":"boolean","description":"Grid, masonry and list: show a Load more button. Default true"},"page_size":{"type":"integer","description":"Grid, masonry and list: cards before Load more, 3 to 30. Default 9"},"avatar_position":{"type":"string","description":"List: the person left of the words, or top","enum":["left","top"]},"dividers":{"type":"boolean","description":"List: lines between testimonials in place of boxes. Default true"},"size":{"type":"string","description":"Single quote: medium, large or extra_large","enum":["medium","large","extra_large"]},"align":{"type":"string","description":"Single quote: left or center","enum":["left","center"]},"rotate":{"type":"boolean","description":"Single quote: step through up to 5 testimonials. Default false"},"rows":{"type":"integer","description":"Marquee: rows, 1 to 3. Default 1"},"speed":{"type":"string","description":"Marquee: slow, medium or fast","enum":["slow","medium","fast"]},"direction":{"type":"string","description":"Marquee: left or right","enum":["left","right"]},"avatars":{"type":"integer","description":"Avatar strip: faces shown, 1 to 8. Default 5"},"text":{"type":"string","description":"Avatar strip and rating badge: the line of text, up to 80 characters. {count} and {average} are filled in from the testimonials"},"link_url":{"type":"string","description":"Avatar strip and rating badge: an https address the whole thing links to"},"shape":{"type":"string","description":"Rating badge: compact or wide","enum":["compact","wide"]},"position":{"type":"string","description":"Corner popup: bottom_left or bottom_right","enum":["bottom_left","bottom_right"]},"delay_seconds":{"type":"integer","description":"Corner popup: seconds before the first one, 0 to 60. Default 5"},"display_seconds":{"type":"integer","description":"Corner popup: seconds each one stays, 4 to 30. Default 8"},"hide_on_phones":{"type":"boolean","description":"Corner popup: not shown on a narrow screen. Default false"},"layout":{"type":"string","description":"carousel, grid, masonry, list, single_quote, marquee, avatar_strip, rating_badge or corner_popup. Options of another layout are ignored","enum":["carousel","grid","masonry","list","single_quote","marquee","avatar_strip","rating_badge","corner_popup"]},"limit":{"type":"integer","description":"The most testimonials shown, 1 to 100. Default 12"},"language_mode":{"type":"string","description":"fixed (always the language below) or page (the language of the page it is on, when the site offers it)","enum":["fixed","page"]},"language":{"type":"string","description":"One of the site's languages: the widget's own words (Read more, Verified, dates)","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]},"show_translations":{"type":"boolean","description":"Show a stored translation of each testimonial in the widget's language, on any plan. Making translations is part of Business"},"count_views":{"type":"boolean","description":"false sends nothing from the visitor's browser: views, clicks and install detection stop. Default true"}}}}}}},"get":{"operationId":"testimonial_widgets_list","summary":"List the widgets of a site","description":"Widgets in the trash are not listed. Each widget carries its settings, how many testimonials it shows now, its views and clicks for the last 30 days and the first page it was seen live on.","tags":["Widgets"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"Searches the name"}},{"name":"layout","in":"query","required":false,"schema":{"type":"string","description":"Only widgets with this layout","enum":["carousel","grid","masonry","list","single_quote","marquee","avatar_strip","rating_badge","corner_popup"]}},{"name":"installed","in":"query","required":false,"schema":{"type":"boolean","description":"true for widgets seen live on a page, false for ones not seen yet"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"name (the default), created or seen","enum":["name","created","seen"],"default":"name"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Widget id, e.g. wdg_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the widget's embed responds 410 and shows nothing"},"name":{"type":"string","description":"Internal name"},"layout":{"type":"string","description":"The layout"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"limit":{"type":"integer","description":"The most testimonials shown"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"language_mode":{"type":"string","description":"fixed or page"},"language":{"type":"string","description":"Language code of the widget's own words"},"show_translations":{"type":"boolean","description":"Stored translations are shown"},"count_views":{"type":"boolean","description":"Views and clicks are counted"},"revision":{"type":"integer","description":"Goes up with every change a visitor could see"},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"installed":{"type":"boolean","description":"It was seen live on a page"},"pages_seen":{"type":"integer","description":"How many pages it was seen live on"},"seen_on":{"anyOf":[{"type":"string","description":"The first page it was seen live on, as host and path"},{"type":"null"}]},"first_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was first seen live"},{"type":"null"}]},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last seen live"},{"type":"null"}]},"fragment_bytes":{"anyOf":[{"type":"integer","description":"Compressed size of the widget at its last render, in bytes"},{"type":"null"}]},"fragment_images":{"anyOf":[{"type":"integer","description":"Images among the cards a visitor sees before scrolling"},{"type":"null"}]},"embed_url":{"type":"string","description":"The address of the widget as a page, for a frame"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_widgets_list","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/widgets/{id}.json":{"delete":{"operationId":"testimonial_widgets_trash","summary":"Move a widget to the trash","description":"Its embeds render nothing and take no space until it is restored. It is deleted for good after 30 days. Over MCP the tool changes nothing and responds with the page of the app where a person does it.","tags":["Widgets"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_widgets_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Widget id, e.g. wdg_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the widget's embed responds 410 and shows nothing"},"name":{"type":"string","description":"Internal name"},"layout":{"type":"string","description":"The layout"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"limit":{"type":"integer","description":"The most testimonials shown"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"language_mode":{"type":"string","description":"fixed or page"},"language":{"type":"string","description":"Language code of the widget's own words"},"show_translations":{"type":"boolean","description":"Stored translations are shown"},"count_views":{"type":"boolean","description":"Views and clicks are counted"},"revision":{"type":"integer","description":"Goes up with every change a visitor could see"},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"installed":{"type":"boolean","description":"It was seen live on a page"},"pages_seen":{"type":"integer","description":"How many pages it was seen live on"},"seen_on":{"anyOf":[{"type":"string","description":"The first page it was seen live on, as host and path"},{"type":"null"}]},"first_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was first seen live"},{"type":"null"}]},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last seen live"},{"type":"null"}]},"fragment_bytes":{"anyOf":[{"type":"integer","description":"Compressed size of the widget at its last render, in bytes"},{"type":"null"}]},"fragment_images":{"anyOf":[{"type":"integer","description":"Images among the cards a visitor sees before scrolling"},{"type":"null"}]},"embed_url":{"type":"string","description":"The address of the widget as a page, for a frame"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"get":{"operationId":"testimonial_widgets_get","summary":"Get one widget with every setting, what it shows and where it is live","description":"Everything the builder stores: the layout and its options, what feeds the widget (a collection, a saved view, tags or a hand-picked list), what each card shows, the style, the language and the review markup, with where it was seen live and how many testimonials it shows now. A widget in the trash responds with 404.","tags":["Widgets"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_widgets_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Widget id, e.g. wdg_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the widget's embed responds 410 and shows nothing"},"name":{"type":"string","description":"Internal name"},"layout":{"type":"string","description":"The layout"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"limit":{"type":"integer","description":"The most testimonials shown"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"language_mode":{"type":"string","description":"fixed or page"},"language":{"type":"string","description":"Language code of the widget's own words"},"show_translations":{"type":"boolean","description":"Stored translations are shown"},"count_views":{"type":"boolean","description":"Views and clicks are counted"},"revision":{"type":"integer","description":"Goes up with every change a visitor could see"},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"installed":{"type":"boolean","description":"It was seen live on a page"},"pages_seen":{"type":"integer","description":"How many pages it was seen live on"},"seen_on":{"anyOf":[{"type":"string","description":"The first page it was seen live on, as host and path"},{"type":"null"}]},"first_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was first seen live"},{"type":"null"}]},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last seen live"},{"type":"null"}]},"fragment_bytes":{"anyOf":[{"type":"integer","description":"Compressed size of the widget at its last render, in bytes"},{"type":"null"}]},"fragment_images":{"anyOf":[{"type":"integer","description":"Images among the cards a visitor sees before scrolling"},{"type":"null"}]},"embed_url":{"type":"string","description":"The address of the widget as a page, for a frame"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_widgets_get","x-permission":"analytics.read"},"patch":{"operationId":"testimonial_widgets_update","summary":"Change a widget","description":"Only the inputs sent change. A saved change reaches every site the widget is on without touching their code, because its cached copies are cleared.","tags":["Widgets"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_widgets_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Widget id, e.g. wdg_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the widget's embed responds 410 and shows nothing"},"name":{"type":"string","description":"Internal name"},"layout":{"type":"string","description":"The layout"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"limit":{"type":"integer","description":"The most testimonials shown"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"language_mode":{"type":"string","description":"fixed or page"},"language":{"type":"string","description":"Language code of the widget's own words"},"show_translations":{"type":"boolean","description":"Stored translations are shown"},"count_views":{"type":"boolean","description":"Views and clicks are counted"},"revision":{"type":"integer","description":"Goes up with every change a visitor could see"},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"installed":{"type":"boolean","description":"It was seen live on a page"},"pages_seen":{"type":"integer","description":"How many pages it was seen live on"},"seen_on":{"anyOf":[{"type":"string","description":"The first page it was seen live on, as host and path"},{"type":"null"}]},"first_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was first seen live"},{"type":"null"}]},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last seen live"},{"type":"null"}]},"fragment_bytes":{"anyOf":[{"type":"integer","description":"Compressed size of the widget at its last render, in bytes"},{"type":"null"}]},"fragment_images":{"anyOf":[{"type":"integer","description":"Images among the cards a visitor sees before scrolling"},{"type":"null"}]},"embed_url":{"type":"string","description":"The address of the widget as a page, for a frame"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_widgets_update","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Internal name, 1 to 100 characters. Required on create"},"source_kind":{"type":"string","description":"What feeds it: collection, view, tags or picked. Nothing is shown until one is chosen","enum":["collection","view","tags","picked"]},"collection_id":{"type":"string","description":"The collection that feeds it (col_...), manual or smart"},"view_id":{"type":"string","description":"The shared saved view that feeds it (vw_...)"},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it (tag_...)"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"Hand-picked testimonials (tm_...), in the order to show them, up to 100"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark","enum":["auto","light","dark"]},"font_size":{"type":"string","description":"small, medium or large","enum":["small","medium","large"]},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts","enum":["inherit","stars","hearts"]},"sort":{"type":"string","description":"source keeps the collection's or the picked order. newest, oldest and rating put pinned testimonials first","enum":["source","newest","oldest","rating"]},"tag_match":{"type":"string","description":"any (a testimonial with any of the tags) or all","enum":["any","all"]},"schema_type":{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization","enum":["Product","SoftwareApplication","Course","Book","Event","Recipe","LocalBusiness","Organization"]},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts. Default true"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown. Default true"},"show_company":{"type":"boolean","description":"Show the person's title and company. Default true"},"show_date":{"type":"boolean","description":"Show the date it was received. Default false"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address. Default true"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one. Default false"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason. Default true"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page. Default true"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on. Default false"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20. Default 8"},"accent_color":{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},"card_color":{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},"text_color":{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},"border_color":{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},"rating_color":{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},"background_color":{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},"radius":{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono","enum":["inherit_page","brand","system","system_serif","system_mono"]},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font","enum":["inherit_page","brand","system","system_serif","system_mono"]},"show_badge":{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},"custom_css":{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_name":{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},"per_view":{"type":"integer","description":"Carousel: cards in view, 1 to 4. Default 3"},"autoplay":{"type":"boolean","description":"Carousel: move by itself. A pause button is then always shown. Default false"},"interval_seconds":{"type":"integer","description":"Carousel and single quote: seconds per step, 3 to 15. Default 6"},"arrows":{"type":"boolean","description":"Carousel: previous and next buttons. Default true"},"dots":{"type":"boolean","description":"Carousel: position dots. Default true"},"loop":{"type":"boolean","description":"Carousel: go back to the start after the last card. Default true"},"columns":{"type":"integer","description":"Grid (1 to 5) and masonry (2 to 5): columns at full width. Default 3"},"gap":{"type":"string","description":"Grid and masonry: space between cards, small, medium or large","enum":["small","medium","large"]},"equal_height":{"type":"boolean","description":"Grid: cards of one row share a height. Default false"},"load_more":{"type":"boolean","description":"Grid, masonry and list: show a Load more button. Default true"},"page_size":{"type":"integer","description":"Grid, masonry and list: cards before Load more, 3 to 30. Default 9"},"avatar_position":{"type":"string","description":"List: the person left of the words, or top","enum":["left","top"]},"dividers":{"type":"boolean","description":"List: lines between testimonials in place of boxes. Default true"},"size":{"type":"string","description":"Single quote: medium, large or extra_large","enum":["medium","large","extra_large"]},"align":{"type":"string","description":"Single quote: left or center","enum":["left","center"]},"rotate":{"type":"boolean","description":"Single quote: step through up to 5 testimonials. Default false"},"rows":{"type":"integer","description":"Marquee: rows, 1 to 3. Default 1"},"speed":{"type":"string","description":"Marquee: slow, medium or fast","enum":["slow","medium","fast"]},"direction":{"type":"string","description":"Marquee: left or right","enum":["left","right"]},"avatars":{"type":"integer","description":"Avatar strip: faces shown, 1 to 8. Default 5"},"text":{"type":"string","description":"Avatar strip and rating badge: the line of text, up to 80 characters. {count} and {average} are filled in from the testimonials"},"link_url":{"type":"string","description":"Avatar strip and rating badge: an https address the whole thing links to"},"shape":{"type":"string","description":"Rating badge: compact or wide","enum":["compact","wide"]},"position":{"type":"string","description":"Corner popup: bottom_left or bottom_right","enum":["bottom_left","bottom_right"]},"delay_seconds":{"type":"integer","description":"Corner popup: seconds before the first one, 0 to 60. Default 5"},"display_seconds":{"type":"integer","description":"Corner popup: seconds each one stays, 4 to 30. Default 8"},"hide_on_phones":{"type":"boolean","description":"Corner popup: not shown on a narrow screen. Default false"},"layout":{"type":"string","description":"carousel, grid, masonry, list, single_quote, marquee, avatar_strip, rating_badge or corner_popup. Options of another layout are ignored","enum":["carousel","grid","masonry","list","single_quote","marquee","avatar_strip","rating_badge","corner_popup"]},"limit":{"type":"integer","description":"The most testimonials shown, 1 to 100. Default 12"},"language_mode":{"type":"string","description":"fixed (always the language below) or page (the language of the page it is on, when the site offers it)","enum":["fixed","page"]},"language":{"type":"string","description":"One of the site's languages: the widget's own words (Read more, Verified, dates)","enum":["en","de","es","fr","it","nl","pt","pl","sv","da","no","fi","ja","ko","zh-CN","zh-TW"]},"show_translations":{"type":"boolean","description":"Show a stored translation of each testimonial in the widget's language, on any plan. Making translations is part of Business"},"count_views":{"type":"boolean","description":"false sends nothing from the visitor's browser: views, clicks and install detection stop. Default true"}}}}}}}},"/sites/{site_id}/testimonials/widgets/{id}/duplicate.json":{"post":{"operationId":"testimonial_widgets_duplicate","summary":"Copy a widget with every setting","description":"Makes a copy with a new id and the name ending in \"copy\". The copy has its own embed code and has not been seen live anywhere. The original is not changed.","tags":["Widgets"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_widgets_list","schema":{"type":"string"}}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Widget id, e.g. wdg_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the widget's embed responds 410 and shows nothing"},"name":{"type":"string","description":"Internal name"},"layout":{"type":"string","description":"The layout"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"limit":{"type":"integer","description":"The most testimonials shown"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"language_mode":{"type":"string","description":"fixed or page"},"language":{"type":"string","description":"Language code of the widget's own words"},"show_translations":{"type":"boolean","description":"Stored translations are shown"},"count_views":{"type":"boolean","description":"Views and clicks are counted"},"revision":{"type":"integer","description":"Goes up with every change a visitor could see"},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"installed":{"type":"boolean","description":"It was seen live on a page"},"pages_seen":{"type":"integer","description":"How many pages it was seen live on"},"seen_on":{"anyOf":[{"type":"string","description":"The first page it was seen live on, as host and path"},{"type":"null"}]},"first_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was first seen live"},{"type":"null"}]},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last seen live"},{"type":"null"}]},"fragment_bytes":{"anyOf":[{"type":"integer","description":"Compressed size of the widget at its last render, in bytes"},{"type":"null"}]},"fragment_images":{"anyOf":[{"type":"integer","description":"Images among the cards a visitor sees before scrolling"},{"type":"null"}]},"embed_url":{"type":"string","description":"The address of the widget as a page, for a frame"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_widgets_duplicate","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Name of the copy. The default adds (copy)"}}}}}}}},"/sites/{site_id}/testimonials/widgets/{id}/embed.json":{"get":{"operationId":"testimonial_widgets_embed","summary":"Get the embed code of a widget and what it weighs","description":"Returns the script snippet (recommended), the pasted HTML, the frame code and the address of the public data, with the measured size of the loader script and of this widget. The pasted HTML and the frame are null for the corner popup.","tags":["Widgets"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_widgets_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"widget_id":{"type":"string","description":"The widget"},"script":{"type":"string","description":"The recommended snippet: one element and the loader script"},"html":{"anyOf":[{"type":"string","description":"Plain HTML and CSS with no script, or null for the corner popup. It does not update by itself"},{"type":"null"}]},"iframe":{"anyOf":[{"type":"string","description":"Frame code, or null for the corner popup"},{"type":"null"}]},"json_url":{"type":"string","description":"The address of the public data of the widget"},"fragment_url":{"type":"string","description":"The address the loader fetches"},"loader_url":{"type":"string","description":"The address of the loader script"},"reserve_height":{"type":"integer","description":"Pixels the snippet keeps for the widget while it loads"},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"loader_bytes":{"type":"integer","description":"Size of the loader script, in bytes"},"loader_compressed_bytes":{"type":"integer","description":"Size of the loader script as it travels, in bytes"},"fragment_bytes":{"type":"integer","description":"Size of this widget, in bytes"},"fragment_compressed_bytes":{"type":"integer","description":"Size of this widget as it travels, in bytes"},"fragment_images":{"type":"integer","description":"Images among the cards a visitor sees before scrolling"},"over_budget":{"type":"integer","description":"Bytes over the guide for one widget, 0 when under it"},"html_copied_at":{"anyOf":[{"type":"string","format":"date-time","description":"When the pasted HTML was last copied"},{"type":"null"}]},"changes_since_copied":{"anyOf":[{"type":"integer","description":"Changes to the widget since the pasted HTML was copied, or null if it never was"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_widgets_embed","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/widgets/{id}/installs.json":{"get":{"operationId":"testimonial_widgets_installs","summary":"List the pages a widget was seen live on","description":"Up to 50 pages, the newest first. Only the script and the frame can be detected.","tags":["Widgets"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_widgets_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"widget_id":{"type":"string","description":"The widget"},"installed":{"type":"boolean","description":"It was seen live on a page"},"first_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was first seen live"},{"type":"null"}]},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last seen live"},{"type":"null"}]},"pages":{"type":"array","items":{"type":"object"},"description":"Up to 50 pages: { url (host and path, never a query string), first_seen_at, last_seen_at, seen_lately (seen in the last 30 days) }"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_widgets_installs","x-permission":"analytics.read"}},"/sites/{site_id}/testimonials/widgets/{id}/restore.json":{"post":{"operationId":"testimonial_widgets_restore","summary":"Restore a widget from the trash","description":"It comes back wherever it was pasted.","tags":["Widgets"],"parameters":[{"name":"site_id","in":"path","required":true,"description":"Site id, e.g. pa_7Q2K9XH3AB","schema":{"type":"string"}},{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by testimonial_widgets_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Widget id, e.g. wdg_7Q2K9XH3AB"},"site_id":{"type":"string","description":"The site it belongs to"},"site_verified":{"type":"boolean","description":"Whether the site is verified (its tracking script was found on its own domain). Until it is, the widget's embed responds 410 and shows nothing"},"name":{"type":"string","description":"Internal name"},"layout":{"type":"string","description":"The layout"},"layout_options":{"type":"object","description":"The options of its layout, each with its value or its default"},"source_kind":{"anyOf":[{"type":"string","description":"What feeds it: collection, view, tags, picked, or null when nothing is chosen yet"},{"type":"null"}]},"collection_id":{"anyOf":[{"type":"string","description":"The collection that feeds it"},{"type":"null"}]},"view_id":{"anyOf":[{"type":"string","description":"The shared saved view that feeds it"},{"type":"null"}]},"tag_ids":{"type":"array","items":{"type":"string"},"description":"The tags that feed it"},"tag_match":{"type":"string","description":"any or all"},"testimonial_ids":{"type":"array","items":{"type":"string"},"description":"The hand-picked testimonials, in order"},"sort":{"type":"string","description":"source, newest, oldest or rating"},"limit":{"type":"integer","description":"The most testimonials shown"},"show_rating":{"type":"boolean","description":"Show the rating, as stars or hearts"},"show_photo":{"type":"boolean","description":"Show the person's photo, or their initials when there is none. A photo the consent record does not allow is never shown"},"show_company":{"type":"boolean","description":"Show the person's title and company"},"show_date":{"type":"boolean","description":"Show the date it was received"},"show_source":{"type":"boolean","description":"Name the review platform it came from, linked to the original when it has an address"},"highlight_only":{"type":"boolean","description":"Show the highlight instead of the whole text, where there is one"},"show_verified":{"type":"boolean","description":"Show the verified mark with its reason"},"video_inline":{"type":"boolean","description":"Play a video in the card, from a poster with a play button. false shows a Watch link to the public page"},"link_permalink":{"type":"boolean","description":"Link each card to the testimonial's public page, when that page is on"},"max_lines":{"type":"integer","description":"Lines of text before Read more: 0 for no limit, or 3 to 20"},"theme":{"type":"string","description":"auto (match the page it is on), light or dark"},"accent_color":{"anyOf":[{"type":"string","description":"Hex color, e.g. #d81b60. Empty inherits the brand kit"},{"type":"null"}]},"card_color":{"anyOf":[{"type":"string","description":"Hex color of the card. Empty inherits the brand kit"},{"type":"null"}]},"text_color":{"anyOf":[{"type":"string","description":"Hex color of the text. Empty inherits the brand kit"},{"type":"null"}]},"border_color":{"anyOf":[{"type":"string","description":"Hex color of the lines. Empty inherits the brand kit"},{"type":"null"}]},"rating_color":{"anyOf":[{"type":"string","description":"Hex color of the stars or hearts. Empty inherits the brand kit"},{"type":"null"}]},"background_color":{"anyOf":[{"type":"string","description":"Hex color, or transparent. A widget is transparent by default, a wall takes the brand kit's background"},{"type":"null"}]},"radius":{"anyOf":[{"type":"integer","description":"Corner radius in pixels, 0 to 24. Empty inherits the brand kit"},{"type":"null"}]},"card_border":{"type":"boolean","description":"A 1px line around each card. Default true"},"font":{"type":"string","description":"inherit_page (match the site, loads nothing), brand (the brand kit's font) or a family: system, system_serif, system_mono"},"quote_font":{"type":"string","description":"The font of the customer's words. The same choices as font"},"font_size":{"type":"string","description":"small, medium or large"},"rating_style":{"type":"string","description":"inherit (the brand kit), stars or hearts"},"show_badge":{"anyOf":[{"type":"boolean","description":"The Collected with Privatus Analytics badge. null follows the brand kit. false needs a plan that can remove it"},{"type":"null"}]},"custom_css":{"anyOf":[{"type":"string","description":"CSS applied inside the embed after everything else, up to 20,000 characters. Business and up. It is checked and restricted before it is used"},{"type":"null"}]},"rich_snippets":{"type":"boolean","description":"Add review markup (JSON-LD) for search engines. It makes a page eligible for rich results. Search engines decide whether to show stars"},"schema_type":{"anyOf":[{"type":"string","description":"What the reviews are about: Product, SoftwareApplication, Course, Book, Event, Recipe, LocalBusiness or Organization"},{"type":"null"}]},"schema_name":{"anyOf":[{"type":"string","description":"Its name, up to 120 characters. The default is the site's name"},{"type":"null"}]},"language_mode":{"type":"string","description":"fixed or page"},"language":{"type":"string","description":"Language code of the widget's own words"},"show_translations":{"type":"boolean","description":"Stored translations are shown"},"count_views":{"type":"boolean","description":"Views and clicks are counted"},"revision":{"type":"integer","description":"Goes up with every change a visitor could see"},"showing":{"type":"integer","description":"How many testimonials it shows right now"},"views_30d":{"type":"integer","description":"Views in the last 30 days"},"clicks_30d":{"type":"integer","description":"Clicks in the last 30 days"},"installed":{"type":"boolean","description":"It was seen live on a page"},"pages_seen":{"type":"integer","description":"How many pages it was seen live on"},"seen_on":{"anyOf":[{"type":"string","description":"The first page it was seen live on, as host and path"},{"type":"null"}]},"first_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was first seen live"},{"type":"null"}]},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was last seen live"},{"type":"null"}]},"fragment_bytes":{"anyOf":[{"type":"integer","description":"Compressed size of the widget at its last render, in bytes"},{"type":"null"}]},"fragment_images":{"anyOf":[{"type":"integer","description":"Images among the cards a visitor sees before scrolling"},{"type":"null"}]},"embed_url":{"type":"string","description":"The address of the widget as a page, for a frame"},"trashed":{"type":"boolean","description":"It is in the trash"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time","description":"When it was moved to the trash"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","description":"When it was made"},"updated_at":{"type":"string","format":"date-time","description":"When it last changed"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"testimonial_widgets_restore","x-permission":"content.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/workspaces/{workspace_id}/white_label.json":{"get":{"operationId":"white_label_get","summary":"Get the white label brand","description":"Returns the workspace's white label branding. Fields are workspace_id (ws_...), brand_name, brand_logo_url and brand_color (a hex color such as #06755b), each null when unset, hide_branding, available (true when the plan includes white label, which is Business and above) and active (true when branding is set and in effect). The branding replaces Privatus Analytics on shared dashboards, embeds, status pages and email reports. Requires workspace.manage.","tags":["Workspaces"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"workspace_id":{"type":"string"},"brand_name":{"anyOf":[{"type":"string","description":"Name shown instead of Privatus Analytics"},{"type":"null"}]},"brand_logo_url":{"anyOf":[{"type":"string","description":"Logo image URL"},{"type":"null"}]},"brand_color":{"anyOf":[{"type":"string","description":"Accent color"},{"type":"null"}]},"hide_branding":{"type":"boolean","description":"Privatus Analytics branding is hidden"},"available":{"type":"boolean","description":"The plan includes white label"},"active":{"type":"boolean","description":"The brand is currently applied"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"white_label_get","x-permission":"workspace.manage"},"patch":{"operationId":"white_label_update","summary":"Set the white label brand for shared dashboards and email reports (Business)","description":"Sets the workspace's white label branding. Business plan only, otherwise it fails with a plan error. Only the inputs you send change, and an empty string clears brand_name, brand_logo_url or brand_color. brand_logo_url must be an https URL to an image and brand_color a hex color such as #06755b. hide_branding true removes the Privatus Analytics link from shared dashboards, embeds and status pages and the logo from email reports. The change applies immediately to existing share links. Requires workspace.manage. Returns the branding (see white_label_get).","tags":["Workspaces"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"workspace_id":{"type":"string"},"brand_name":{"anyOf":[{"type":"string","description":"Name shown instead of Privatus Analytics"},{"type":"null"}]},"brand_logo_url":{"anyOf":[{"type":"string","description":"Logo image URL"},{"type":"null"}]},"brand_color":{"anyOf":[{"type":"string","description":"Accent color"},{"type":"null"}]},"hide_branding":{"type":"boolean","description":"Privatus Analytics branding is hidden"},"available":{"type":"boolean","description":"The plan includes white label"},"active":{"type":"boolean","description":"The brand is currently applied"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"white_label_update","x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"brand_name":{"type":"string","description":"Name shown instead of Privatus Analytics (blank removes it)"},"brand_logo_url":{"type":"string","description":"https URL of the logo image. An empty string removes it."},"brand_color":{"type":"string","description":"Accent color as a hex code such as"},"hide_branding":{"type":"boolean","description":"Remove the Privatus Analytics link from shared dashboards, embeds and status pages, and the Privatus Analytics logo from email reports"}}}}}}}},"/workspaces/{workspace_id}/security.json":{"get":{"operationId":"workspace_security_get","summary":"Get workspace security settings","description":"Returns the workspace security policy. Fields are workspace_id (ws_...), enforce_2fa (members must use two-factor authentication), login_methods (the allowed ones from password, magic_link, passkey, google, github, apple and sso), session_ttl_hours (sign-out after this many hours, null for no limit), app_ip_allowlist (IPs or CIDR ranges allowed to use the app and API, empty means anywhere) and support_access_until (ISO 8601 time until which Privatus Analytics support may view the workspace, null when no access is granted). Requires workspace.manage.","tags":["Workspaces"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"workspace_id":{"type":"string"},"enforce_2fa":{"type":"boolean","description":"Members must set up 2FA"},"login_methods":{"type":"array","items":{"type":"string"},"description":"Allowed login methods"},"session_ttl_hours":{"anyOf":[{"type":"integer","description":"Session lifetime (null = none)"},{"type":"null"}]},"app_ip_allowlist":{"type":"array","items":{"type":"string"},"description":"Allowed IPs/CIDRs (empty = anywhere)"},"support_access_until":{"anyOf":[{"type":"string","format":"date-time","description":"Privatus Analytics support may view the workspace until"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"workspace_security_get","x-permission":"workspace.manage"},"patch":{"operationId":"workspace_security_update","summary":"Update workspace security settings (2FA, login methods, session lifetime, IP allowlist, support access)","description":"Changes the workspace security policy, only the inputs you send. enforce_2fa true requires every member to use two-factor authentication and needs the Business plan. login_methods replaces the allowed list with values from password, magic_link, passkey, google, github, apple and sso, and removing a method signs out members' remembered logins so they must log in again. session_ttl_hours signs members out after that many hours (0 removes the limit). app_ip_allowlist replaces the list of IPs or CIDR ranges allowed to reach the app and API (Business plan, an empty list means anywhere) and is refused if it would exclude the IP of the caller, so you cannot lock yourself out. support_access true lets Privatus Analytics support view the workspace for 7 days and false withdraws that access. Requires workspace.manage. Returns the policy (see workspace_security_get).","tags":["Workspaces"],"parameters":[{"name":"workspace_id","in":"path","required":true,"description":"Workspace id, e.g. ws_7Q2K9XH3AB","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"workspace_id":{"type":"string"},"enforce_2fa":{"type":"boolean","description":"Members must set up 2FA"},"login_methods":{"type":"array","items":{"type":"string"},"description":"Allowed login methods"},"session_ttl_hours":{"anyOf":[{"type":"integer","description":"Session lifetime (null = none)"},{"type":"null"}]},"app_ip_allowlist":{"type":"array","items":{"type":"string"},"description":"Allowed IPs/CIDRs (empty = anywhere)"},"support_access_until":{"anyOf":[{"type":"string","format":"date-time","description":"Privatus Analytics support may view the workspace until"},{"type":"null"}]}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enforce_2fa":{"type":"boolean","description":"Require members to set up 2FA"},"login_methods":{"type":"array","items":{"type":"string","enum":["password","magic_link","passkey","google","github","apple","sso"]},"description":"Allowed login methods, any of password, magic_link, passkey, google, github, apple and sso. Replaces the current list. Removing a method signs out members who used it."},"session_ttl_hours":{"type":"integer","description":"Sign members out after this many hours. 0 removes the limit."},"app_ip_allowlist":{"type":"array","items":{"type":"string"},"description":"IP addresses or CIDR ranges (for example 203.0.113.7 or 198.51.100.0/24) allowed to use the app and API. Business plan. An empty list allows anywhere. Refused if it would exclude your own IP."},"support_access":{"type":"boolean","description":"true lets Privatus Analytics support view the workspace for 7 days. false withdraws access."}}}}}}}},"/workspaces.json":{"post":{"operationId":"workspaces_create","summary":"Create a workspace (you become the owner)","tags":["Workspaces"],"parameters":[],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Workspace id, e.g. ws_7Q2K9XH3AB"},"name":{"type":"string"},"timezone":{"type":"string","description":"Default reporting timezone"},"currency":{"type":"string","description":"Default currency"},"plan":{"type":"string","description":"free, pro, business or enterprise"},"plan_events":{"type":"integer","description":"Events per month included in the plan"},"benchmarks":{"type":"boolean","description":"Whether the workspace's sites take part in the benchmarks across all sites and are shown them"},"subscription_status":{"type":"string"},"trial_ends_at":{"type":"string","format":"date-time","description":"When the workspace's 14-day Pro trial ends. While it runs, plan stays free and the workspace has Pro's limits and 250k events. null when there is no trial running"},"role":{"type":"string","description":"Your role in this workspace"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Workspace name","examples":["Acme Inc"]},"timezone":{"type":"string","description":"Default reporting timezone (defaults to the user's)"},"currency":{"type":"string","description":"Default currency (ISO 4217)","default":"USD"},"how_heard":{"type":"string","description":"How you heard about us"}},"required":["name"]}}}}},"get":{"operationId":"workspaces_list","summary":"List your workspaces","description":"Lists the workspaces the caller belongs to, ordered by name. An API token or MCP connection only sees the one workspace it was issued for. Each item has id (ws_..., used as workspace_id by most tools), name, timezone, currency, plan, plan_events, subscription_status and role (the caller's role). Call sites_list with a workspace id next to find site ids. Creating a workspace is only possible in the app.","tags":["Workspaces"],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Workspace id, e.g. ws_7Q2K9XH3AB"},"name":{"type":"string"},"timezone":{"type":"string","description":"Default reporting timezone"},"currency":{"type":"string","description":"Default currency"},"plan":{"type":"string","description":"free, pro, business or enterprise"},"plan_events":{"type":"integer","description":"Events per month included in the plan"},"benchmarks":{"type":"boolean","description":"Whether the workspace's sites take part in the benchmarks across all sites and are shown them"},"subscription_status":{"type":"string"},"trial_ends_at":{"type":"string","format":"date-time","description":"When the workspace's 14-day Pro trial ends. While it runs, plan stays free and the workspace has Pro's limits and 250k events. null when there is no trial running"},"role":{"type":"string","description":"Your role in this workspace"},"created_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"workspaces_list"}},"/workspaces/{id}.json":{"delete":{"operationId":"workspaces_delete","summary":"Delete a workspace and all its sites (owner only, cancels any subscription)","description":"Deletes a workspace together with all of its sites. It is a soft delete, everything disappears at once and is permanently purged after 7 days, so treat it as irreversible. Only the owner can do it, and confirm must be the workspace's exact name (case sensitive). A live paid subscription is canceled immediately first, and if that cancellation fails nothing is deleted. Pending site transfers from the workspace are canceled. Members lose access. Use workspaces_get to read the name. Requires workspace.manage and the owner role. Returns the workspace.","tags":["Workspaces"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by workspaces_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Workspace id, e.g. ws_7Q2K9XH3AB"},"name":{"type":"string"},"timezone":{"type":"string","description":"Default reporting timezone"},"currency":{"type":"string","description":"Default currency"},"plan":{"type":"string","description":"free, pro, business or enterprise"},"plan_events":{"type":"integer","description":"Events per month included in the plan"},"benchmarks":{"type":"boolean","description":"Whether the workspace's sites take part in the benchmarks across all sites and are shown them"},"subscription_status":{"type":"string"},"trial_ends_at":{"type":"string","format":"date-time","description":"When the workspace's 14-day Pro trial ends. While it runs, plan stays free and the workspace has Pro's limits and 250k events. null when there is no trial running"},"role":{"type":"string","description":"Your role in this workspace"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"string","description":"The workspace's exact name as shown by workspaces_get. Case sensitive."}},"required":["confirm"]}}}}},"get":{"operationId":"workspaces_get","summary":"Get a workspace","description":"Returns one workspace by its public id (ws_..., from workspaces_list). Fields are id, name, timezone (IANA name), currency (ISO 4217), plan (free, pro, business or enterprise), plan_events (the monthly event allowance of the plan), subscription_status (none, trialing, active, past_due, paused or canceled), role (the caller's role in it) and created_at. Use billing_get for full billing details and billing_usage for this month's usage. Any member can read it.","tags":["Workspaces"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by workspaces_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Workspace id, e.g. ws_7Q2K9XH3AB"},"name":{"type":"string"},"timezone":{"type":"string","description":"Default reporting timezone"},"currency":{"type":"string","description":"Default currency"},"plan":{"type":"string","description":"free, pro, business or enterprise"},"plan_events":{"type":"integer","description":"Events per month included in the plan"},"benchmarks":{"type":"boolean","description":"Whether the workspace's sites take part in the benchmarks across all sites and are shown them"},"subscription_status":{"type":"string"},"trial_ends_at":{"type":"string","format":"date-time","description":"When the workspace's 14-day Pro trial ends. While it runs, plan stays free and the workspace has Pro's limits and 250k events. null when there is no trial running"},"role":{"type":"string","description":"Your role in this workspace"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"workspaces_get"},"patch":{"operationId":"workspaces_update","summary":"Update workspace settings","description":"Changes a workspace's name, default timezone, default currency or whether it takes part in benchmarks, only the inputs you send. timezone is an IANA name such as Europe/Berlin and currency is a 3-letter ISO 4217 code. These are defaults for new sites, they do not change existing sites (use sites_update for those). Requires workspace.manage. Returns the workspace (see workspaces_get).","tags":["Workspaces"],"parameters":[{"name":"id","in":"path","required":true,"description":"Id of the item to act on, the id field returned by workspaces_list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Workspace id, e.g. ws_7Q2K9XH3AB"},"name":{"type":"string"},"timezone":{"type":"string","description":"Default reporting timezone"},"currency":{"type":"string","description":"Default currency"},"plan":{"type":"string","description":"free, pro, business or enterprise"},"plan_events":{"type":"integer","description":"Events per month included in the plan"},"benchmarks":{"type":"boolean","description":"Whether the workspace's sites take part in the benchmarks across all sites and are shown them"},"subscription_status":{"type":"string"},"trial_ends_at":{"type":"string","format":"date-time","description":"When the workspace's 14-day Pro trial ends. While it runs, plan stays free and the workspace has Pro's limits and 250k events. null when there is no trial running"},"role":{"type":"string","description":"Your role in this workspace"},"created_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-mcp-tool":"workspaces_update","x-permission":"workspace.manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Workspace name."},"timezone":{"type":"string","description":"IANA timezone name such as Europe/Berlin. Default for new sites only."},"currency":{"type":"string","description":"3-letter ISO 4217 code such as USD. Default for new sites only."},"benchmarks":{"type":"boolean","description":"false to leave this workspace's sites out of the benchmarks across all sites and to hide the comparisons, true to take part again (the default)."}}}}}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{"type":"object"}}}}}}}}