{
  "openapi": "3.0.3",
  "info": {
    "title": "IsAgentReady API",
    "description": "JSON API for scanning websites for AI agent readiness. Returns scores, letter grades, and actionable recommendations across 5 categories.",
    "version": "1.0.0",
    "contact": {
      "name": "IsAgentReady",
      "url": "https://isagentready.com"
    }
  },
  "servers": [
    {
      "url": "https://isagentready.com",
      "description": "Production"
    }
  ],
  "paths": {
    "/api/v1/scan/{domain}": {
      "get": {
        "operationId": "getScanResults",
        "summary": "Get latest scan results for a domain",
        "description": "Returns the most recent completed scan results for the given domain, including overall score, letter grade, per-category breakdowns, and individual checkpoint results with recommendations.",
        "tags": [
          "Scans"
        ],
        "parameters": [
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "The domain to get scan results for (e.g., example.com)",
            "schema": {
              "type": "string",
              "example": "example.com"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Completed scan results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScanResult"
                }
              }
            }
          },
          "202": {
            "description": "Scan is in progress",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScanPending"
                }
              }
            }
          },
          "404": {
            "description": "No scan found for this domain",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/scan": {
      "post": {
        "operationId": "createScan",
        "summary": "Trigger a new scan",
        "description": "Start scanning a website for AI agent readiness. The scan runs asynchronously and typically takes 15-30 seconds. Poll GET /api/v1/scan/{domain} for results. If a recent scan exists (within 1 hour), returns the cached results instead.",
        "tags": [
          "Scans"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "The full URL to scan (must be http:// or https://)",
                    "example": "https://example.com"
                  }
                },
                "required": [
                  "url"
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Scan enqueued successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Scan ID"
                    },
                    "domain": {
                      "type": "string",
                      "description": "Normalized domain"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "running"
                      ]
                    },
                    "poll_url": {
                      "type": "string",
                      "description": "URL to poll for results"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "200": {
            "description": "Recent scan exists (cooldown), returning cached results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScanResult"
                }
              }
            }
          },
          "400": {
            "description": "Missing required parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid URL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded; retry after the number of seconds in the Retry-After header",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rankings": {
      "get": {
        "operationId": "getRankings",
        "summary": "Get AI readiness rankings",
        "description": "Returns a paginated, sorted list of website AI readiness scores. Supports filtering by grade range, category, and search.",
        "tags": [
          "Rankings"
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 25,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "grade_range",
            "in": "query",
            "required": false,
            "description": "Filter by grade range",
            "schema": {
              "type": "string",
              "enum": [
                "high",
                "mid",
                "low"
              ]
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Search by domain name",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Sort rankings by category score",
            "schema": {
              "type": "string",
              "enum": [
                "discovery",
                "search",
                "semantics",
                "protocols",
                "security"
              ]
            }
          },
          {
            "name": "industry",
            "in": "query",
            "required": false,
            "description": "Filter rankings by industry slug",
            "schema": {
              "type": "string",
              "enum": [
                "e-commerce",
                "news",
                "tech",
                "education",
                "government",
                "finance",
                "telecom",
                "travel",
                "logistics",
                "weather",
                "real-estate",
                "health",
                "energy",
                "food",
                "sports",
                "jobs",
                "culture",
                "entertainment",
                "insurance",
                "utilities"
              ]
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort order",
            "schema": {
              "type": "string",
              "enum": [
                "score_desc",
                "score_asc",
                "domain",
                "newest"
              ],
              "default": "score_desc"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated rankings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "entries": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RankingSummary"
                      }
                    },
                    "total": {
                      "type": "integer",
                      "description": "Total number of ranked websites"
                    },
                    "page": {
                      "type": "integer"
                    },
                    "per_page": {
                      "type": "integer"
                    },
                    "total_pages": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/rankings": {
      "get": {
        "operationId": "getCompactRankings",
        "summary": "Get compact AI readiness rankings",
        "description": "Returns paginated ranking summaries and one selected readiness profile without category or checkpoint bodies.",
        "tags": [
          "Rankings"
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 25,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "grade_range",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "high",
                "mid",
                "low"
              ]
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Sort by an overall category score. This does not sort by profile score.",
            "schema": {
              "type": "string",
              "enum": [
                "discovery",
                "search",
                "semantics",
                "protocols",
                "security"
              ]
            }
          },
          {
            "name": "industry",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "e-commerce",
                "news",
                "tech",
                "education",
                "government",
                "finance",
                "telecom",
                "travel",
                "logistics",
                "weather",
                "real-estate",
                "health",
                "energy",
                "food",
                "sports",
                "jobs",
                "culture",
                "entertainment",
                "insurance",
                "utilities"
              ]
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "score_desc",
                "score_asc",
                "domain",
                "newest"
              ],
              "default": "score_desc"
            }
          },
          {
            "name": "profile",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "ai_search_visibility",
                "browser_agent_usability",
                "api_tool_readiness",
                "agentic_commerce"
              ],
              "default": "ai_search_visibility"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Compact paginated rankings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompactRankingsPage"
                }
              }
            }
          },
          "400": {
            "description": "Unknown profile identifier",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/monitoring/sites": {
      "post": {
        "operationId": "createMonitoringSite",
        "summary": "Claim a site for monitoring",
        "tags": ["Monitoring"],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"type": "object", "required": ["url"], "properties": {"url": {"type": "string", "format": "uri"}, "locale": {"type": "string", "enum": ["en", "nl"]}}}}}
        },
        "responses": {
          "201": {"description": "Pending site claim and one-time management token", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringClaimResponse"}}}},
          "400": {"description": "Missing claim URL", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
          "409": {"description": "Domain already monitored", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
          "422": {"description": "Invalid claim", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
          "429": {"description": "Rate limit exceeded", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}
        }
      }
    },
    "/api/v1/monitoring/sites/{site_id}/verify": {
      "post": {
        "operationId": "verifyMonitoringSite",
        "summary": "Verify the site ownership challenge",
        "tags": ["Monitoring"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}],
        "responses": {"202": {"description": "Ownership verification queued", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringVerifyResponse"}}}}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}, "503": {"$ref": "#/components/responses/MonitoringInvalid"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/recovery": {
      "post": {
        "operationId": "recoverMonitoringSite",
        "summary": "Request a management recovery link",
        "tags": ["Monitoring"],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}],
        "responses": {"202": {"description": "Recovery request accepted", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringRecoveryResponse"}}}}, "429": {"description": "Rate limit exceeded", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}": {
      "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}],
      "get": {
        "operationId": "getMonitoringSite",
        "summary": "Get monitoring configuration",
        "tags": ["Monitoring"],
        "security": [{"bearerAuth": []}],
        "responses": {"200": {"description": "Monitoring site", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringSite"}}}}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}}
      },
      "patch": {
        "operationId": "updateMonitoringSite",
        "summary": "Pause, resume, or change cadence",
        "tags": ["Monitoring"],
        "security": [{"bearerAuth": []}],
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringSiteUpdateInput"}}}},
        "responses": {"200": {"description": "Updated site", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringSite"}}}}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}, "422": {"$ref": "#/components/responses/MonitoringInvalid"}}
      },
      "delete": {
        "operationId": "deleteMonitoringSite",
        "summary": "Delete the monitor and its history",
        "tags": ["Monitoring"],
        "security": [{"bearerAuth": []}],
        "responses": {"204": {"description": "Deleted"}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/policy": {
      "get": {
        "operationId": "getMonitoringPolicy",
        "summary": "Get the active immutable policy snapshot",
        "tags": ["Monitoring"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}],
        "responses": {"200": {"description": "Active policy", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringPolicy"}}}}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/policies": {
      "post": {
        "operationId": "createMonitoringPolicy",
        "summary": "Create and activate a new policy version",
        "tags": ["Monitoring"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}],
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringPolicyInput"}}}},
        "responses": {"200": {"description": "Existing idempotent policy version", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringPolicy"}}}}, "201": {"description": "New policy version", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringPolicy"}}}}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}, "422": {"$ref": "#/components/responses/MonitoringInvalid"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/history": {
      "get": {
        "operationId": "getMonitoringHistory",
        "summary": "List monitoring runs",
        "tags": ["Monitoring"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100}}, {"name": "before", "in": "query", "schema": {"type": "string", "format": "uuid"}}],
        "responses": {"200": {"description": "Monitoring history", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringHistoryResponse"}}}}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/runs/{run_id}/diff": {
      "get": {
        "operationId": "getMonitoringDiff",
        "summary": "Compare two monitoring runs",
        "tags": ["Monitoring"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}, {"name": "run_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}],
        "responses": {"200": {"description": "Run diff", "content": {"application/json": {"schema": {"type": "object"}}}}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}, "422": {"$ref": "#/components/responses/MonitoringInvalid"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/status": {
      "get": {
        "operationId": "getMonitoringStatus",
        "summary": "Get readiness gate status",
        "tags": ["Monitoring"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}],
        "responses": {"200": {"description": "Latest run passed", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringStatus"}}}}, "202": {"description": "No terminal run yet", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringStatus"}}}}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}, "412": {"description": "Latest run failed policy", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringStatus"}}}}, "503": {"description": "Latest scan failed", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringStatus"}}}}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/channels": {
      "post": {
        "operationId": "createMonitoringChannel",
        "summary": "Create an email or webhook channel",
        "tags": ["Monitoring"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}],
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringChannelInput"}}}},
        "responses": {"201": {"description": "Channel and optional one-time webhook secret", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringChannelResponse"}}}}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}, "422": {"$ref": "#/components/responses/MonitoringInvalid"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/channels/{channel_id}/rotate-secret": {
      "post": {
        "operationId": "rotateMonitoringChannelSecret",
        "summary": "Rotate a webhook signing secret",
        "tags": ["Monitoring"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}, {"$ref": "#/components/parameters/MonitoringChannelId"}],
        "responses": {"200": {"description": "Rotated one-time webhook secret", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonitoringChannelResponse"}}}}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}, "422": {"$ref": "#/components/responses/MonitoringInvalid"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/channels/{channel_id}": {
      "delete": {
        "operationId": "deleteMonitoringChannel",
        "summary": "Delete a notification channel",
        "tags": ["Monitoring"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}, {"$ref": "#/components/parameters/MonitoringChannelId"}],
        "responses": {"204": {"description": "Deleted"}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/outcome-imports/search-console": {
      "post": {
        "operationId": "importSearchConsoleOutcomes",
        "summary": "Import bounded Search Console daily evidence",
        "description": "Requires a verified, unexpired owner. The raw application/octet-stream body uses the IARSC1 envelope containing separate Dates.csv and Filters.csv bytes, each capped at 2 MiB. Authentication runs before the body is consumed. Query and page exports are not accepted. Provenance is owner_uploaded_search_console_csv and associations never establish causation.",
        "tags": ["Outcomes"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}, {"name": "request_id", "in": "query", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "property", "in": "query", "required": true, "schema": {"type": "string"}}],
        "requestBody": {"required": true, "content": {"application/octet-stream": {"schema": {"type": "string", "format": "binary"}}}},
        "responses": {"200": {"description": "Completed import or idempotent original", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OutcomeImport"}}}}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}, "422": {"$ref": "#/components/responses/MonitoringInvalid"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/outcome-imports/crawler-log": {
      "post": {
        "operationId": "importCrawlerLogOutcomes",
        "summary": "Import a bounded canonical crawler-log CSV",
        "description": "Requires a verified, unexpired owner. Authentication runs before the raw text/csv or application/octet-stream body is consumed. The body is capped at 25 MiB and 250000 rows. Raw IP addresses, full user agents, paths and referers are discarded. Verified counts mean matched provider-published range snapshot, not cryptographic attestation.",
        "tags": ["Outcomes"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}, {"name": "request_id", "in": "query", "required": true, "schema": {"type": "string", "format": "uuid"}}],
        "requestBody": {"required": true, "content": {"text/csv": {"schema": {"type": "string", "format": "binary"}}, "application/octet-stream": {"schema": {"type": "string", "format": "binary"}}}},
        "responses": {"200": {"description": "Completed import or idempotent original", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OutcomeImport"}}}}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}, "422": {"$ref": "#/components/responses/MonitoringInvalid"}, "503": {"description": "No complete official crawler source snapshot available"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/outcome-imports/{batch_id}": {
      "delete": {
        "operationId": "deleteOutcomeImport",
        "summary": "Hard-delete one private import and its aggregates",
        "tags": ["Outcomes"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}, {"name": "batch_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}],
        "responses": {"204": {"description": "Private import deleted"}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/discoverability-observations": {
      "post": {
        "operationId": "importDiscoverabilityObservations",
        "summary": "Import bounded provider-neutral discoverability observations",
        "description": "Requires a verified, unexpired owner. Validates every observation before one atomic import. Evidence is experimental, excluded from every score, and never supports a causal claim.",
        "tags": ["Outcomes"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}],
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DiscoverabilityObservationImportInput"}}}},
        "responses": {"201": {"description": "Immutable batch created or idempotent original returned", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DiscoverabilityObservationBatch"}}}}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}, "409": {"description": "Request identifier was reused for different content", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "422": {"$ref": "#/components/responses/MonitoringInvalid"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/discoverability-observations/{batch_id}": {
      "delete": {
        "operationId": "deleteDiscoverabilityObservationBatch",
        "summary": "Hard-delete one private discoverability batch",
        "tags": ["Outcomes"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}, {"name": "batch_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}],
        "responses": {"204": {"description": "Private discoverability batch deleted"}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/outcomes": {
      "get": {
        "operationId": "getOutcomeTimeline",
        "summary": "Get bounded private outcome and intervention evidence",
        "description": "Returns descriptive observations with causal_claim false. Search Console uses America/Los_Angeles source days and crawler logs use UTC.",
        "tags": ["Outcomes"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}, {"name": "date_from", "in": "query", "schema": {"type": "string", "format": "date"}}, {"name": "date_to", "in": "query", "schema": {"type": "string", "format": "date"}}, {"name": "batch_ids", "in": "query", "schema": {"type": "string"}}],
        "responses": {"200": {"description": "Private bounded timeline", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OutcomeTimeline"}}}}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}, "422": {"$ref": "#/components/responses/MonitoringInvalid"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/interventions": {
      "post": {
        "operationId": "createOutcomeIntervention",
        "summary": "Create one immutable owner intervention",
        "tags": ["Outcomes"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}],
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OutcomeInterventionInput"}}}},
        "responses": {"201": {"description": "Immutable intervention created"}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}, "422": {"$ref": "#/components/responses/MonitoringInvalid"}}
      }
    },
    "/api/v1/monitoring/sites/{site_id}/interventions/{intervention_id}": {
      "delete": {
        "operationId": "deleteOutcomeIntervention",
        "summary": "Hard-delete one owner intervention",
        "tags": ["Outcomes"],
        "security": [{"bearerAuth": []}],
        "parameters": [{"$ref": "#/components/parameters/MonitoringSiteId"}, {"name": "intervention_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}],
        "responses": {"204": {"description": "Intervention deleted"}, "404": {"$ref": "#/components/responses/MonitoringNotFound"}}
      }
    },
    "/api/v2/benchmarks/state-of-agent-ready-web/{version}": {
      "get": {
        "operationId": "getStateOfAgentReadyWebBenchmark",
        "summary": "Get one immutable published benchmark snapshot",
        "description": "Aggregate research for a fixed sample of eligible, previously submitted public sites. It is not an estimate of all websites and never includes private outcome imports.",
        "tags": ["Benchmarks"],
        "parameters": [{"name": "version", "in": "path", "required": true, "schema": {"type": "string"}}],
        "responses": {"200": {"description": "Persisted immutable aggregate snapshot", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BenchmarkSnapshot"}}}}, "404": {"description": "Unknown or unpublished version"}}
      }
    },
    "/mcp": {
      "post": {
        "operationId": "mcpRequest",
        "summary": "MCP Streamable HTTP endpoint",
        "description": "Model Context Protocol server endpoint. Send JSON-RPC 2.0 requests to interact with the IsAgentReady scanner tools. Supports initialize, tools/list, and tools/call methods.",
        "tags": [
          "MCP"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "jsonrpc": {
                    "type": "string",
                    "const": "2.0"
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "initialize",
                      "tools/list",
                      "tools/call"
                    ],
                    "description": "The JSON-RPC method to call"
                  },
                  "id": {
                    "description": "Request ID (omit for notifications)",
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "integer"
                      }
                    ]
                  },
                  "params": {
                    "type": "object",
                    "description": "Method-specific parameters"
                  }
                },
                "required": [
                  "jsonrpc",
                  "method"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {
                      "type": "string",
                      "const": "2.0"
                    },
                    "result": {
                      "type": "object"
                    },
                    "id": {}
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "iar_mon_ token"
      }
    },
    "parameters": {
      "MonitoringSiteId": {"name": "site_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}},
      "MonitoringChannelId": {"name": "channel_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}
    },
    "responses": {
      "MonitoringNotFound": {"description": "Site or resource not found", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "MonitoringInvalid": {"description": "Invalid monitoring request", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}
    },
    "schemas": {
      "ScanResult": {
        "type": "object",
        "required": ["access_blockers"],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "domain": {
            "type": "string",
            "example": "example.com"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "completed",
              "failed",
              "canceled"
            ]
          },
          "overall_score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Overall AI readiness score"
          },
          "letter_grade": {
            "type": "string",
            "enum": [
              "F",
              "D",
              "C",
              "B",
              "A",
              "A+"
            ],
            "description": "Letter grade based on overall score"
          },
          "methodology_version": {
            "type": "string",
            "description": "Immutable scoring methodology version, or legacy for historical scans"
          },
          "schema_version": {
            "type": "string",
            "description": "Version of the canonical public report representation"
          },
          "report_url": {
            "type": "string",
            "description": "Localized URL for the latest report"
          },
          "snapshot_url": {
            "type": "string",
            "description": "Localized immutable URL for this exact scan"
          },
          "scanned_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "score_breakdown": {
            "type": "object",
            "description": "Canonical stable-core and adoption score breakdown"
          },
          "surfaces": {
            "type": "object",
            "description": "Detected agent-facing surfaces and their persisted classification"
          },
          "issues": {
            "type": "array",
            "description": "Prioritized failed and partial checkpoints",
            "items": {
              "type": "object",
              "required": ["maturity", "access_blocker"],
              "properties": {
                "id": {"type": "string"},
                "category": {"type": "string"},
                "name": {"type": "string"},
                "status": {"type": "string"},
                "priority": {"type": "string", "enum": ["high", "medium"]},
                "potential_gain": {"type": "integer"},
                "recommendation": {"type": "string", "nullable": true},
                "evidence": {"type": "string", "nullable": true},
                "references": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": ["title", "url"],
                    "properties": {
                      "title": {"type": "string", "maxLength": 240},
                      "url": {"type": "string", "maxLength": 2048}
                    }
                  }
                },
                "maturity": {
                  "type": "string",
                  "enum": ["essential", "recommended", "emerging"]
                },
                "access_blocker": {"type": "boolean"}
              }
            }
          },
          "access_blockers": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["kind", "provider", "title"],
              "properties": {
                "kind": {"type": "string"},
                "provider": {"type": "string"},
                "title": {"type": "string"}
              }
            }
          },
          "browser_journeys": {
            "type": "object",
            "description": "Qualitative browser evidence excluded from the numeric score",
            "properties": {
              "included_in_score": {"type": "boolean", "enum": [false]},
              "evidence": {"type": "array", "items": {"type": "object"}}
            }
          },
          "profiles": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ProfileResults"
              },
              {
                "type": "null"
              }
            ]
          },
          "scan_duration_ms": {
            "type": "integer",
            "description": "Scan duration in milliseconds"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time"
          },
          "categories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Category"
            }
          },
          "browser_tasks": {
            "type": "array",
            "description": "Optional experimental browser evidence. It is not included in readiness scores.",
            "items": {
              "$ref": "#/components/schemas/BrowserTaskEvidence"
            }
          }
        }
      },
      "RankingSummary": {
        "type": "object",
        "description": "Compact scan summary returned by the V1 rankings endpoint.",
        "required": [
          "id",
          "domain",
          "status",
          "overall_score",
          "letter_grade",
          "methodology_version",
          "profiles",
          "scan_duration_ms",
          "completed_at",
          "categories"
        ],
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "domain": {"type": "string", "example": "example.com"},
          "status": {
            "type": "string",
            "enum": ["pending", "running", "completed", "failed", "canceled"]
          },
          "overall_score": {"type": "integer", "minimum": 0, "maximum": 100},
          "letter_grade": {"type": "string", "enum": ["F", "D", "C", "B", "A", "A+"]},
          "methodology_version": {"type": "string"},
          "profiles": {
            "$ref": "#/components/schemas/ProfileResults"
          },
          "scan_duration_ms": {"type": "integer", "minimum": 0},
          "completed_at": {"type": "string", "format": "date-time"},
          "categories": {
            "type": "array",
            "items": {"$ref": "#/components/schemas/Category"}
          },
          "browser_tasks": {
            "type": "array",
            "deprecated": true,
            "description": "Deprecated compatibility property. Browser evidence is available from the scan detail endpoint and is omitted from ranking responses.",
            "items": {"$ref": "#/components/schemas/BrowserTaskEvidence"}
          }
        }
      },
      "BrowserTaskEvidence": {
        "type": "object",
        "properties": {
          "task_key": {"type": "string"},
          "objective": {"type": "string"},
          "status": {"type": "string", "enum": ["pending", "running", "completed", "failed", "skipped"]},
          "outcome": {"type": "string", "nullable": true, "enum": ["success", "partial", "failure", "not_applicable"]},
          "protocol_path": {"type": "string", "nullable": true},
          "evidence": {"type": "object"},
          "failure_code": {"type": "string", "nullable": true},
          "probe_version": {"type": "string"},
          "experimental": {"type": "boolean", "enum": [true]},
          "included_in_score": {"type": "boolean", "enum": [false]}
        },
        "required": ["task_key", "objective", "status", "probe_version", "experimental", "included_in_score"]
      },
      "ScanPending": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "domain": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running"
            ]
          },
          "methodology_version": {
            "type": "string"
          },
          "profiles": {
            "type": "null",
            "description": "Profile snapshot is populated only when the scan completes"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "Category": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Canonical category identifier"
          },
          "category": {
            "type": "string",
            "enum": [
              "discovery",
              "structured_data",
              "semantics",
              "agent_protocols",
              "security"
            ],
            "description": "Category identifier"
          },
          "label": {
            "type": "string",
            "description": "Human-readable category name"
          },
          "score": {
            "type": "integer",
            "description": "Points scored"
          },
          "max_score": {
            "type": "integer",
            "description": "Maximum possible points"
          },
          "percentage": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Canonical percentage score for this category"
          },
          "weight": {
            "type": "integer",
            "description": "Category weight as percentage (e.g., 30 for 30%)"
          },
          "checkpoints": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Checkpoint"
            }
          }
        }
      },
      "Checkpoint": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Checkpoint ID (e.g., '1.1', '4.3')"
          },
          "name": {
            "type": "string",
            "description": "Checkpoint name"
          },
          "status": {
            "type": "string",
            "enum": [
              "pass",
              "partial",
              "fail",
              "skip"
            ]
          },
          "score": {
            "type": "integer",
            "description": "Points scored"
          },
          "max_score": {
            "type": "integer",
            "description": "Maximum possible points"
          },
          "evidence_tier": {
            "oneOf": [
              {
                "type": "string",
                "enum": [
                  "standard",
                  "supported",
                  "emerging",
                  "experimental"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Evidence maturity for this methodology version"
          },
          "profile_applicability": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "ai_search_visibility",
                "browser_agent_usability",
                "api_tool_readiness",
                "agentic_commerce"
              ]
            }
          },
          "details": {
            "type": "string",
            "description": "What was found or not found"
          },
          "recommendation": {
            "type": "string",
            "description": "Actionable recommendation for improvement"
          },
          "why": {
            "type": "string",
            "description": "Why this checkpoint matters"
          },
          "code_example": {
            "type": "string",
            "description": "Example code to implement the recommendation"
          },
          "references": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["title", "url"],
              "properties": {
                "title": {"type": "string", "maxLength": 240},
                "url": {"type": "string", "maxLength": 2048}
              }
            },
            "description": "Public references supporting the checkpoint"
          },
          "score_role": {
            "type": "string",
            "nullable": true,
            "description": "Role of this checkpoint in the stored methodology"
          },
          "surface_applicability": {
            "type": "array",
            "items": {"type": "string"},
            "description": "Detected surfaces to which this checkpoint applies"
          }
        }
      },
      "ProfileResults": {
        "type": "object",
        "properties": {
          "ai_search_visibility": {
            "$ref": "#/components/schemas/ProfileResult"
          },
          "browser_agent_usability": {
            "$ref": "#/components/schemas/ProfileResult"
          },
          "api_tool_readiness": {
            "$ref": "#/components/schemas/ProfileResult"
          },
          "agentic_commerce": {
            "$ref": "#/components/schemas/ProfileResult"
          }
        }
      },
      "ProfileResult": {
        "type": "object",
        "properties": {
          "score": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "maximum": 100
          },
          "applicable_score": {
            "type": "integer"
          },
          "applicable_max_score": {
            "type": "integer"
          },
          "applicable": {
            "type": "boolean"
          },
          "methodology_version": {
            "type": "string"
          }
        }
      },
      "CompactRankingsPage": {
        "type": "object",
        "required": [
          "entries",
          "total",
          "page",
          "per_page",
          "total_pages"
        ],
        "properties": {
          "entries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CompactRankingEntry"
            }
          },
          "total": {
            "type": "integer"
          },
          "page": {
            "type": "integer"
          },
          "per_page": {
            "type": "integer"
          },
          "total_pages": {
            "type": "integer"
          }
        }
      },
      "CompactRankingEntry": {
        "type": "object",
        "required": [
          "domain",
          "overall_score",
          "letter_grade",
          "profile",
          "methodology_version",
          "completed_at"
        ],
        "properties": {
          "domain": {
            "type": "string"
          },
          "overall_score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "letter_grade": {
            "type": "string",
            "enum": [
              "F",
              "D",
              "C",
              "B",
              "A",
              "A+"
            ]
          },
          "profile": {
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/CompactProfile"
              }
            ]
          },
          "methodology_version": {
            "type": "string"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "CompactProfile": {
        "type": "object",
        "required": [
          "id",
          "score",
          "applicable"
        ],
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "ai_search_visibility",
              "browser_agent_usability",
              "api_tool_readiness",
              "agentic_commerce"
            ]
          },
          "score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "nullable": true
          },
          "applicable": {
            "type": "boolean"
          }
        }
      },
      "MonitoringSite": {
        "type": "object",
        "required": ["id", "domain", "status", "schedule", "next_run_at", "current_policy_version", "locale", "ownership_expires_at", "channels"],
        "properties": {"id": {"type": "string", "format": "uuid"}, "domain": {"type": "string"}, "status": {"type": "string", "enum": ["pending", "verified", "paused", "ownership_lost"]}, "schedule": {"type": "string", "enum": ["daily", "weekly"], "nullable": true}, "next_run_at": {"type": "string", "format": "date-time", "nullable": true}, "current_policy_version": {"type": "integer", "minimum": 0}, "locale": {"type": "string", "enum": ["en", "nl"]}, "ownership_expires_at": {"type": "string", "format": "date-time", "nullable": true}, "channels": {"type": "array", "items": {"$ref": "#/components/schemas/MonitoringChannel"}}}
      },
      "MonitoringClaimResponse": {
        "type": "object",
        "required": ["site", "management_token", "proof_url", "challenge"],
        "properties": {"site": {"$ref": "#/components/schemas/MonitoringSite"}, "management_token": {"type": "string", "writeOnly": true}, "proof_url": {"type": "string", "format": "uri"}, "challenge": {"type": "string"}}
      },
      "MonitoringVerifyResponse": {
        "type": "object",
        "required": ["status"],
        "properties": {"status": {"type": "string", "enum": ["verification_queued"]}}
      },
      "MonitoringRecoveryResponse": {
        "type": "object",
        "required": ["status"],
        "properties": {"status": {"type": "string", "enum": ["recovery_requested"]}}
      },
      "MonitoringSiteUpdateInput": {
        "type": "object",
        "properties": {"status": {"type": "string", "enum": ["verified", "paused"]}, "schedule": {"type": "string", "enum": ["daily", "weekly"]}, "locale": {"type": "string", "enum": ["en", "nl"]}}
      },
      "MonitoringPolicyInput": {
        "type": "object",
        "required": ["request_id", "schema_version", "profile", "baseline_scan_id", "required_checks", "exceptions"],
        "properties": {"request_id": {"type": "string", "format": "uuid"}, "schema_version": {"type": "string", "enum": ["1"]}, "profile": {"type": "string", "enum": ["ai_search_visibility", "browser_agent_usability", "api_tool_readiness", "agentic_commerce"]}, "baseline_scan_id": {"type": "string", "format": "uuid"}, "required_checks": {"type": "array", "items": {"type": "object", "required": ["id", "minimum_status"], "properties": {"id": {"type": "string"}, "minimum_status": {"type": "string", "enum": ["fail", "partial", "pass"]}}}, "exceptions": {"type": "array", "items": {"type": "object", "required": ["checkpoint_id", "reason", "expires_at"], "properties": {"checkpoint_id": {"type": "string"}, "reason": {"type": "string"}, "expires_at": {"type": "string", "format": "date-time"}}}}}}
      },
      "MonitoringPolicy": {
        "type": "object",
        "required": ["id", "version", "schema_version", "methodology_version", "profile", "baseline_scan_id", "required_checks", "exceptions", "created_at"],
        "properties": {"id": {"type": "string", "format": "uuid"}, "version": {"type": "integer", "minimum": 1}, "schema_version": {"type": "string"}, "methodology_version": {"type": "string"}, "profile": {"type": "string"}, "baseline_scan_id": {"type": "string", "format": "uuid"}, "required_checks": {"type": "array", "items": {"type": "object"}}, "exceptions": {"type": "array", "items": {"type": "object"}}, "created_at": {"type": "string", "format": "date-time"}}
      },
      "MonitoringRun": {
        "type": "object",
        "required": ["id", "scan_id", "policy_id", "baseline_scan_id", "scheduled_for", "status", "conclusion", "severity", "methodology_changed", "result", "evaluated_at"],
        "properties": {"id": {"type": "string", "format": "uuid"}, "scan_id": {"type": "string", "format": "uuid"}, "policy_id": {"type": "string", "format": "uuid"}, "baseline_scan_id": {"type": "string", "format": "uuid"}, "scheduled_for": {"type": "string", "format": "date-time"}, "status": {"type": "string", "enum": ["awaiting_scan", "evaluated", "scan_failed"]}, "conclusion": {"type": "string", "enum": ["success", "failure", "neutral", "error"], "nullable": true}, "severity": {"type": "string", "enum": ["none", "info", "warning", "critical"], "nullable": true}, "methodology_changed": {"type": "boolean"}, "result": {"type": "object", "nullable": true}, "evaluated_at": {"type": "string", "format": "date-time", "nullable": true}}
      },
      "MonitoringHistoryResponse": {
        "type": "object",
        "required": ["runs"],
        "properties": {"runs": {"type": "array", "items": {"$ref": "#/components/schemas/MonitoringRun"}}}
      },
      "MonitoringStatus": {
        "type": "object",
        "required": ["run_id", "generated_at", "latest_run_at", "next_run_at"],
        "properties": {"run_id": {"type": "string", "format": "uuid"}, "generated_at": {"type": "string", "format": "date-time"}, "latest_run_at": {"type": "string", "format": "date-time"}, "next_run_at": {"type": "string", "format": "date-time", "nullable": true}, "schema_version": {"type": "string"}, "site_id": {"type": "string", "format": "uuid"}, "policy": {"type": "object"}, "baseline": {"type": "object"}, "current": {"type": "object"}, "evaluated_at": {"type": "string", "format": "date-time"}, "comparison": {"type": "string", "enum": ["comparable", "methodology_changed", "scan_failed"]}, "conclusion": {"type": "string", "enum": ["success", "failure", "neutral", "error"]}, "severity": {"type": "string", "enum": ["none", "info", "warning", "critical"]}, "methodology_changed": {"type": "boolean"}, "profile_delta": {"type": "integer", "nullable": true}, "changes": {"type": "array", "items": {"type": "object"}}, "violations": {"type": "array", "items": {"type": "object"}}}
      },
      "MonitoringChannelInput": {
        "type": "object",
        "required": ["request_id", "kind", "target"],
        "properties": {"request_id": {"type": "string", "format": "uuid"}, "kind": {"type": "string", "enum": ["email", "webhook"]}, "target": {"type": "string"}}
      },
      "MonitoringChannel": {
        "type": "object",
        "required": ["id", "kind", "status", "target", "verified_at"],
        "properties": {"id": {"type": "string", "format": "uuid"}, "kind": {"type": "string", "enum": ["email", "webhook"]}, "status": {"type": "string", "enum": ["pending", "verified", "disabled"]}, "target": {"type": "string", "description": "Masked destination"}, "verified_at": {"type": "string", "format": "date-time", "nullable": true}}
      },
      "MonitoringChannelResponse": {
        "type": "object",
        "required": ["channel"],
        "properties": {"channel": {"$ref": "#/components/schemas/MonitoringChannel"}, "webhook_secret": {"type": "string", "writeOnly": true}}
      },
      "OutcomeImport": {
        "type": "object",
        "required": ["id", "source_type", "status", "schema_version", "source_date_from", "source_date_to", "source_timezone", "source_scope", "accepted_rows", "rejected_rows", "unverified_rows", "provenance", "retention_expires_at"],
        "properties": {"id": {"type": "string", "format": "uuid"}, "source_type": {"type": "string", "enum": ["search_console", "crawler_log"]}, "status": {"type": "string", "enum": ["completed"]}, "schema_version": {"type": "string", "enum": ["1"]}, "source_date_from": {"type": "string", "format": "date"}, "source_date_to": {"type": "string", "format": "date"}, "source_timezone": {"type": "string", "enum": ["America/Los_Angeles", "UTC"]}, "source_scope": {"type": "object"}, "accepted_rows": {"type": "integer", "minimum": 0}, "rejected_rows": {"type": "integer", "minimum": 0}, "unverified_rows": {"type": "integer", "minimum": 0}, "provenance": {"type": "string", "enum": ["owner_uploaded_search_console_csv", "owner_uploaded_canonical_crawler_log"]}, "retention_expires_at": {"type": "string", "format": "date-time"}}
      },
      "DiscoverabilityObservationImportInput": {
        "type": "object",
        "additionalProperties": false,
        "required": ["request_id", "schema_version", "provider", "model", "locale", "provenance", "observations"],
        "properties": {"request_id": {"type": "string", "format": "uuid"}, "schema_version": {"type": "string", "enum": ["1"]}, "provider": {"type": "string", "minLength": 1, "maxLength": 80, "x-maxBytes": 80, "description": "Provider identifier, capped at 80 UTF-8 bytes."}, "model": {"type": "string", "minLength": 1, "maxLength": 120, "x-maxBytes": 120, "description": "Model or engine identifier, capped at 120 UTF-8 bytes."}, "locale": {"type": "string", "minLength": 2, "maxLength": 35, "x-maxBytes": 35, "description": "Normalized locale, capped at 35 UTF-8 bytes."}, "provenance": {"type": "object", "maxProperties": 20, "x-maxBytes": 4000, "description": "Credential-free provenance metadata, capped at 4000 canonical JSON bytes. Secret key names are rejected after separator and case normalization."}, "observations": {"type": "array", "minItems": 1, "maxItems": 20, "uniqueItems": true, "items": {"$ref": "#/components/schemas/DiscoverabilityObservationInput"}}}
      },
      "DiscoverabilityObservationInput": {
        "type": "object",
        "additionalProperties": false,
        "required": ["probe_key", "status", "evidence_source", "observed_at"],
        "oneOf": [{"description": "A found observation. Position is optional. Brand and developer probes require a credential-free same-site citation URL, with subdomains allowed only by the immutable probe definition.", "properties": {"status": {"type": "string", "enum": ["found"]}}, "oneOf": [{"properties": {"probe_key": {"type": "string", "enum": ["brand_discovery", "developer_discovery"]}, "citation_url": {"type": "string", "format": "uri", "nullable": false}}, "required": ["citation_url"]}, {"properties": {"probe_key": {"type": "string", "enum": ["recommendation_presence"]}}}]}, {"description": "A non-found, ambiguous, or error observation. Position must be null or absent.", "properties": {"status": {"type": "string", "enum": ["not_found", "ambiguous", "error"]}, "position": {"type": "integer", "nullable": true, "enum": [null]}}}],
        "properties": {"probe_key": {"type": "string", "enum": ["brand_discovery", "developer_discovery", "recommendation_presence"], "maxLength": 80, "x-maxBytes": 80}, "status": {"type": "string", "enum": ["found", "not_found", "ambiguous", "error"]}, "position": {"type": "integer", "minimum": 1, "maximum": 10000, "nullable": true, "description": "Allowed only when status is found."}, "citation_url": {"type": "string", "format": "uri", "maxLength": 2048, "x-maxBytes": 2048, "nullable": true, "description": "Credential-free HTTP(S) URL, capped at 2048 UTF-8 bytes. Required when brand_discovery or developer_discovery is found. Any supplied citation for brand_discovery and developer_discovery, including non-found observations, is same-site validated. Subdomains are accepted only when the immutable probe definition allows them. Query and fragment parameters may not contain credential names or values."}, "answer_summary": {"type": "string", "maxLength": 2000, "x-maxBytes": 2000, "nullable": true}, "evidence_source": {"type": "string", "enum": ["provider_response", "provider_citation", "manual_review"]}, "evidence": {"type": "string", "maxLength": 4000, "x-maxBytes": 4000, "nullable": true}, "observed_at": {"type": "string", "format": "date-time", "maxLength": 64, "x-maxBytes": 64}}
      },
      "DiscoverabilityObservationBatch": {
        "type": "object",
        "additionalProperties": false,
        "required": ["id", "request_id", "schema_version", "probe_set_version", "probe_set_hash", "provider", "model", "locale", "provenance", "observation_count", "experimental", "included_in_score", "causal_claim", "inserted_at", "observations"],
        "properties": {"id": {"type": "string", "format": "uuid"}, "request_id": {"type": "string", "format": "uuid"}, "schema_version": {"type": "string", "enum": ["1"]}, "probe_set_version": {"type": "string"}, "probe_set_hash": {"type": "string", "pattern": "^[0-9a-f]{64}$"}, "provider": {"type": "string"}, "model": {"type": "string"}, "locale": {"type": "string"}, "provenance": {"type": "object"}, "observation_count": {"type": "integer", "minimum": 1, "maximum": 20}, "experimental": {"type": "boolean", "enum": [true]}, "included_in_score": {"type": "boolean", "enum": [false]}, "causal_claim": {"type": "boolean", "enum": [false]}, "inserted_at": {"type": "string", "format": "date-time"}, "observations": {"type": "array", "items": {"$ref": "#/components/schemas/DiscoverabilityObservation"}}}
      },
      "DiscoverabilityObservation": {
        "type": "object",
        "additionalProperties": false,
        "required": ["id", "batch_id", "probe_set_version", "probe_set_hash", "provider", "model", "locale", "probe_key", "prompt_sha256", "status", "position", "citation_url", "answer_summary", "evidence_source", "evidence", "observed_at", "provenance", "experimental", "included_in_score", "causal_claim", "label"],
        "properties": {"id": {"type": "string", "format": "uuid"}, "batch_id": {"type": "string", "format": "uuid"}, "probe_set_version": {"type": "string"}, "probe_set_hash": {"type": "string", "pattern": "^[0-9a-f]{64}$"}, "provider": {"type": "string"}, "model": {"type": "string"}, "locale": {"type": "string"}, "probe_key": {"type": "string"}, "prompt_sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"}, "status": {"type": "string", "enum": ["found", "not_found", "ambiguous", "error"]}, "position": {"type": "integer", "minimum": 1, "maximum": 10000, "nullable": true}, "citation_url": {"type": "string", "format": "uri", "nullable": true}, "answer_summary": {"type": "string", "nullable": true}, "evidence_source": {"type": "string", "enum": ["provider_response", "provider_citation", "manual_review"]}, "evidence": {"type": "string", "nullable": true}, "observed_at": {"type": "string", "format": "date-time"}, "provenance": {"type": "object"}, "experimental": {"type": "boolean", "enum": [true]}, "included_in_score": {"type": "boolean", "enum": [false]}, "causal_claim": {"type": "boolean", "enum": [false]}, "label": {"type": "string", "enum": ["observation"]}}
      },
      "OutcomeTimeline": {
        "type": "object",
        "required": ["date_from", "date_to", "selected_batches", "available_batches", "overlapping_batches", "daily_metrics", "interventions", "associations", "discoverability_associations", "discoverability_observations", "discoverability_observations_meta", "scans", "monitoring_runs", "interpretation", "causal_claim", "caveats"],
        "properties": {"date_from": {"type": "string", "format": "date"}, "date_to": {"type": "string", "format": "date"}, "selected_batches": {"type": "array", "items": {"$ref": "#/components/schemas/OutcomeBatchSummary"}}, "available_batches": {"type": "array", "items": {"$ref": "#/components/schemas/OutcomeBatchSummary"}}, "overlapping_batches": {"type": "object", "additionalProperties": {"type": "boolean"}}, "daily_metrics": {"type": "array", "items": {"$ref": "#/components/schemas/OutcomeDailyMetric"}}, "interventions": {"type": "array", "items": {"$ref": "#/components/schemas/OutcomeIntervention"}}, "associations": {"type": "array", "items": {"$ref": "#/components/schemas/OutcomeAssociation"}}, "discoverability_associations": {"type": "array", "items": {"$ref": "#/components/schemas/DiscoverabilityAssociation"}}, "discoverability_observations": {"type": "array", "maxItems": 100, "items": {"$ref": "#/components/schemas/DiscoverabilityObservation"}}, "discoverability_observations_meta": {"$ref": "#/components/schemas/DiscoverabilityObservationTimelineMeta"}, "scans": {"type": "array", "items": {"$ref": "#/components/schemas/OutcomeScanEvidence"}}, "monitoring_runs": {"type": "array", "items": {"$ref": "#/components/schemas/OutcomeMonitoringObservation"}}, "interpretation": {"type": "string", "enum": ["observed_association_only"]}, "causal_claim": {"type": "boolean", "enum": [false]}, "caveats": {"type": "array", "items": {"type": "string"}}}
      },
      "DiscoverabilityObservationTimelineMeta": {
        "type": "object",
        "additionalProperties": false,
        "required": ["limit", "returned", "truncated", "order"],
        "properties": {"limit": {"type": "integer", "enum": [100]}, "returned": {"type": "integer", "minimum": 0, "maximum": 100}, "truncated": {"type": "boolean"}, "order": {"type": "string", "enum": ["chronological"]}}
      },
      "OutcomeBatchSummary": {
        "type": "object",
        "required": ["id", "source_type", "date_from", "date_to", "source_timezone", "source_scope", "provenance", "retention_expires_at"],
        "properties": {"id": {"type": "string", "format": "uuid"}, "source_type": {"type": "string", "enum": ["search_console", "crawler_log"]}, "date_from": {"type": "string", "format": "date"}, "date_to": {"type": "string", "format": "date"}, "source_timezone": {"type": "string", "enum": ["America/Los_Angeles", "UTC"]}, "source_scope": {"type": "object"}, "provenance": {"type": "string", "enum": ["owner_uploaded_search_console_csv", "owner_uploaded_canonical_crawler_log"]}, "retention_expires_at": {"type": "string", "format": "date-time"}}
      },
      "CrawlerSnapshotProvenance": {
        "type": "object",
        "required": ["id", "source_url", "provider_creation_time", "fetched_at", "content_sha256", "verification_basis"],
        "properties": {"id": {"type": "string", "format": "uuid"}, "source_url": {"type": "string", "format": "uri"}, "provider_creation_time": {"type": "string", "format": "date-time"}, "fetched_at": {"type": "string", "format": "date-time"}, "content_sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"}, "verification_basis": {"type": "string", "enum": ["matched_provider_published_range_snapshot"]}}
      },
      "OutcomeDailyMetric": {
        "type": "object",
        "required": ["date", "metric_key", "evidence_kind", "value"],
        "properties": {"date": {"type": "string", "format": "date"}, "metric_key": {"type": "string"}, "provider": {"type": "string", "nullable": true}, "product": {"type": "string", "nullable": true}, "classifier_version": {"type": "string", "nullable": true}, "evidence_kind": {"type": "string", "enum": ["owner_uploaded", "verified_official_range", "claimed_historical", "unclassified", "classified_referral", "self_declared_utm"]}, "status_class": {"type": "integer", "minimum": 1, "maximum": 5, "nullable": true}, "crawler_source_snapshot": {"allOf": [{"$ref": "#/components/schemas/CrawlerSnapshotProvenance"}], "nullable": true}, "value": {"oneOf": [{"type": "integer"}, {"type": "string"}]}}
      },
      "OutcomeIntervention": {
        "type": "object",
        "required": ["id", "occurred_at", "kind", "title", "label"],
        "properties": {"id": {"type": "string", "format": "uuid"}, "occurred_at": {"type": "string", "format": "date-time"}, "kind": {"type": "string", "enum": ["readiness_change", "content_change", "infrastructure_change", "measurement_change", "other"]}, "title": {"type": "string", "maxLength": 120}, "related_scan_id": {"type": "string", "format": "uuid", "nullable": true}, "label": {"type": "string", "enum": ["intervention"]}}
      },
      "OutcomeAssociation": {
        "type": "object",
        "required": ["intervention_id", "source", "status", "result"],
        "properties": {"intervention_id": {"type": "string", "format": "uuid"}, "source": {"type": "string", "enum": ["search_console", "crawler_log"]}, "status": {"type": "string", "enum": ["available", "insufficient_coverage", "source_version_mismatch", "methodology_version_mismatch"]}, "result": {"allOf": [{"$ref": "#/components/schemas/OutcomeAssociationResult"}], "nullable": true}}
      },
      "DiscoverabilityAssociation": {
        "type": "object",
        "additionalProperties": false,
        "required": ["intervention_id", "source", "probe_key", "identity", "status", "experimental", "included_in_score", "causal_claim", "result"],
        "properties": {"intervention_id": {"type": "string", "format": "uuid"}, "source": {"type": "string", "enum": ["discoverability"]}, "probe_key": {"type": "string"}, "identity": {"$ref": "#/components/schemas/DiscoverabilityObservationIdentity"}, "status": {"type": "string", "enum": ["available", "insufficient_coverage", "version_incompatible"]}, "experimental": {"type": "boolean", "enum": [true]}, "included_in_score": {"type": "boolean", "enum": [false]}, "causal_claim": {"type": "boolean", "enum": [false]}, "result": {"$ref": "#/components/schemas/DiscoverabilityAssociationResult"}}
      },
      "DiscoverabilityAssociationResult": {
        "type": "object",
        "additionalProperties": false,
        "required": ["analysis_version", "interpretation", "causal_claim", "before", "after", "incompatible_dimensions", "limitations"],
        "properties": {"analysis_version": {"type": "string", "enum": ["1"]}, "interpretation": {"type": "string", "enum": ["observed_association_only"]}, "causal_claim": {"type": "boolean", "enum": [false]}, "before": {"allOf": [{"$ref": "#/components/schemas/DiscoverabilityAssociationPoint"}], "nullable": true}, "after": {"allOf": [{"$ref": "#/components/schemas/DiscoverabilityAssociationPoint"}], "nullable": true}, "incompatible_dimensions": {"type": "array", "items": {"type": "string", "enum": ["probe_set_version", "probe_set_hash", "provider", "model", "locale", "probe_key", "prompt_sha256"]}}, "limitations": {"type": "array", "items": {"type": "string"}}}
      },
      "DiscoverabilityObservationIdentity": {
        "type": "object",
        "additionalProperties": false,
        "required": ["probe_set_version", "probe_set_hash", "provider", "model", "locale", "probe_key", "prompt_sha256"],
        "properties": {"probe_set_version": {"type": "string"}, "probe_set_hash": {"type": "string", "pattern": "^[0-9a-f]{64}$"}, "provider": {"type": "string"}, "model": {"type": "string"}, "locale": {"type": "string"}, "probe_key": {"type": "string"}, "prompt_sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"}}
      },
      "DiscoverabilityAssociationPoint": {
        "type": "object",
        "additionalProperties": false,
        "required": ["observation_id", "batch_id", "observed_at", "probe_set_version", "probe_set_hash", "provider", "model", "locale", "probe_key", "prompt_sha256", "status", "position", "citation_url"],
        "properties": {"observation_id": {"type": "string", "format": "uuid"}, "batch_id": {"type": "string", "format": "uuid"}, "observed_at": {"type": "string", "format": "date-time"}, "probe_set_version": {"type": "string"}, "probe_set_hash": {"type": "string", "pattern": "^[0-9a-f]{64}$"}, "provider": {"type": "string"}, "model": {"type": "string"}, "locale": {"type": "string"}, "probe_key": {"type": "string"}, "prompt_sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"}, "status": {"type": "string", "enum": ["found", "not_found", "ambiguous", "error"]}, "position": {"type": "integer", "nullable": true}, "citation_url": {"type": "string", "format": "uri", "nullable": true}}
      },
      "OutcomeAssociationResult": {
        "type": "object",
        "required": ["analysis_version", "interpretation", "causal_claim", "window_days", "coverage", "methodology_version", "source_versions", "source_batch_ids", "metrics", "readiness", "browser_evidence", "limitations"],
        "properties": {"analysis_version": {"type": "string", "enum": ["1"]}, "interpretation": {"type": "string", "enum": ["observed_association_only"]}, "causal_claim": {"type": "boolean", "enum": [false]}, "window_days": {"type": "integer", "enum": [28]}, "coverage": {"type": "object", "additionalProperties": {"type": "object", "required": ["before", "after"], "properties": {"before": {"type": "integer"}, "after": {"type": "integer"}}}}, "methodology_version": {"type": "string", "nullable": true}, "source_versions": {"type": "object", "additionalProperties": {"oneOf": [{"type": "string"}, {"type": "object", "properties": {"registry_version": {"type": "string", "nullable": true}, "classifier_version": {"type": "string", "nullable": true}}}]}}, "source_batch_ids": {"type": "object", "additionalProperties": {"type": "array", "items": {"type": "string", "format": "uuid"}}}, "metrics": {"type": "array", "items": {"type": "object"}}, "readiness": {"type": "object", "nullable": true, "description": "Exact before and after scan IDs, one methodology version, profile changes and checkpoint changes."}, "browser_evidence": {"type": "object", "required": ["status", "probe_versions", "evidence"], "properties": {"status": {"type": "string", "enum": ["compatible", "versioned_adjacent_only"]}, "probe_versions": {"type": "array", "items": {"type": "string"}}, "evidence": {"type": "array", "items": {"$ref": "#/components/schemas/OutcomeBrowserEvidence"}}}}, "limitations": {"type": "array", "items": {"type": "string"}}}
      },
      "OutcomeBrowserEvidence": {
        "type": "object",
        "required": ["outcome", "protocol_path", "probe_version", "experimental", "included_in_score"],
        "properties": {"outcome": {"type": "string"}, "protocol_path": {"type": "string"}, "probe_version": {"type": "string"}, "experimental": {"type": "boolean", "enum": [true]}, "included_in_score": {"type": "boolean", "enum": [false]}}
      },
      "OutcomeScanEvidence": {
        "type": "object",
        "required": ["id", "completed_at", "methodology_version", "profile_results", "label", "browser_tasks"],
        "properties": {"id": {"type": "string", "format": "uuid"}, "completed_at": {"type": "string", "format": "date-time"}, "methodology_version": {"type": "string"}, "profile_results": {"type": "object"}, "overall_score": {"type": "integer", "nullable": true}, "letter_grade": {"type": "string", "nullable": true}, "label": {"type": "string", "enum": ["observation"]}, "browser_tasks": {"type": "array", "items": {"$ref": "#/components/schemas/OutcomeBrowserEvidence"}}}
      },
      "OutcomeMonitoringObservation": {
        "type": "object",
        "required": ["id", "scheduled_for", "status", "methodology_changed", "policy_id", "label"],
        "properties": {"id": {"type": "string", "format": "uuid"}, "scheduled_for": {"type": "string", "format": "date-time"}, "status": {"type": "string"}, "conclusion": {"type": "string", "nullable": true}, "methodology_changed": {"type": "boolean"}, "policy_id": {"type": "string", "format": "uuid"}, "label": {"type": "string", "enum": ["observation"]}}
      },
      "OutcomeInterventionInput": {
        "type": "object",
        "required": ["request_id", "occurred_at", "kind", "title"],
        "properties": {"request_id": {"type": "string", "format": "uuid"}, "occurred_at": {"type": "string", "format": "date-time"}, "kind": {"type": "string", "enum": ["readiness_change", "content_change", "infrastructure_change", "measurement_change", "other"]}, "title": {"type": "string", "maxLength": 120}, "related_scan_id": {"type": "string", "format": "uuid", "nullable": true}}
      },
      "BenchmarkSnapshot": {
        "type": "object",
        "description": "Immutable aggregate snapshot with sampling limitations, denominators, attrition, methodology and analysis versions. Browser evidence is experimental and non-scored.",
        "required": ["schema_version", "cohort_version", "report_version", "methodology_version", "profile", "analysis_version", "denominators", "attrition", "limitations"],
        "additionalProperties": true
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "instance": {
            "type": "string"
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Scans",
      "description": "Trigger scans and retrieve results"
    },
    {
      "name": "Rankings",
      "description": "Browse AI readiness rankings"
    },
    {
      "name": "MCP",
      "description": "Model Context Protocol server endpoint"
    },
    {
      "name": "Monitoring",
      "description": "Manage verified readiness monitoring and regression notifications"
    },
    {
      "name": "Outcomes",
      "description": "Manage private owner-uploaded aggregate outcome evidence without causal claims"
    },
    {
      "name": "Benchmarks",
      "description": "Read immutable aggregate research snapshots for a fixed submitted-site cohort"
    }
  ]
}
