{
  "openapi": "3.0.3",
  "info": {
    "title": "Salience (LogLens) Public API",
    "version": "1",
    "description": "Server-log analytics for SEO and security. Full reference: https://salience.com/docs/api/ \u2014 agent playbook: https://salience.com/llms/agents.md. Operations come from the reference; query parameters are reviewed per endpoint against the API handlers (x-salience-contract). Operations marked typed carry typed evidence schemas (Site Checks, URL detail and search, index coverage); operations marked parameters still describe their response as a generic object until its fields are reviewed. Responses may gain fields."
  },
  "servers": [
    {
      "url": "https://api.salience.com"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key (llapi_\u2026) from Organization \u2192 API Access. Keys are read-only unless created with the read_write scope."
      }
    }
  },
  "paths": {
    "/public/v1/billing": {
      "get": {
        "summary": "Billing Status",
        "description": "The organisation's plan, trial state, whether a card is on file, a Stripe customer-portal link when a customer exists, and the paid plans a trial or checkout can target.",
        "operationId": "get_billing",
        "tags": [
          "Billing Status"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-billing"
        }
      }
    },
    "/public/v1/billing/checkout": {
      "post": {
        "summary": "Start Checkout",
        "description": "Create a Stripe Checkout session for a plan and return its URL. The customer opens the link in a browser and enters card details on Stripe's page; nothing about the card passes through this API. During a no-card trial the remaining trial days and the first-month discount apply; an organisation with a live subscription is switched in place instead and gets no URL. Requires a key with the read_write scope (a read-only key gets a 403).",
        "operationId": "post_billing_checkout",
        "tags": [
          "Start Checkout"
        ],
        "x-salience-contract": "parameters",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#start-checkout"
        }
      }
    },
    "/public/v1/billing/trial": {
      "post": {
        "summary": "Start Trial",
        "description": "Start the one 14-day no-card trial of a paid plan for a Free organisation. Same rules as the dashboard: one trial per user account and per organisation; a 409 with a code explains a refusal. Requires a key with the read_write scope (a read-only key gets a 403).",
        "operationId": "post_billing_trial",
        "tags": [
          "Start Trial"
        ],
        "x-salience-contract": "parameters",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#start-trial"
        }
      }
    },
    "/public/v1/websites": {
      "get": {
        "summary": "List Websites",
        "description": "Returns all websites accessible to your API key.",
        "operationId": "get_websites",
        "tags": [
          "List Websites"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#list-websites"
        }
      },
      "post": {
        "summary": "Create Website",
        "description": "Register a website in the key's organisation, mint its ingest key and detect the hosting platform. This is what the MCP create_website tool calls. Requires a key with the read_write scope (a read-only key gets a 403).",
        "operationId": "post_websites",
        "tags": [
          "Create Website"
        ],
        "x-salience-contract": "parameters",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#create-website"
        }
      }
    },
    "/public/v1/websites/{website_id}/ai-funnel": {
      "get": {
        "summary": "AI Funnel",
        "description": "Two reports on what AI gives back. operators: per AI company, the search/answer fetches it made (fetches), its training crawls (training_requests), the human visitors who arrived from its answers (referrals, detected from the referrer host or a utm_source=chatgpt.com-style tag) and fetches_per_visit \u2014 the scrape-to-referral ratio. discovery: Search Console pages with at least min_impressions impressions (28 days) that no AI search or answer bot fetched in the period \u2014 invisible to AI search. Requires a connected Search Console property; otherwise discovery.gsc_connected is false.",
        "operationId": "get_websites_website_id_ai_funnel",
        "tags": [
          "AI Funnel"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 720. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 720,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "countries",
            "in": "query",
            "required": false,
            "description": "Comma-separated ISO country codes, e.g. GB,US.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_impressions",
            "in": "query",
            "required": false,
            "description": "Minimum 28-day Search Console impressions for discovery gaps.",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-ai-funnel"
        }
      }
    },
    "/public/v1/websites/{website_id}/ai-landing": {
      "get": {
        "summary": "AI Landing Pages",
        "description": "Which pages AI assistants (ChatGPT, Perplexity, Claude, Gemini, Copilot \u2026) send people to, and what those visitors do next. A visit is AI-referred when a human request\u2019s referrer host is an AI assistant (chatgpt.com, perplexity.ai, claude.ai, gemini.google.com, copilot.microsoft.com \u2026) or its URL carries a utm_source naming one (utm_source=chatgpt.com). totals: ai_referred_visits, unique_paths, operators, humans_total, share_of_human_traffic_pct and previous (the equal period before, with delta_pct). by_operator: visits, unique paths and the most-cited page per assistant. pages (top 200 by vis",
        "operationId": "get_websites_website_id_ai_landing",
        "tags": [
          "AI Landing Pages"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 720. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 720,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "countries",
            "in": "query",
            "required": false,
            "description": "Comma-separated ISO country codes, e.g. GB,US.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "operator",
            "in": "query",
            "required": false,
            "description": "One AI assistant operator, e.g. OpenAI.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum pages, clamped to 1-500.",
            "schema": {
              "type": "integer",
              "default": 200,
              "minimum": 1,
              "maximum": 500
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-ai-landing"
        }
      }
    },
    "/public/v1/websites/{website_id}/alerts": {
      "get": {
        "summary": "Alert History",
        "description": "Fired alerts for a website (anomaly detector, error spikes, new-bot detection, etc.). Sorted most-recent first; includes a count of unacknowledged alerts in the last 30 days.",
        "operationId": "get_websites_website_id_alerts",
        "tags": [
          "Alert History"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Selects the window ending now; switches to the paged selected-window listing.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start of a selected window (with end).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end of a selected window (with start).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Alert type filter.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "acknowledged",
            "in": "query",
            "required": false,
            "description": "Acknowledgement filter.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum alerts when no time parameter is given.",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 500
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page of a selected window (with hours, start or end).",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Page size of a selected window.",
            "schema": {
              "type": "integer",
              "default": 100,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "selection_version",
            "in": "query",
            "required": false,
            "description": "Required with start and end for pages after the first.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "view",
            "in": "query",
            "required": false,
            "description": "Group alerts into incidents.",
            "schema": {
              "type": "string",
              "enum": [
                "incidents"
              ]
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#list-alerts"
        }
      }
    },
    "/public/v1/websites/{website_id}/alerts/config": {
      "get": {
        "summary": "Alert Configuration",
        "description": "Returns the website's current alert configuration \u2014 which alert types are enabled, how often each runs, suppression lists, email/webhook settings, and the anomaly-detector baseline status.",
        "operationId": "get_websites_website_id_alerts_config",
        "tags": [
          "Alert Configuration"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-alert-config"
        }
      }
    },
    "/public/v1/websites/{website_id}/alerts/{alert_id}/acknowledge": {
      "post": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "post_websites_website_id_alerts_alert_id_acknowledge",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "alert_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#write-side"
        }
      }
    },
    "/public/v1/websites/{website_id}/bots": {
      "get": {
        "summary": "Get Bots",
        "description": "Returns bot analytics including identification and verification status.",
        "operationId": "get_websites_website_id_bots",
        "tags": [
          "Get Bots"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "split_variants",
            "in": "query",
            "required": false,
            "description": "true, 1 or yes lists Googlebot Desktop and Smartphone separately.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-bots"
        }
      }
    },
    "/public/v1/websites/{website_id}/bots/access": {
      "get": {
        "summary": "Get Bot Access",
        "description": "Served vs rejected, per bot. For each bot: served (2xx/3xx) and rejected (401/403/429/451) requests, each split into verified and unverified identity; rejected_by_status (which codes the site used); rejected_paths (top 5 paths where rejections happened, with status); access = mixed (served on some requests, rejected on others \u2014 listed first), rejected, served or none (only 404s/errors); and rejected_who = impersonators_only, verified_only, both or unverifiable. Blocking only impersonators is the healthy pattern; verified_only means a rule is turning away the real bot. hours defaults to 168; li",
        "operationId": "get_websites_website_id_bots_access",
        "tags": [
          "Get Bot Access"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 168. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 168,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "countries",
            "in": "query",
            "required": false,
            "description": "Comma-separated ISO country codes, e.g. GB,US.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum bots returned.",
            "schema": {
              "type": "integer",
              "default": 200,
              "minimum": 1
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-bot-access"
        }
      }
    },
    "/public/v1/websites/{website_id}/bots/{bot_name}/suppress": {
      "post": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "post_websites_website_id_bots_bot_name_suppress",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bot_name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#write-side"
        }
      },
      "delete": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "delete_websites_website_id_bots_bot_name_suppress",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bot_name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#write-side"
        }
      }
    },
    "/public/v1/websites/{website_id}/checks": {
      "get": {
        "summary": "Recommendations, Insights & Health NEW",
        "description": "Programmatic access to the same actionable recommendations, AI-generated insights, real-time feed, and site/ingestion health you see in the dashboard. All read-only (GET), authenticated with your API key like every other endpoint.",
        "operationId": "get_websites_website_id_checks",
        "tags": [
          "Recommendations, Insights & Health NEW"
        ],
        "x-salience-contract": "typed",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "checks": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Stable check id."
                          },
                          "title": {
                            "type": "string",
                            "nullable": true
                          },
                          "category": {
                            "type": "string",
                            "nullable": true
                          },
                          "verdict": {
                            "type": "string",
                            "enum": [
                              "pass",
                              "warn",
                              "fail",
                              "unknown",
                              "not_applicable"
                            ],
                            "description": "pass | warn | fail | unknown (could not be evaluated this run; never a pass) | not_applicable (does not apply to this website)"
                          },
                          "weight": {
                            "type": "integer"
                          },
                          "evidence": {
                            "type": "object",
                            "properties": {
                              "note": {
                                "type": "string",
                                "description": "Explanation of the verdict."
                              },
                              "outcome": {
                                "type": "string",
                                "description": "Retrieval or content outcome for delivery probes, e.g. ok, partial, missing, blocked, server_error, http_error, invalid, unreachable, unconfirmed or not_checked. A warn with outcome ok and advisories is delivery advice, not a retrieval failure."
                              },
                              "requested_url": {
                                "type": "string",
                                "description": "URL the checker requested.",
                                "nullable": true
                              },
                              "final_url": {
                                "type": "string",
                                "description": "URL that produced the final response after any redirects.",
                                "nullable": true
                              },
                              "redirects": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "additionalProperties": true
                                },
                                "description": "Redirect hops followed by the checker."
                              },
                              "status": {
                                "type": "integer",
                                "description": "HTTP status the checker received.",
                                "nullable": true
                              },
                              "advisories": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "Delivery improvements (cookies, caching, content type); advisory only."
                              },
                              "notes": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "Informational observations that do not affect the verdict."
                              }
                            },
                            "additionalProperties": true,
                            "description": "Check-specific evidence. Keys vary by check; clients must tolerate keys not listed here."
                          },
                          "updated_at": {
                            "type": "string",
                            "description": "When this verdict was last evaluated (UTC ISO 8601).",
                            "nullable": true
                          },
                          "previous_verdict": {
                            "type": "string",
                            "enum": [
                              "pass",
                              "warn",
                              "fail",
                              "unknown",
                              "not_applicable",
                              null
                            ],
                            "description": "Verdict before the most recent change.",
                            "nullable": true
                          },
                          "flipped_at": {
                            "type": "string",
                            "description": "When the verdict last changed.",
                            "nullable": true
                          }
                        },
                        "additionalProperties": true,
                        "required": [
                          "id",
                          "verdict",
                          "weight",
                          "evidence",
                          "updated_at"
                        ]
                      },
                      "description": "Sorted fail, warn, unknown, pass, not_applicable, then by weight descending."
                    },
                    "summary": {
                      "type": "object",
                      "properties": {
                        "pass": {
                          "type": "integer"
                        },
                        "warn": {
                          "type": "integer"
                        },
                        "fail": {
                          "type": "integer"
                        },
                        "unknown": {
                          "type": "integer"
                        },
                        "not_applicable": {
                          "type": "integer"
                        }
                      },
                      "additionalProperties": true,
                      "description": "Count per verdict. Only verdicts that occur are present; a missing key means zero."
                    },
                    "evaluated": {
                      "type": "boolean",
                      "description": "false until a first evaluation has stored any verdict. Not a pass."
                    }
                  },
                  "additionalProperties": true,
                  "required": [
                    "checks",
                    "summary",
                    "evaluated"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-checks"
        }
      }
    },
    "/public/v1/websites/{website_id}/checks/history": {
      "get": {
        "summary": "Recommendations, Insights & Health NEW",
        "description": "Programmatic access to the same actionable recommendations, AI-generated insights, real-time feed, and site/ingestion health you see in the dashboard. All read-only (GET), authenticated with your API key like every other endpoint.",
        "operationId": "get_websites_website_id_checks_history",
        "tags": [
          "Recommendations, Insights & Health NEW"
        ],
        "x-salience-contract": "typed",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "History window in days, clamped to 1-90.",
            "schema": {
              "type": "integer",
              "default": 30,
              "minimum": 1,
              "maximum": 90
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "history": {
                      "type": "object",
                      "description": "Per check id, the stored daily verdicts in the window, oldest first. Days without a stored verdict are absent.",
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "date": {
                              "type": "string",
                              "pattern": "^[0-9]{8}$",
                              "description": "UTC day, YYYYMMDD."
                            },
                            "verdict": {
                              "type": "string",
                              "enum": [
                                "pass",
                                "warn",
                                "fail",
                                "unknown",
                                "not_applicable",
                                null
                              ],
                              "description": "pass | warn | fail | unknown (could not be evaluated this run; never a pass) | not_applicable (does not apply to this website)",
                              "nullable": true
                            }
                          },
                          "additionalProperties": true,
                          "required": [
                            "date",
                            "verdict"
                          ]
                        }
                      }
                    },
                    "changes": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "check_id": {
                            "type": "string"
                          },
                          "date": {
                            "type": "string",
                            "pattern": "^[0-9]{8}$",
                            "description": "UTC day of the change, YYYYMMDD."
                          },
                          "from": {
                            "type": "string",
                            "enum": [
                              "pass",
                              "warn",
                              "fail",
                              "unknown",
                              "not_applicable",
                              null
                            ],
                            "description": "pass | warn | fail | unknown (could not be evaluated this run; never a pass) | not_applicable (does not apply to this website)",
                            "nullable": true
                          },
                          "to": {
                            "type": "string",
                            "enum": [
                              "pass",
                              "warn",
                              "fail",
                              "unknown",
                              "not_applicable",
                              null
                            ],
                            "description": "pass | warn | fail | unknown (could not be evaluated this run; never a pass) | not_applicable (does not apply to this website)",
                            "nullable": true
                          }
                        },
                        "additionalProperties": true,
                        "required": [
                          "check_id",
                          "date",
                          "from",
                          "to"
                        ]
                      },
                      "description": "Derived verdict changes, newest first. Changes into or out of unknown are included."
                    },
                    "days": {
                      "type": "integer",
                      "description": "Window actually used after clamping."
                    }
                  },
                  "additionalProperties": true,
                  "required": [
                    "history",
                    "changes",
                    "days"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-checks"
        }
      }
    },
    "/public/v1/websites/{website_id}/crawl-audit": {
      "get": {
        "summary": "Segments",
        "description": "Saved page groups defined in the dashboard (SEO \u2192 Segments): a name and rules \u2014 prefix, contains, exact, regex on the path, or query on the query string \u2014 with optional exclusions and nesting. They are evaluated on the logs at query time, so they apply to all history. Add ?segment=<segment_id> to a segment-aware read \u2014 /summary, /traffic, /bots, /paths, /llms, /ai-funnel, /ai-landing, /crawl-report, /crawl-audit, /url and the others listed under Common Query Parameters \u2014 to filter it to one group; other reads ignore it. /segments-breakdown returns every segment (plus _all) with requests, human",
        "operationId": "get_websites_website_id_crawl_audit",
        "tags": [
          "Segments"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 720. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 720,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "crawl_id",
            "in": "query",
            "required": false,
            "description": "A specific crawl; default is the latest ready crawl.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum rows per finding.",
            "schema": {
              "type": "integer",
              "default": 100
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-crawl-audit"
        }
      }
    },
    "/public/v1/websites/{website_id}/crawl-links": {
      "get": {
        "summary": "Link Map (crawl-links)",
        "description": "The internal link graph of the latest Salience crawl, crossed with your logs. Every page is a node with an internal pagerank (0\u20131, the most-linked-into page = 1), inlinks, outlinks, click depth, HTTP status, and the verified search-bot / AI / human hits in the period; edges are [source_id, target_id] pairs between the returned nodes. Nodes are the top limit by PageRank (public API default 200, clamped to 50\u20133,000); the homepage is always included. The prefix and max_depth filters are not currently applied by the public API, so filter the returned nodes yourself. Two lists come with it: linked_",
        "operationId": "get_websites_website_id_crawl_links",
        "tags": [
          "Link Map (crawl-links)"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 720. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 720,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "crawl_id",
            "in": "query",
            "required": false,
            "description": "A specific crawl; default is the latest ready crawl.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum nodes, clamped to 50-3000.",
            "schema": {
              "type": "integer",
              "default": 200,
              "minimum": 50,
              "maximum": 3000
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-crawl-links"
        }
      }
    },
    "/public/v1/websites/{website_id}/crawl-report": {
      "get": {
        "summary": "Crawl Join",
        "description": "The latest site crawl (an uploaded export from your site crawler, a URL list, or Salience's own crawl \u2014 managed in the dashboard under SEO \u2192 Crawl Join) crossed with the logs for the period. summary counts pages, active (fetched by a verified search bot), ignored (indexable and linked but never fetched) and orphans (fetched but not linked from the site). ignored is sorted by Search Console impressions, inlinks and depth; by_depth / by_inlinks give crawl attention per bucket. Returns available: false, reason: \"no_crawl\" until a crawl exists. Defaults to the latest ready crawl; pass crawl_id= (f",
        "operationId": "get_websites_website_id_crawl_report",
        "tags": [
          "Crawl Join"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 720. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 720,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "crawl_id",
            "in": "query",
            "required": false,
            "description": "A specific crawl; default is the latest ready crawl.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum rows per list.",
            "schema": {
              "type": "integer",
              "default": 200
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-crawl-report"
        }
      }
    },
    "/public/v1/websites/{website_id}/crawls": {
      "get": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "get_websites_website_id_crawls",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-crawls"
        }
      }
    },
    "/public/v1/websites/{website_id}/crawls/run": {
      "post": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "post_websites_website_id_crawls_run",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-crawls"
        }
      }
    },
    "/public/v1/websites/{website_id}/crawls/{crawl_id}/cancel": {
      "post": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "post_websites_website_id_crawls_crawl_id_cancel",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "crawl_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-crawls"
        }
      }
    },
    "/public/v1/websites/{website_id}/devices": {
      "get": {
        "summary": "Get Devices",
        "description": "Returns device, browser, and operating system analytics.",
        "operationId": "get_websites_website_id_devices",
        "tags": [
          "Get Devices"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-devices"
        }
      }
    },
    "/public/v1/websites/{website_id}/exports": {
      "get": {
        "summary": "List Exports",
        "description": "List your background export jobs for a website with status, row count, file size, and a presigned download URL for completed jobs (URL valid for 7 days).",
        "operationId": "get_websites_website_id_exports",
        "tags": [
          "List Exports"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#create-seo-report"
        }
      },
      "post": {
        "summary": "Create Export",
        "description": "Queue a new background export job. The export runs asynchronously; poll List Exports for status, or wait for the email notification when it's ready. Files are CSV and links expire after 7 days.",
        "operationId": "post_websites_website_id_exports",
        "tags": [
          "Create Export"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#create-export"
        }
      }
    },
    "/public/v1/websites/{website_id}/exports/{job_id}/download": {
      "get": {
        "summary": "List Exports",
        "description": "List your background export jobs for a website with status, row count, file size, and a presigned download URL for completed jobs (URL valid for 7 days).",
        "operationId": "get_websites_website_id_exports_job_id_download",
        "tags": [
          "List Exports"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redirect",
            "in": "query",
            "required": false,
            "description": "false returns the presigned URL as JSON instead of redirecting.",
            "schema": {
              "type": "string",
              "enum": [
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "With redirect=false: JSON with download_url (a short-lived presigned URL) and expires_in seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "302": {
            "description": "Redirect to a short-lived download URL (default)."
          },
          "404": {
            "description": "Export job not found for this website."
          },
          "409": {
            "description": "Export not ready."
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#list-exports"
        }
      }
    },
    "/public/v1/websites/{website_id}/ga/overview": {
      "get": {
        "summary": "Google Analytics Overview",
        "description": "Google Analytics 4 is a connected source, like Search Console \u2014 not an ingest path. It adds the human outcomes the logs cannot see (sessions, active users, engagement, key events, revenue) next to the request stream. This endpoint returns the period totals against the previous equal period with deltas, a daily series that carries log_humans alongside the GA numbers, the top 25 traffic sources, ai_sources (sessions and outcomes from AI assistants; operator names match AI Landing Pages) and measurement_gap: human page requests in your logs against GA pageviews, with unmeasured_pct \u2014 the share of",
        "operationId": "get_websites_website_id_ga_overview",
        "tags": [
          "Google Analytics Overview"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24. Ignored when both start and end are given. Google Analytics counts whole days ending on the latest synced day (window.lag_days).",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-ga-overview"
        }
      }
    },
    "/public/v1/websites/{website_id}/ga/pages": {
      "get": {
        "summary": "Google Analytics Pages",
        "description": "GA4 landing pages for the period, sorted by sessions. Each row carries sessions, engaged sessions, engagement rate, key events (GA4 conversions), revenue, pageviews, active users and average engagement time, plus ai_sessions (sessions that landed here from an AI assistant) and search_sessions (from organic search). path is the GA landing-page path without the query string, so it lines up with URL detail, whose ga section holds the same figures for one page together with its own measurement gap.",
        "operationId": "get_websites_website_id_ga_pages",
        "tags": [
          "Google Analytics Pages"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24. Ignored when both start and end are given. Google Analytics counts whole days ending on the latest synced day (window.lag_days).",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum pages, clamped to 1-1000.",
            "schema": {
              "type": "integer",
              "default": 100,
              "minimum": 1,
              "maximum": 1000
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Case-insensitive path substring.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-ga-pages"
        }
      }
    },
    "/public/v1/websites/{website_id}/geography": {
      "get": {
        "summary": "Get Geography",
        "description": "Returns geographic distribution of traffic by country and city.",
        "operationId": "get_websites_website_id_geography",
        "tags": [
          "Get Geography"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-geography"
        }
      }
    },
    "/public/v1/websites/{website_id}/health": {
      "get": {
        "summary": "Recommendations, Insights & Health NEW",
        "description": "Programmatic access to the same actionable recommendations, AI-generated insights, real-time feed, and site/ingestion health you see in the dashboard. All read-only (GET), authenticated with your API key like every other endpoint.",
        "operationId": "get_websites_website_id_health",
        "tags": [
          "Recommendations, Insights & Health NEW"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-health"
        }
      }
    },
    "/public/v1/websites/{website_id}/health/history": {
      "get": {
        "summary": "Recommendations, Insights & Health NEW",
        "description": "Programmatic access to the same actionable recommendations, AI-generated insights, real-time feed, and site/ingestion health you see in the dashboard. All read-only (GET), authenticated with your API key like every other endpoint.",
        "operationId": "get_websites_website_id_health_history",
        "tags": [
          "Recommendations, Insights & Health NEW"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "metric",
            "in": "query",
            "required": false,
            "description": "Metric.",
            "schema": {
              "type": "string",
              "enum": [
                "traffic",
                "errors",
                "bots",
                "crawlers",
                "not_found",
                "latency"
              ],
              "default": "traffic"
            }
          },
          {
            "name": "period",
            "in": "query",
            "required": false,
            "description": "Period.",
            "schema": {
              "type": "string",
              "enum": [
                "24h",
                "7d",
                "30d"
              ],
              "default": "24h"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-health"
        }
      }
    },
    "/public/v1/websites/{website_id}/insights": {
      "get": {
        "summary": "Recommendations, Insights & Health NEW",
        "description": "Programmatic access to the same actionable recommendations, AI-generated insights, real-time feed, and site/ingestion health you see in the dashboard. All read-only (GET), authenticated with your API key like every other endpoint.",
        "operationId": "get_websites_website_id_insights",
        "tags": [
          "Recommendations, Insights & Health NEW"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Dashboard page the cached insights belong to.",
            "schema": {
              "type": "string",
              "default": "/"
            }
          },
          {
            "name": "filters",
            "in": "query",
            "required": false,
            "description": "JSON object of the filters the insights were generated with.",
            "schema": {
              "type": "string",
              "default": "{}"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-insights"
        }
      }
    },
    "/public/v1/websites/{website_id}/ips": {
      "get": {
        "summary": "Get IPs",
        "description": "Returns IP address and IP range analytics.",
        "operationId": "get_websites_website_id_ips",
        "tags": [
          "Get IPs"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-ips"
        }
      }
    },
    "/public/v1/websites/{website_id}/ips/{ip_address}/requests": {
      "get": {
        "summary": "Search IP Requests",
        "description": "Returns all requests made by a specific IP address. Useful for investigating suspicious activity.",
        "operationId": "get_websites_website_id_ips_ip_address_requests",
        "tags": [
          "Search IP Requests"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ip_address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours, clamped to 1-168.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 168
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Rows per page, default 50, clamped to 1-500.",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 500
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#search-ip"
        }
      }
    },
    "/public/v1/websites/{website_id}/live": {
      "get": {
        "summary": "Recommendations, Insights & Health NEW",
        "description": "Programmatic access to the same actionable recommendations, AI-generated insights, real-time feed, and site/ingestion health you see in the dashboard. All read-only (GET), authenticated with your API key like every other endpoint.",
        "operationId": "get_websites_website_id_live",
        "tags": [
          "Recommendations, Insights & Health NEW"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Feed filter.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "bots",
                "human",
                "errors"
              ],
              "default": "all"
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-live"
        }
      }
    },
    "/public/v1/websites/{website_id}/llms": {
      "get": {
        "summary": "LLM / AI Crawler Analytics",
        "description": "Dedicated analytics for LLM and AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, etc.). Every crawler carries an intent: training (model-training corpus crawl), search (AI-search index crawl) or fetcher (a person asked the AI about a page; fetchers ignore robots.txt by design). intent_totals gives the request split. pages_by_intent provides ranked URL paths for each intent. Returns per-bot time series, crawler verification status, and the pages those bots are reading.",
        "operationId": "get_websites_website_id_llms",
        "tags": [
          "LLM / AI Crawler Analytics"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start; used only together with end (invalid values return 400).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end; used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "countries",
            "in": "query",
            "required": false,
            "description": "Comma-separated ISO country codes, e.g. GB,US.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-llms"
        }
      }
    },
    "/public/v1/websites/{website_id}/page-importance": {
      "get": {
        "summary": "Recommendations, Insights & Health NEW",
        "description": "Programmatic access to the same actionable recommendations, AI-generated insights, real-time feed, and site/ingestion health you see in the dashboard. All read-only (GET), authenticated with your API key like every other endpoint.",
        "operationId": "get_websites_website_id_page_importance",
        "tags": [
          "Recommendations, Insights & Health NEW"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bot",
            "in": "query",
            "required": false,
            "description": "Crawler family; the response lists available families.",
            "schema": {
              "type": "string",
              "default": "google"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Top-N pages, clamped to 1-50000.",
            "schema": {
              "type": "integer",
              "default": 200,
              "minimum": 1,
              "maximum": 50000
            }
          },
          {
            "name": "full",
            "in": "query",
            "required": false,
            "description": "1 returns every page regardless of limit.",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-page-importance"
        }
      }
    },
    "/public/v1/websites/{website_id}/paths": {
      "get": {
        "summary": "Get Paths",
        "description": "Returns path/URL analytics sorted by request count.",
        "operationId": "get_websites_website_id_paths",
        "tags": [
          "Get Paths"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum paths, clamped to 1-1000.",
            "schema": {
              "type": "integer",
              "default": 100,
              "minimum": 1,
              "maximum": 1000
            }
          },
          {
            "name": "countries",
            "in": "query",
            "required": false,
            "description": "Comma-separated ISO country codes, e.g. GB,US.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-paths"
        }
      }
    },
    "/public/v1/websites/{website_id}/recommendations": {
      "get": {
        "summary": "Recommendations, Insights & Health NEW",
        "description": "Programmatic access to the same actionable recommendations, AI-generated insights, real-time feed, and site/ingestion health you see in the dashboard. All read-only (GET), authenticated with your API key like every other endpoint.",
        "operationId": "get_websites_website_id_recommendations",
        "tags": [
          "Recommendations, Insights & Health NEW"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-recommendations"
        }
      }
    },
    "/public/v1/websites/{website_id}/recommendations/paths-404": {
      "get": {
        "summary": "Recommendations, Insights & Health NEW",
        "description": "Programmatic access to the same actionable recommendations, AI-generated insights, real-time feed, and site/ingestion health you see in the dashboard. All read-only (GET), authenticated with your API key like every other endpoint.",
        "operationId": "get_websites_website_id_recommendations_paths_404",
        "tags": [
          "Recommendations, Insights & Health NEW"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-recommendations"
        }
      }
    },
    "/public/v1/websites/{website_id}/recommendations/resolve": {
      "post": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "post_websites_website_id_recommendations_resolve",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-recommendations"
        }
      }
    },
    "/public/v1/websites/{website_id}/recommendations/resolve/{key}": {
      "delete": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "delete_websites_website_id_recommendations_resolve_key",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-recommendations"
        }
      }
    },
    "/public/v1/websites/{website_id}/recommendations/slow-paths": {
      "get": {
        "summary": "Recommendations, Insights & Health NEW",
        "description": "Programmatic access to the same actionable recommendations, AI-generated insights, real-time feed, and site/ingestion health you see in the dashboard. All read-only (GET), authenticated with your API key like every other endpoint.",
        "operationId": "get_websites_website_id_recommendations_slow_paths",
        "tags": [
          "Recommendations, Insights & Health NEW"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-recommendations"
        }
      }
    },
    "/public/v1/websites/{website_id}/recommendations/snippet": {
      "get": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "get_websites_website_id_recommendations_snippet",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Snippet type.",
            "schema": {
              "type": "string",
              "enum": [
                "block_ips",
                "block_bots",
                "gone_404s"
              ],
              "default": "block_ips"
            }
          },
          {
            "name": "target",
            "in": "query",
            "required": false,
            "description": "Platform; defaults to the website's platform.",
            "schema": {
              "type": "string",
              "enum": [
                "cloudflare",
                "cloudfront",
                "nginx",
                "apache",
                "netlify",
                "vercel",
                "robots"
              ]
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "Window in days, used only when hours is absent.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 365
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-snippet"
        }
      }
    },
    "/public/v1/websites/{website_id}/recommendations/unverified-bots": {
      "get": {
        "summary": "Recommendations, Insights & Health NEW",
        "description": "Programmatic access to the same actionable recommendations, AI-generated insights, real-time feed, and site/ingestion health you see in the dashboard. All read-only (GET), authenticated with your API key like every other endpoint.",
        "operationId": "get_websites_website_id_recommendations_unverified_bots",
        "tags": [
          "Recommendations, Insights & Health NEW"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-recommendations"
        }
      }
    },
    "/public/v1/websites/{website_id}/referrers": {
      "get": {
        "summary": "Get Referrers",
        "description": "Returns referrer domain analytics - see which sites are sending traffic to you.",
        "operationId": "get_websites_website_id_referrers",
        "tags": [
          "Get Referrers"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum referrers, clamped to 1-500.",
            "schema": {
              "type": "integer",
              "default": 100,
              "minimum": 1,
              "maximum": 500
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-referrers"
        }
      }
    },
    "/public/v1/websites/{website_id}/reports/seo": {
      "post": {
        "summary": "Recommendations, Insights & Health NEW",
        "description": "Programmatic access to the same actionable recommendations, AI-generated insights, real-time feed, and site/ingestion health you see in the dashboard. All read-only (GET), authenticated with your API key like every other endpoint.",
        "operationId": "post_websites_website_id_reports_seo",
        "tags": [
          "Recommendations, Insights & Health NEW"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#create-seo-report"
        }
      }
    },
    "/public/v1/websites/{website_id}/requests": {
      "get": {
        "summary": "Raw Request Log",
        "description": "The request-level log behind the dashboard's Log Explorer \u2014 every stored request (bots and humans), newest first, with the full enriched row: geography, ASN, bot verification verdict, protocol, device and timing. All filters are optional and combine freely: bot_name, is_bot, bot_verified, client_ip, path (substring), status, status_category, method, host, country, user_agent (substring). Time range via hours or start/end (ISO 8601). Up to 500 rows per call (limit); continue with the returned next_cursor or page. A response with data_buffering: true means the archive query is still running \u2014 re",
        "operationId": "get_websites_website_id_requests",
        "tags": [
          "Raw Request Log"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Exact status code.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status_category",
            "in": "query",
            "required": false,
            "description": "2xx, 3xx, 4xx or 5xx.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "path",
            "in": "query",
            "required": false,
            "description": "Path substring.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bot_name",
            "in": "query",
            "required": false,
            "description": "Exact bot name.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bot_category",
            "in": "query",
            "required": false,
            "description": "Bot category.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "is_bot",
            "in": "query",
            "required": false,
            "description": "Bots or humans only.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "bot_verified",
            "in": "query",
            "required": false,
            "description": "Verified or unverified bots.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "client_ip",
            "in": "query",
            "required": false,
            "description": "Exact client IP.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "method",
            "in": "query",
            "required": false,
            "description": "HTTP method.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "host",
            "in": "query",
            "required": false,
            "description": "Exact host.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Two-letter country code.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user_agent",
            "in": "query",
            "required": false,
            "description": "User-agent substring.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows per call, clamped to 1-500.",
            "schema": {
              "type": "integer",
              "default": 100,
              "minimum": 1,
              "maximum": 500
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Continuation cursor from the previous response.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number on archive-backed websites.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-requests"
        }
      }
    },
    "/public/v1/websites/{website_id}/search/performance": {
      "get": {
        "summary": "Search Performance",
        "description": "Search Console impressions, clicks, CTR and average position as a daily series for the period, totals against the previous equal period, site-wide top queries and top pages. Requires a Search Console connection; returns gsc_connected: false otherwise. Data lags Google by 2\u20133 days and is synced daily.",
        "operationId": "get_websites_website_id_search_performance",
        "tags": [
          "Search Performance"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24. Ignored when both start and end are given. Counted in whole days (at least one).",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-search-performance"
        }
      }
    },
    "/public/v1/websites/{website_id}/search/queries": {
      "get": {
        "summary": "Search Queries (per page)",
        "description": "The Search Console queries that showed one page over the trailing 28 days (up to 10, synced for the top 200 pages by impressions) plus the page's daily impressions/clicks series (top 500 pages). The same fields are embedded in the URL detail response under index_status.top_queries and index_status.daily.",
        "operationId": "get_websites_website_id_search_queries",
        "tags": [
          "Search Queries (per page)"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "path",
            "in": "query",
            "required": true,
            "description": "URL path, e.g. /pricing.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-search-queries"
        }
      }
    },
    "/public/v1/websites/{website_id}/search/reconcile": {
      "get": {
        "summary": "Index vs Fetch Reconciliation",
        "description": "Search Console index status per URL crossed with verified Googlebot fetches from your logs over the period. Four buckets: indexed_fetched, indexed_not_fetched (Google is not revisiting), not_indexed_fetched (fetched but refused) and fetched_not_inspected (status unknown). Counts cover every path in the union; examples are capped at 50 per bucket. Static assets are excluded from the fetch side. Cached for one hour per period.",
        "operationId": "get_websites_website_id_search_reconcile",
        "tags": [
          "Index vs Fetch Reconciliation"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-search-reconcile"
        }
      }
    },
    "/public/v1/websites/{website_id}/segments": {
      "get": {
        "summary": "4 Date Ranges",
        "description": "Many log analytics endpoints accept a time range. Use hours for a rolling window, or start and end for a specific date range (ISO 8601 format).",
        "operationId": "get_websites_website_id_segments",
        "tags": [
          "4 Date Ranges"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-segments"
        }
      },
      "post": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "post_websites_website_id_segments",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-segments"
        }
      }
    },
    "/public/v1/websites/{website_id}/segments-breakdown": {
      "get": {
        "summary": "Segments",
        "description": "Saved page groups defined in the dashboard (SEO \u2192 Segments): a name and rules \u2014 prefix, contains, exact, regex on the path, or query on the query string \u2014 with optional exclusions and nesting. They are evaluated on the logs at query time, so they apply to all history. Add ?segment=<segment_id> to a segment-aware read \u2014 /summary, /traffic, /bots, /paths, /llms, /ai-funnel, /ai-landing, /crawl-report, /crawl-audit, /url and the others listed under Common Query Parameters \u2014 to filter it to one group; other reads ignore it. /segments-breakdown returns every segment (plus _all) with requests, human",
        "operationId": "get_websites_website_id_segments_breakdown",
        "tags": [
          "Segments"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 720. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 720,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "countries",
            "in": "query",
            "required": false,
            "description": "Comma-separated ISO country codes, e.g. GB,US.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "compare",
            "in": "query",
            "required": false,
            "description": "Adds the previous equal period and deltas.",
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            }
          },
          {
            "name": "segments",
            "in": "query",
            "required": false,
            "description": "Comma-separated segment ids to include.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-segments"
        }
      }
    },
    "/public/v1/websites/{website_id}/segments/library": {
      "post": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "post_websites_website_id_segments_library",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-segments"
        }
      }
    },
    "/public/v1/websites/{website_id}/segments/{segment_id}": {
      "put": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "put_websites_website_id_segments_segment_id",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "segment_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-segments"
        }
      },
      "delete": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "delete_websites_website_id_segments_segment_id",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "segment_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-segments"
        }
      }
    },
    "/public/v1/websites/{website_id}/seo": {
      "get": {
        "summary": "Get SEO Stats",
        "description": "Returns search engine crawler statistics - Googlebot, Bingbot, etc.",
        "operationId": "get_websites_website_id_seo",
        "tags": [
          "Get SEO Stats"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bot",
            "in": "query",
            "required": false,
            "description": "Bot name filter, e.g. googlebot.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "params_filter",
            "in": "query",
            "required": false,
            "description": "with_params or without_params; omit for all URLs.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "file_type",
            "in": "query",
            "required": false,
            "description": "File type filter, e.g. html, js, css, images.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-seo"
        }
      }
    },
    "/public/v1/websites/{website_id}/seo/budget-urls": {
      "get": {
        "summary": "Crawl Budget URLs",
        "description": "Per-URL crawl budget breakdown within a directory. Shows which paths search engine crawlers are spending budget on, so you can spot waste.",
        "operationId": "get_websites_website_id_seo_budget_urls",
        "tags": [
          "Crawl Budget URLs"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bot",
            "in": "query",
            "required": false,
            "description": "Bot name filter, e.g. googlebot.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "directory",
            "in": "query",
            "required": false,
            "description": "Directory to drill into.",
            "schema": {
              "type": "string",
              "default": "/"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Rows per page.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "params_filter",
            "in": "query",
            "required": false,
            "description": "with_params or without_params; omit for all URLs.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "file_type",
            "in": "query",
            "required": false,
            "description": "File type filter, e.g. html, js, css, images.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-budget-urls"
        }
      }
    },
    "/public/v1/websites/{website_id}/seo/index-coverage": {
      "get": {
        "summary": "Index Coverage",
        "description": "Google index coverage for your current sitemap URLs plus any URL whose last inspection says indexed, crossed with recorded Googlebot crawls. crawled means a Googlebot crawl was recorded within hours of now (default 720) \u2014 a recency threshold, not a historical selection. indexed / not_indexed come from the last stored Search Console URL Inspection result, not a live check. pending_inspection counts URLs without a stored indexed or not_indexed result, including URLs never inspected; it is not evidence either way. directories (paged with dir_page and dir_page_size) break the buckets down by first",
        "operationId": "get_websites_website_id_seo_index_coverage",
        "tags": [
          "Index Coverage"
        ],
        "x-salience-contract": "typed",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Googlebot crawl-recency window in hours measured back from now, default 720. Not a historical selection.",
            "schema": {
              "type": "integer",
              "default": 720,
              "minimum": 1
            }
          },
          {
            "name": "dir_page",
            "in": "query",
            "required": false,
            "description": "Directory page.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "dir_page_size",
            "in": "query",
            "required": false,
            "description": "Directories per page, default 20; 0 returns every directory.",
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 0
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "gsc_connected": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string",
                      "description": "Present when Search Console is not connected."
                    },
                    "property_url": {
                      "type": "string",
                      "nullable": true
                    },
                    "last_sync_at": {
                      "type": "string",
                      "nullable": true
                    },
                    "sync_status": {
                      "type": "string",
                      "nullable": true
                    },
                    "buckets": {
                      "type": "object",
                      "properties": {
                        "crawled_indexed": {
                          "type": "integer"
                        },
                        "crawled_not_indexed": {
                          "type": "integer"
                        },
                        "not_crawled_indexed": {
                          "type": "integer"
                        },
                        "not_crawled_not_indexed": {
                          "type": "integer"
                        },
                        "pending_inspection": {
                          "type": "integer"
                        }
                      },
                      "additionalProperties": true,
                      "required": [
                        "crawled_indexed",
                        "crawled_not_indexed",
                        "not_crawled_indexed",
                        "not_crawled_not_indexed",
                        "pending_inspection"
                      ],
                      "description": "crawled = a verified-name Googlebot crawl recorded within hours of now; indexed / not_indexed = the last stored URL Inspection result; pending_inspection = no stored indexed or not_indexed result, including URLs never inspected."
                    },
                    "total_urls": {
                      "type": "integer",
                      "description": "Current sitemap URLs plus URLs whose last inspection says indexed."
                    },
                    "directories": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "directory": {
                            "type": "string"
                          },
                          "crawled_indexed": {
                            "type": "integer"
                          },
                          "crawled_not_indexed": {
                            "type": "integer"
                          },
                          "not_crawled_indexed": {
                            "type": "integer"
                          },
                          "not_crawled_not_indexed": {
                            "type": "integer"
                          },
                          "pending_inspection": {
                            "type": "integer"
                          }
                        },
                        "additionalProperties": true,
                        "required": [
                          "directory"
                        ]
                      }
                    },
                    "total_directories": {
                      "type": "integer"
                    },
                    "dir_page": {
                      "type": "integer"
                    },
                    "dir_page_size": {
                      "type": "integer"
                    },
                    "data_freshness": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "from_cache": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true,
                  "required": [
                    "gsc_connected"
                  ],
                  "description": "gsc_connected=false responses carry only message."
                }
              }
            }
          },
          "503": {
            "description": "Current index coverage records are unavailable; retry shortly."
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-index-coverage"
        }
      }
    },
    "/public/v1/websites/{website_id}/seo/index-coverage/urls": {
      "get": {
        "summary": "Index Coverage URLs",
        "description": "Paginated URLs from index coverage, sorted by 28-day impressions, with the inspection provenance for each row. index_status is the last stored inspection coverage (pending when never inspected); inspected_at dates it; inspected_url is the exact URL Google inspected (protocol, www/apex, trailing slash) and is null for older inspections that did not record it; google_canonical is Google's choice and not proof of indexing. crawl_count and last_crawled_at come from Googlebot crawls recorded within hours of now. Returns 400 when Search Console is not connected; sitemap_status explains an empty list",
        "operationId": "get_websites_website_id_seo_index_coverage_urls",
        "tags": [
          "Index Coverage URLs"
        ],
        "x-salience-contract": "typed",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bucket",
            "in": "query",
            "required": false,
            "description": "Bucket to list; omit for every bucket. An unrecognised name returns no rows. crawled = a verified-name Googlebot crawl recorded within hours of now; indexed / not_indexed = the last stored URL Inspection result; pending_inspection = no stored indexed or not_indexed result, including URLs never inspected.",
            "schema": {
              "type": "string",
              "enum": [
                "crawled_indexed",
                "crawled_not_indexed",
                "not_crawled_indexed",
                "not_crawled_not_indexed",
                "pending_inspection"
              ]
            }
          },
          {
            "name": "directory",
            "in": "query",
            "required": false,
            "description": "Path prefix filter, e.g. /blog.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Rows per page, default 50; 0 returns every matching row, so prefer bounded pages.",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 0
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Googlebot crawl-recency window in hours measured back from now, default 720.",
            "schema": {
              "type": "integer",
              "default": 720,
              "minimum": 1
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "urls": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "url_path": {
                            "type": "string"
                          },
                          "bucket": {
                            "type": "string",
                            "enum": [
                              "crawled_indexed",
                              "crawled_not_indexed",
                              "not_crawled_indexed",
                              "not_crawled_not_indexed",
                              "pending_inspection"
                            ],
                            "description": "crawled = a verified-name Googlebot crawl recorded within hours of now; indexed / not_indexed = the last stored URL Inspection result; pending_inspection = no stored indexed or not_indexed result, including URLs never inspected."
                          },
                          "crawl_count": {
                            "type": "integer",
                            "description": "Stored crawl counts summed across Googlebot variants recorded in the window."
                          },
                          "last_crawled_at": {
                            "type": "string",
                            "nullable": true
                          },
                          "last_crawled_by": {
                            "type": "string",
                            "nullable": true
                          },
                          "index_status": {
                            "type": "string",
                            "description": "Last stored inspection coverage; pending when never inspected."
                          },
                          "index_status_reason": {
                            "type": "string",
                            "nullable": true
                          },
                          "inspection_verdict": {
                            "type": "string",
                            "nullable": true
                          },
                          "inspected_at": {
                            "type": "string",
                            "description": "When the stored inspection ran.",
                            "nullable": true
                          },
                          "inspected_url": {
                            "type": "string",
                            "description": "Exact URL Google inspected; null when not recorded.",
                            "nullable": true
                          },
                          "google_canonical": {
                            "type": "string",
                            "description": "Google-selected canonical; not proof of indexing.",
                            "nullable": true
                          },
                          "impressions_28d": {
                            "type": "integer"
                          },
                          "clicks_28d": {
                            "type": "integer"
                          },
                          "avg_position": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": true,
                        "required": [
                          "url_path",
                          "bucket",
                          "index_status",
                          "inspected_at",
                          "inspected_url"
                        ]
                      }
                    },
                    "page": {
                      "type": "integer"
                    },
                    "page_size": {
                      "type": "integer"
                    },
                    "total": {
                      "type": "integer"
                    },
                    "total_pages": {
                      "type": "integer"
                    },
                    "bucket_filter": {
                      "type": "string",
                      "nullable": true
                    },
                    "directory_filter": {
                      "type": "string",
                      "nullable": true
                    },
                    "from_cache": {
                      "type": "boolean"
                    },
                    "sitemap_status": {
                      "type": "string",
                      "description": "Present when no sitemap URLs have been synced; an empty list is then not a clean result."
                    }
                  },
                  "additionalProperties": true,
                  "required": [
                    "urls",
                    "page",
                    "page_size",
                    "total",
                    "total_pages"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Search Console is not connected."
          },
          "503": {
            "description": "Current index coverage records are unavailable; retry shortly."
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-index-coverage-urls"
        }
      }
    },
    "/public/v1/websites/{website_id}/seo/path-explorer": {
      "get": {
        "summary": "Path Explorer",
        "description": "Hierarchical view of crawled paths with per-bot and per-status breakdowns. Use to build a directory tree of crawler activity.",
        "operationId": "get_websites_website_id_seo_path_explorer",
        "tags": [
          "Path Explorer"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bot",
            "in": "query",
            "required": false,
            "description": "Bot name filter, e.g. googlebot.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "params_filter",
            "in": "query",
            "required": false,
            "description": "with_params or without_params; omit for all URLs.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "file_type",
            "in": "query",
            "required": false,
            "description": "File type filter, e.g. html, js, css, images.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-path-explorer"
        }
      }
    },
    "/public/v1/websites/{website_id}/seo/requests": {
      "get": {
        "summary": "Crawler Request Log",
        "description": "Raw crawler request log with filtering. Each row is one crawler hit \u2014 timestamp, path, status, bot identity and verification, and response time.",
        "operationId": "get_websites_website_id_seo_requests",
        "tags": [
          "Crawler Request Log"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bot",
            "in": "query",
            "required": false,
            "description": "Bot name filter, e.g. googlebot.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter_type",
            "in": "query",
            "required": false,
            "description": "all, errors, redirects or slow.",
            "schema": {
              "type": "string",
              "default": "all"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Rows per page, default 50, clamped to 1-500.",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 500
            }
          },
          {
            "name": "params_filter",
            "in": "query",
            "required": false,
            "description": "with_params or without_params; omit for all URLs.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "file_type",
            "in": "query",
            "required": false,
            "description": "File type filter, e.g. html, js, css, images.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-seo-requests"
        }
      }
    },
    "/public/v1/websites/{website_id}/seo/robots": {
      "get": {
        "summary": "robots.txt Audit",
        "description": "Fetches your live robots.txt, parses the rule groups, and cross-references them against actual crawler activity to surface violations (bots hitting paths they were told to skip).",
        "operationId": "get_websites_website_id_seo_robots",
        "tags": [
          "robots.txt Audit"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bot",
            "in": "query",
            "required": false,
            "description": "Bot name filter, e.g. googlebot.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-robots"
        }
      }
    },
    "/public/v1/websites/{website_id}/seo/sitemap": {
      "get": {
        "summary": "Get Sitemap Coverage",
        "description": "Returns sitemap coverage data - tracks which URLs from your sitemap have been crawled by search engines, their crawl frequency, and current status.",
        "operationId": "get_websites_website_id_seo_sitemap",
        "tags": [
          "Get Sitemap Coverage"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Rows per page, default 50, clamped to 1-500.",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 500
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Crawl-status filter.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "never_crawled",
                "recently_crawled",
                "stale",
                "not_in_sitemap"
              ]
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort column.",
            "schema": {
              "type": "string",
              "default": "path"
            }
          },
          {
            "name": "sort_dir",
            "in": "query",
            "required": false,
            "description": "Sort direction.",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "asc"
            }
          },
          {
            "name": "bot",
            "in": "query",
            "required": false,
            "description": "Bot name filter, e.g. googlebot.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-sitemap"
        }
      }
    },
    "/public/v1/websites/{website_id}/seo/sitemap/url-history": {
      "get": {
        "summary": "URL Crawl History",
        "description": "Per-URL crawl history \u2014 every individual crawl event for a single sitemap URL, including which bot, status code, response time, and country.",
        "operationId": "get_websites_website_id_seo_sitemap_url_history",
        "tags": [
          "URL Crawl History"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "url_path",
            "in": "query",
            "required": true,
            "description": "Path to look up (url is accepted as an alias).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 168 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 168,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bot",
            "in": "query",
            "required": false,
            "description": "Bot name filter, e.g. googlebot.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Rows per page, default 50, clamped to 1-500.",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 500
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-sitemap-url-history"
        }
      }
    },
    "/public/v1/websites/{website_id}/seo/status-consistency": {
      "get": {
        "summary": "Status Consistency",
        "description": "URLs whose HTTP status changed across crawls \u2014 e.g. mostly 200 but occasionally 404 or 5xx. Useful for surfacing flapping pages and intermittent errors that hit crawlers.",
        "operationId": "get_websites_website_id_seo_status_consistency",
        "tags": [
          "Status Consistency"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bot",
            "in": "query",
            "required": false,
            "description": "Bot name filter, e.g. googlebot.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_requests",
            "in": "query",
            "required": false,
            "description": "Minimum requests for a URL to be analysed.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "params_filter",
            "in": "query",
            "required": false,
            "description": "with_params or without_params; omit for all URLs.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "file_type",
            "in": "query",
            "required": false,
            "description": "File type filter, e.g. html, js, css, images.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-status-consistency"
        }
      }
    },
    "/public/v1/websites/{website_id}/seo/url-patterns": {
      "get": {
        "summary": "URL Patterns",
        "description": "Auto-detected URL pattern templates with crawl frequency. Variable segments (numbers, UUIDs, dates) are replaced with placeholders so you can see how crawlers treat each route family.",
        "operationId": "get_websites_website_id_seo_url_patterns",
        "tags": [
          "URL Patterns"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 168 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 168,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bot",
            "in": "query",
            "required": false,
            "description": "Bot name filter, e.g. googlebot.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_urls",
            "in": "query",
            "required": false,
            "description": "Minimum URLs to form a pattern.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "params_filter",
            "in": "query",
            "required": false,
            "description": "with_params or without_params; omit for all URLs.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "file_type",
            "in": "query",
            "required": false,
            "description": "File type filter, e.g. html, js, css, images.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-url-patterns"
        }
      }
    },
    "/public/v1/websites/{website_id}/setup": {
      "get": {
        "summary": "Setup Status",
        "description": "Platform, ingest endpoint, whether logs have arrived and what to do next. Backs the MCP get_setup_instructions and get_setup_status tools. The ingest key is only returned by Create Website; this endpoint never repeats it.",
        "operationId": "get_websites_website_id_setup",
        "tags": [
          "Setup Status"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-setup"
        }
      }
    },
    "/public/v1/websites/{website_id}/site-events": {
      "post": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "post_websites_website_id_site_events",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#write-side"
        }
      },
      "get": {
        "summary": "Site Events",
        "description": "Annotated, site-wide events that overlay onto charts in the dashboard \u2014 deploys, algorithm updates, marketing campaigns, anything you want to correlate against traffic shifts.",
        "operationId": "get_websites_website_id_site_events",
        "tags": [
          "Site Events"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date",
            "in": "query",
            "required": false,
            "description": "YYYY-MM-DD; with end_date selects a date range, alone selects that date onwards.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end_date",
            "in": "query",
            "required": false,
            "description": "YYYY-MM-DD; used together with start_date.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#site-events"
        }
      }
    },
    "/public/v1/websites/{website_id}/site-events/{event_id}": {
      "delete": {
        "summary": "Actions & key scopes",
        "description": "API keys have a scope: read (the default \u2014 every endpoint above) or read_write, which can also perform the actions below. Create a read & write key under Organization \u2192 API Access. A read-only key gets 403 with \"This API key is read-only\". Writes are limited to 120 per hour per organisation, and every write is recorded as a site event on the timeline naming the key. Nothing here deletes data or touches your hosting.",
        "operationId": "delete_websites_website_id_site_events_event_id",
        "tags": [
          "Actions & key scopes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#write-side"
        }
      }
    },
    "/public/v1/websites/{website_id}/status-codes": {
      "get": {
        "summary": "Get Status Codes",
        "description": "Returns HTTP status code distribution with hourly breakdown.",
        "operationId": "get_websites_website_id_status_codes",
        "tags": [
          "Get Status Codes"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-status-codes"
        }
      }
    },
    "/public/v1/websites/{website_id}/summary": {
      "get": {
        "summary": "Get Summary",
        "description": "Returns summary statistics for a website.",
        "operationId": "get_websites_website_id_summary",
        "tags": [
          "Get Summary"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-summary"
        }
      }
    },
    "/public/v1/websites/{website_id}/traffic": {
      "get": {
        "summary": "Get Traffic",
        "description": "Returns traffic data with hourly breakdown.",
        "operationId": "get_websites_website_id_traffic",
        "tags": [
          "Get Traffic"
        ],
        "x-salience-contract": "parameters",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24 (clamped to 1-8760). Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 8760
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-traffic"
        }
      }
    },
    "/public/v1/websites/{website_id}/url": {
      "get": {
        "summary": "Recommendations, Insights & Health NEW",
        "description": "Programmatic access to the same actionable recommendations, AI-generated insights, real-time feed, and site/ingestion health you see in the dashboard. All read-only (GET), authenticated with your API key like every other endpoint.",
        "operationId": "get_websites_website_id_url",
        "tags": [
          "Recommendations, Insights & Health NEW"
        ],
        "x-salience-contract": "typed",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "path",
            "in": "query",
            "required": true,
            "description": "URL path, e.g. /pricing. A full URL is accepted; query string and fragment are dropped.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Rolling window in hours ending now, default 24. Ignored when both start and end are given.",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "ISO 8601 start, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Used only together with end.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "ISO 8601 end. Used only together with start.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "countries",
            "in": "query",
            "required": false,
            "description": "Comma-separated ISO country codes, e.g. GB,US.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "segment",
            "in": "query",
            "required": false,
            "description": "Saved segment id (GET \u2026/segments). Narrows the log-derived figures to that page group; an id that does not belong to the website is ignored.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "path": {
                      "type": "string"
                    },
                    "variant_path": {
                      "type": "string",
                      "description": "Trailing-slash twin.",
                      "nullable": true
                    },
                    "period_hours": {
                      "type": "integer"
                    },
                    "start": {
                      "type": "string",
                      "description": "Log window start."
                    },
                    "end": {
                      "type": "string",
                      "description": "Log window end."
                    },
                    "logs": {
                      "type": "object",
                      "properties": {
                        "requests": {
                          "type": "integer"
                        },
                        "humans": {
                          "type": "integer"
                        },
                        "bots": {
                          "type": "integer"
                        },
                        "verified_search": {
                          "type": "integer"
                        },
                        "status_mix": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "avg_time_ms": {
                          "type": "number",
                          "nullable": true
                        },
                        "p95_time_ms": {
                          "type": "number",
                          "nullable": true
                        },
                        "first_seen": {
                          "type": "string",
                          "nullable": true
                        },
                        "last_seen": {
                          "type": "string",
                          "nullable": true
                        },
                        "granularity": {
                          "type": "string"
                        },
                        "series": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        },
                        "variant_series": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        },
                        "variant": {
                          "type": "object",
                          "additionalProperties": true,
                          "nullable": true
                        },
                        "top_bots": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          },
                          "nullable": true
                        },
                        "top_referrers": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          },
                          "nullable": true
                        },
                        "top_countries": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          },
                          "nullable": true
                        }
                      },
                      "additionalProperties": true,
                      "required": [
                        "requests",
                        "humans",
                        "bots",
                        "verified_search"
                      ],
                      "description": "Requests for the path in the selected window.",
                      "nullable": true
                    },
                    "search_bots": {
                      "type": "object",
                      "additionalProperties": true,
                      "nullable": true
                    },
                    "crawl": {
                      "type": "object",
                      "properties": {
                        "available": {
                          "type": "boolean"
                        },
                        "in_crawl": {
                          "type": "boolean"
                        },
                        "reason": {
                          "type": "string",
                          "description": "no_crawl, not_in_crawl, missing_results (saved crawl files are missing; run a new crawl), lookup_failed or a temporary storage reason."
                        },
                        "detail": {
                          "type": "string"
                        },
                        "crawl_id": {
                          "type": "string",
                          "nullable": true
                        },
                        "completed_at": {
                          "type": "string",
                          "description": "When the crawl completed; independent of the log window.",
                          "nullable": true
                        },
                        "source": {
                          "type": "string",
                          "nullable": true
                        },
                        "status": {
                          "type": "integer",
                          "nullable": true
                        },
                        "depth": {
                          "type": "integer",
                          "nullable": true
                        },
                        "inlinks": {
                          "type": "integer",
                          "nullable": true
                        },
                        "outlinks_internal": {
                          "type": "integer",
                          "nullable": true
                        },
                        "pagerank": {
                          "type": "number",
                          "nullable": true
                        },
                        "indexable": {
                          "type": "boolean",
                          "nullable": true
                        },
                        "canonical": {
                          "type": "string",
                          "description": "Canonical declared by the page when crawled.",
                          "nullable": true
                        },
                        "redirect_to": {
                          "type": "string",
                          "nullable": true
                        }
                      },
                      "additionalProperties": true,
                      "required": [
                        "available"
                      ],
                      "description": "Latest ready crawl.",
                      "nullable": true
                    },
                    "sitemap": {
                      "type": "object",
                      "properties": {
                        "membership_status": {
                          "type": "string",
                          "enum": [
                            "present",
                            "removed",
                            "not_found",
                            "unknown"
                          ],
                          "description": "present = confirmed in the sitemap; removed = confirmed and later removed; not_found = no confirmed membership and the last sitemap fetch was complete; unknown = no confirmed membership and completeness is not established (not proof of absence)."
                        },
                        "membership_confirmed": {
                          "type": "boolean"
                        },
                        "in_sitemap": {
                          "type": "boolean",
                          "description": "true only when membership is confirmed and the URL has not been removed."
                        },
                        "removed": {
                          "type": "boolean"
                        },
                        "removed_at": {
                          "type": "string",
                          "nullable": true
                        },
                        "last_seen": {
                          "type": "string",
                          "description": "When a confirmed sitemap last listed the URL.",
                          "nullable": true
                        },
                        "reason": {
                          "type": "string",
                          "description": "not_in_sitemap when no inventory record exists; read membership_status, which remains unknown unless the last fetch was complete."
                        },
                        "url_path": {
                          "type": "string",
                          "description": "Inventory path matched (may be the trailing-slash twin)."
                        },
                        "first_seen": {
                          "type": "string",
                          "nullable": true
                        },
                        "sitemap_lastmod": {
                          "type": "string",
                          "nullable": true
                        },
                        "last_crawled_at": {
                          "type": "string",
                          "description": "Latest recorded bot crawl of the path (legacy records: null).",
                          "nullable": true
                        },
                        "last_crawled_by": {
                          "type": "string",
                          "nullable": true
                        },
                        "times_crawled": {
                          "type": "integer"
                        },
                        "last_status_code": {
                          "type": "integer",
                          "nullable": true
                        },
                        "crawl_status": {
                          "type": "string",
                          "nullable": true
                        },
                        "source": {
                          "type": "string",
                          "enum": [
                            "aurora",
                            "legacy"
                          ],
                          "description": "aurora (current inventory) or legacy (frozen fallback record)."
                        },
                        "last_checked_at": {
                          "type": "string",
                          "description": "Last sitemap fetch attempt.",
                          "nullable": true
                        },
                        "last_successful_fetch_at": {
                          "type": "string",
                          "description": "Last fetch that imported the sitemap successfully.",
                          "nullable": true
                        },
                        "fetch_complete": {
                          "type": "boolean",
                          "description": "true = the last fetch read every sitemap file; false = incomplete; null = not recorded.",
                          "nullable": true
                        },
                        "error": {
                          "type": "string",
                          "description": "Last fetch error, when recorded.",
                          "nullable": true
                        }
                      },
                      "additionalProperties": true,
                      "required": [
                        "membership_status",
                        "membership_confirmed",
                        "in_sitemap",
                        "removed"
                      ],
                      "description": "null when the sitemap stores could not be read.",
                      "nullable": true
                    },
                    "index_status": {
                      "type": "object",
                      "properties": {
                        "available": {
                          "type": "boolean"
                        },
                        "reason": {
                          "type": "string",
                          "description": "gsc_not_connected, lookup_failed, or not_inspected (no stored URL Inspection result; not evidence that the page is not indexed)."
                        },
                        "gsc_connected": {
                          "type": "boolean"
                        },
                        "index_status": {
                          "type": "string",
                          "description": "Last stored URL Inspection coverage result, e.g. indexed or not_indexed; null when never inspected.",
                          "nullable": true
                        },
                        "index_status_reason": {
                          "type": "string",
                          "nullable": true
                        },
                        "inspection_verdict": {
                          "type": "string",
                          "description": "Google's stored inspection verdict.",
                          "nullable": true
                        },
                        "inspected_at": {
                          "type": "string",
                          "description": "When Google's URL Inspection ran; independent of the log window.",
                          "nullable": true
                        },
                        "inspected_url": {
                          "type": "string",
                          "description": "Exact URL Google inspected (protocol, www/apex, trailing slash). null for older records that did not store it.",
                          "nullable": true
                        },
                        "google_canonical": {
                          "type": "string",
                          "description": "Google-selected canonical from the inspection. A canonical is not proof of indexing.",
                          "nullable": true
                        },
                        "impressions_28d": {
                          "type": "integer",
                          "nullable": true
                        },
                        "clicks_28d": {
                          "type": "integer",
                          "nullable": true
                        },
                        "avg_position": {
                          "type": "number",
                          "nullable": true
                        },
                        "period": {
                          "type": "object",
                          "additionalProperties": true,
                          "nullable": true
                        },
                        "daily": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          },
                          "nullable": true
                        },
                        "top_queries": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          },
                          "nullable": true
                        },
                        "queries_window": {
                          "type": "string"
                        }
                      },
                      "additionalProperties": true,
                      "required": [
                        "available"
                      ],
                      "description": "Search Console inspection and performance; independently dated.",
                      "nullable": true
                    },
                    "ga": {
                      "type": "object",
                      "additionalProperties": true,
                      "nullable": true
                    },
                    "importance": {
                      "type": "object",
                      "properties": {
                        "available": {
                          "type": "boolean"
                        },
                        "reason": {
                          "type": "string"
                        },
                        "generated_at": {
                          "type": "string",
                          "nullable": true
                        },
                        "window_days": {
                          "type": "integer",
                          "nullable": true
                        },
                        "families": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "object",
                            "additionalProperties": true,
                            "nullable": true
                          }
                        }
                      },
                      "additionalProperties": true,
                      "required": [
                        "available"
                      ],
                      "nullable": true
                    },
                    "data_source": {
                      "type": "string"
                    },
                    "data_buffering": {
                      "type": "boolean",
                      "description": "true while the log query is still running (logs is null): retry shortly."
                    },
                    "data_note": {
                      "type": "string"
                    },
                    "logs_error": {
                      "type": "string"
                    },
                    "data_range": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  },
                  "additionalProperties": true,
                  "required": [
                    "path",
                    "period_hours",
                    "start",
                    "end",
                    "logs",
                    "crawl",
                    "sitemap",
                    "index_status",
                    "importance"
                  ],
                  "description": "Each section has its own source and date; the log window does not make the other sources current."
                }
              }
            }
          },
          "400": {
            "description": "path missing or too long."
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#get-url-detail"
        }
      }
    },
    "/public/v1/websites/{website_id}/urls/search": {
      "get": {
        "summary": "URL search",
        "description": "Typeahead over the URLs Salience already knows for the site: the sitemap inventory, search-bot crawl records and your latest Site Crawler run. Use it to find the exact path for a page you half-remember, then call URL detail with it. q is a path fragment, prefix or full URL (the origin and any query string are stripped server-side; an empty q returns the site's most-crawled URLs); limit defaults to 15 (max 50). Results are ranked prefix matches first, then substring matches, then by crawls descending. Each result has path, source (sitemap = confirmed sitemap membership, crawl_discovered = an in",
        "operationId": "get_websites_website_id_urls_search",
        "tags": [
          "URL search"
        ],
        "x-salience-contract": "typed",
        "parameters": [
          {
            "name": "website_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Path fragment, prefix or full URL. Origin, query string and fragment are stripped; empty returns the most-crawled URLs.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum results, clamped to 1-50.",
            "schema": {
              "type": "integer",
              "default": 15,
              "minimum": 1,
              "maximum": 50
            }
          },
          {
            "name": "max_rows",
            "in": "query",
            "required": false,
            "description": "Caps every list in the JSON response to N entries and adds a _truncated map describing what was cut.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "query": {
                      "type": "string"
                    },
                    "sitemap_snapshot": {
                      "type": "object",
                      "properties": {
                        "last_checked_at": {
                          "type": "string",
                          "description": "Last sitemap fetch attempt.",
                          "nullable": true
                        },
                        "last_successful_fetch_at": {
                          "type": "string",
                          "description": "Last fetch that imported the sitemap successfully.",
                          "nullable": true
                        },
                        "fetch_complete": {
                          "type": "boolean",
                          "description": "true = the last fetch read every sitemap file; false = incomplete; null = not recorded.",
                          "nullable": true
                        },
                        "error": {
                          "type": "string",
                          "description": "Last fetch error, when recorded.",
                          "nullable": true
                        }
                      },
                      "additionalProperties": true,
                      "description": "Sitemap inventory snapshot shared by every result."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "source": {
                            "type": "string",
                            "enum": [
                              "sitemap",
                              "crawl_discovered",
                              "crawl"
                            ],
                            "description": "sitemap = confirmed sitemap inventory; crawl_discovered = inventory record without confirmed sitemap membership; crawl = seen only in the latest Site Crawler run."
                          },
                          "membership_status": {
                            "type": "string",
                            "enum": [
                              "present",
                              "removed",
                              "not_found",
                              "unknown"
                            ],
                            "description": "present = confirmed in the sitemap; removed = confirmed and later removed; not_found = no confirmed membership and the last sitemap fetch was complete; unknown = no confirmed membership and completeness is not established (not proof of absence)."
                          },
                          "membership_confirmed": {
                            "type": "boolean"
                          },
                          "in_sitemap": {
                            "type": "boolean"
                          },
                          "removed": {
                            "type": "boolean"
                          },
                          "removed_at": {
                            "type": "string",
                            "nullable": true
                          },
                          "last_seen": {
                            "type": "string",
                            "nullable": true
                          },
                          "sitemap_last_seen_at": {
                            "type": "string",
                            "nullable": true
                          },
                          "crawls": {
                            "type": "integer",
                            "description": "Recorded search-bot crawl count."
                          },
                          "last_crawled": {
                            "type": "string",
                            "nullable": true
                          },
                          "last_bot": {
                            "type": "string",
                            "nullable": true
                          },
                          "crawl_status_code": {
                            "type": "integer",
                            "nullable": true
                          },
                          "indexable": {
                            "type": "boolean",
                            "nullable": true
                          }
                        },
                        "additionalProperties": true,
                        "required": [
                          "path",
                          "source",
                          "membership_status",
                          "in_sitemap",
                          "removed",
                          "crawls"
                        ]
                      },
                      "description": "Prefix matches first, then substring matches, then by crawls."
                    },
                    "total_matches": {
                      "type": "integer"
                    },
                    "sources": {
                      "type": "object",
                      "properties": {
                        "sitemap_urls": {
                          "type": "integer",
                          "description": "Rows from the sitemap inventory store, confirmed or not."
                        },
                        "crawl": {
                          "type": "integer",
                          "description": "Rows found only in the latest crawl."
                        }
                      },
                      "additionalProperties": true
                    },
                    "note": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true,
                  "required": [
                    "query",
                    "sitemap_snapshot",
                    "results",
                    "total_matches",
                    "sources"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "No access to this website, or a read-only key on a write"
          },
          "429": {
            "description": "Rate limit reached"
          }
        },
        "externalDocs": {
          "url": "https://salience.com/docs/api/#search-urls"
        }
      }
    }
  }
}
