{"openapi":"3.1.0","info":{"title":"SearchSeal API","version":"1.0.0","description":"Provider-independent AI-crawler observability. Every number is observed evidence: unknown is never presented as zero, an unobserved response is never presented as a status code, and totals equal the dashboard's totals for the same window and purpose filter."},"servers":[{"url":"https://api.searchseal.com"}],"security":[{"apiKey":[]}],"paths":{"/v1/sites":{"get":{"operationId":"listSites","summary":"Sites this API key can read","responses":{"200":{"description":"Site memberships.","content":{"application/json":{"schema":{"type":"object","required":["sites"],"properties":{"sites":{"type":"array","items":{"type":"object","required":["id","root_domain","role"],"properties":{"id":{"type":"string","format":"uuid","description":"Immutable site identifier — usable anywhere {site} appears in a path. Domains are mutable data."},"root_domain":{"type":"string"},"role":{"type":"string","enum":["owner","viewer"]}}}}}}}}},"401":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Allow":{"schema":{"type":"string"},"description":"Methods supported by this resource."}}},"500":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sites/{site}/performance":{"get":{"operationId":"getPerformance","summary":"Totals, flat daily rows, and HTTP outcomes","parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"Site id (uuid, immutable — preferred) or root domain, e.g. dino.markets."},{"name":"window","in":"query","schema":{"type":"string","enum":["3d","7d","30d","90d","180d","365d"],"default":"30d"},"description":"UTC day window ending today."},{"name":"purpose","in":"query","style":"form","explode":false,"schema":{"type":"array","items":{"type":"string","enum":["search","assistant","training","unknown"]},"default":["search","assistant","unknown"]},"description":"Crawler purposes to include, comma-separated. Default search,assistant,unknown — training is opt-in, undeclared purpose is included, invalid values are a 400 (never silently corrected)."}],"responses":{"200":{"description":"Windowed performance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Performance"}}}},"400":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Allow":{"schema":{"type":"string"},"description":"Methods supported by this resource."}}},"500":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sites/{site}/crawlers":{"get":{"operationId":"getCrawlers","summary":"Per-crawler totals and shares","parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"Site id (uuid, immutable — preferred) or root domain, e.g. dino.markets."},{"name":"window","in":"query","schema":{"type":"string","enum":["3d","7d","30d","90d","180d","365d"],"default":"30d"},"description":"UTC day window ending today."},{"name":"purpose","in":"query","style":"form","explode":false,"schema":{"type":"array","items":{"type":"string","enum":["search","assistant","training","unknown"]},"default":["search","assistant","unknown"]},"description":"Crawler purposes to include, comma-separated. Default search,assistant,unknown — training is opt-in, undeclared purpose is included, invalid values are a 400 (never silently corrected)."}],"responses":{"200":{"description":"Per-crawler totals.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Crawlers"}}}},"400":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Allow":{"schema":{"type":"string"},"description":"Methods supported by this resource."}}},"500":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sites/{site}/top-pages":{"get":{"operationId":"getTopPages","summary":"Ranked pages (capped, truncation explicit)","parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"Site id (uuid, immutable — preferred) or root domain, e.g. dino.markets."},{"name":"window","in":"query","schema":{"type":"string","enum":["3d","7d","30d","90d","180d","365d"],"default":"30d"},"description":"UTC day window ending today."},{"name":"purpose","in":"query","style":"form","explode":false,"schema":{"type":"array","items":{"type":"string","enum":["search","assistant","training","unknown"]},"default":["search","assistant","unknown"]},"description":"Crawler purposes to include, comma-separated. Default search,assistant,unknown — training is opt-in, undeclared purpose is included, invalid values are a 400 (never silently corrected)."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":50}}],"responses":{"200":{"description":"Ranked pages.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopPages"}}}},"400":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Allow":{"schema":{"type":"string"},"description":"Methods supported by this resource."}}},"500":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sites/{site}/issues":{"get":{"operationId":"getIssues","summary":"Open issues (observed harm only)","parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"Site id (uuid, immutable — preferred) or root domain, e.g. dino.markets."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":8}}],"responses":{"200":{"description":"Open issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Issues"}}}},"400":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Allow":{"schema":{"type":"string"},"description":"Methods supported by this resource."}}},"500":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sites/{site}/sources":{"get":{"operationId":"getSources","summary":"Connected evidence sources","parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"Site id (uuid, immutable — preferred) or root domain, e.g. dino.markets."}],"responses":{"200":{"description":"Evidence sources.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sources"}}}},"400":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Allow":{"schema":{"type":"string"},"description":"Methods supported by this resource."}}},"500":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/sites/{site}/access-checks":{"post":{"operationId":"runAccessCheck","summary":"Live policy check for one URL (current state only)","parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"Site id (uuid, immutable — preferred) or root domain, e.g. dino.markets."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","pattern":"^[Hh][Tt][Tt][Pp][Ss]?://","description":"HTTP or HTTPS URL on this site."}}}}}},"responses":{"200":{"description":"Current policy evidence.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessCheck"}}}},"400":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Allow":{"schema":{"type":"string"},"description":"Methods supported by this resource."}}},"422":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Error (RFC 9457).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"ssk_read_ API key from the dashboard. It grants reads plus owner-gated fix verification."}},"schemas":{"Problem":{"type":"object","required":["title","status"],"properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"}}},"Meta":{"type":"object","required":["as_of","window","coverage_state","purpose_filter","registry_version","sources","data_through","gaps"],"properties":{"as_of":{"type":"string","format":"date-time","description":"Instant this response was computed. Surfaces queried seconds apart can differ by live ingestion; compare as_of before comparing totals."},"coverage_state":{"type":"string","enum":["complete","partial","unknown"],"description":"THE truth signal — read this before any count. unknown: no primary source has ever reported; every count in this response is null, never zero. partial: coverage exists but is impaired in this window (gap days, backfilled days, a partial or sampled source). complete: full coverage."},"registry_version":{"type":["string","null"],"description":"Crawler-registry version that labeled purposes/identities in this response. A registry change re-labels history."},"window":{"type":"object","required":["from","to","timezone"],"properties":{"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date"},"timezone":{"type":"string","const":"UTC"}}},"purpose_filter":{"type":"array","items":{"type":"string","enum":["search","assistant","training","unknown"]},"description":"The effective (expanded) purpose filter this response was computed with."},"sources":{"type":"array","items":{"$ref":"#/components/schemas/Source"}},"data_through":{"type":["string","null"],"format":"date-time","description":"Freshest instant every primary source has reported through; null when unknown (never zero)."},"gaps":{"type":"array","items":{"type":"object","required":["from","to"],"properties":{"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date"}}},"description":"In-window day ranges where no primary source reported coverage — unknown, never zero traffic. Only meaningful when primary sources exist: with sources empty (data_through null) the ENTIRE window is unknown and gaps is empty — check sources/data_through before trusting any zero."}}},"Source":{"type":"object","required":["id","source_type","connection_status","is_primary","connected_at","data_through","evidence_from","backfill","hostname_coverage","completeness","sampling","http_status_fidelity"],"properties":{"id":{"type":"string","format":"uuid"},"source_type":{"type":"string","enum":["cloudflare_zone","https_intake","log_upload"]},"connection_status":{"type":"string","enum":["pending","live","error","revoked","disconnected"]},"is_primary":{"type":"boolean","description":"Only primary sources count toward totals (overlap never double-counts)."},"connected_at":{"type":["string","null"],"format":"date-time"},"data_through":{"type":["string","null"],"format":"date-time"},"evidence_from":{"type":["string","null"],"format":"date","description":"Earliest evidence day this source holds; null when none yet."},"backfill":{"oneOf":[{"type":"object","required":["from","to"],"properties":{"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date"}}},{"type":"null"}],"description":"Inclusive day range of provider backfill: evidence imported at connect time that PRECEDES the connection day, labeled from the actual evidence interval. History observed by SearchSeal starts at connected_at; backfilled days are the provider's history, not ours."},"hostname_coverage":{"type":"object","description":"Hostnames this source can and cannot see (source-declared).","properties":{"proxied":{"type":"array","items":{"type":"string"}},"unproxied":{"type":"array","items":{"type":"string"}},"checked_at":{"type":"string","format":"date-time"}}},"completeness":{"type":["string","null"],"enum":["complete","partial","unknown",null]},"sampling":{"type":["number","null"],"minimum":0,"maximum":1},"http_status_fidelity":{"type":["string","null"],"enum":["exact","grouped","unavailable",null]}}},"DailyRow":{"type":"object","required":["date","crawler_id","observed_request_count"],"properties":{"date":{"type":"string","format":"date"},"crawler_id":{"type":"string"},"observed_request_count":{"type":"integer","minimum":0}}},"Outcome":{"description":"Discriminated on `outcome`: a null http_status is STRUCTURALLY impossible under an observed class — only response_unobserved carries it.","oneOf":[{"type":"object","required":["outcome","observed_request_count","statuses"],"properties":{"outcome":{"type":"string","enum":["2xx","3xx","4xx","5xx","other"]},"observed_request_count":{"type":"integer","minimum":0},"statuses":{"type":"array","items":{"type":"object","required":["http_status","observed_request_count"],"properties":{"http_status":{"type":"integer","minimum":100},"observed_request_count":{"type":"integer","minimum":0}}}}}},{"type":"object","required":["outcome","observed_request_count","statuses"],"properties":{"outcome":{"type":"string","const":"response_unobserved","description":"The source saw the request but never the response — never folded into 2xx."},"observed_request_count":{"type":"integer","minimum":0},"statuses":{"type":"array","items":{"type":"object","required":["http_status","observed_request_count"],"properties":{"http_status":{"type":"null"},"observed_request_count":{"type":"integer","minimum":0}}}}}}]},"Crawler":{"type":"object","required":["crawler_id","platform","display_name","purpose","identity","observed_request_count","observed_share"],"properties":{"crawler_id":{"type":"string"},"platform":{"type":["string","null"]},"display_name":{"type":["string","null"]},"purpose":{"type":"string","enum":["search","assistant","training","unknown"],"description":"Vendor-declared via the registry; unknown when undeclared, never guessed."},"identity":{"type":"string","enum":["ua_identified","provider_verified","network_verified","unknown"],"description":"Aggregation never upgrades identity: mixed rows collapse to the weakest present."},"observed_request_count":{"type":"integer","minimum":0},"observed_share":{"type":"number","minimum":0,"maximum":1}}},"Page":{"type":"object","required":["host","path","observed_request_count","observed_share","observed_crawler_count","observed_response_count"],"properties":{"host":{"type":"string"},"path":{"type":"string"},"observed_request_count":{"type":"integer","minimum":0},"observed_share":{"type":"number","minimum":0,"maximum":1},"observed_crawler_count":{"type":"integer","minimum":0},"observed_response_count":{"type":"integer","minimum":0,"description":"Of the observed requests, how many had an HTTP response observed (request-only feeds see the request, never the response)."}}},"Performance":{"type":"object","required":["meta","observed_request_count","daily","http_outcomes"],"properties":{"meta":{"$ref":"#/components/schemas/Meta"},"observed_request_count":{"type":["integer","null"],"minimum":0,"description":"Observed evidence in the window under the effective purpose filter — never claimed total crawler traffic. null when meta.coverage_state is unknown (unknown never reads as zero)."},"daily":{"type":"array","items":{"$ref":"#/components/schemas/DailyRow"}},"http_outcomes":{"type":"array","items":{"$ref":"#/components/schemas/Outcome"}}}},"Crawlers":{"type":"object","required":["meta","crawlers"],"properties":{"meta":{"$ref":"#/components/schemas/Meta"},"crawlers":{"type":"array","items":{"$ref":"#/components/schemas/Crawler"}}}},"TopPages":{"type":"object","required":["meta","limit","returned_count","total_count","truncated","pages"],"properties":{"meta":{"$ref":"#/components/schemas/Meta"},"limit":{"type":"integer"},"returned_count":{"type":"integer"},"total_count":{"type":["integer","null"],"minimum":0,"description":"Uncapped distinct-page count — a capped ranking always names the real total. null when meta.coverage_state is unknown."},"truncated":{"type":"boolean"},"pages":{"type":"array","items":{"$ref":"#/components/schemas/Page"}}}},"Issues":{"type":"object","required":["limit","returned_count","total_count","truncated","issues"],"properties":{"limit":{"type":"integer","minimum":1,"maximum":50},"returned_count":{"type":"integer","minimum":0},"total_count":{"type":"integer","minimum":0},"truncated":{"type":"boolean"},"issues":{"type":"array","items":{"type":"object","required":["id","title","state","cause","confidence","description","path","crawler_id","detected_at","fix_confirmed_at","evidence_refs","fix_prompt"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string","description":"States the observation (\"received HTTP 405\"), never a conclusion."},"state":{"type":"string","enum":["open","fix_detected","regressed"],"description":"fix_detected means SearchSeal's own inspection came back clean. Fresh observed harm can move it to regressed."},"cause":{"type":"string","enum":["robots_rule","http_status","waf_or_challenge","redirect_chain","dns","tls","origin_error","unknown"],"description":"unknown is legal; an evidence-free assessment is not."},"confidence":{"type":"string","enum":["high","medium","low"]},"description":{"type":"string"},"path":{"type":["string","null"]},"crawler_id":{"type":["string","null"]},"detected_at":{"type":"string","format":"date-time"},"fix_confirmed_at":{"type":["string","null"],"format":"date-time","description":"Set only by subsequent organic evidence succeeding (layer 2) — never by our own inspection."},"evidence_refs":{"type":"array","minItems":1,"description":"Evidence-free assessments are illegal (DB-enforced non-empty).","items":{"oneOf":[{"type":"object","required":["kind","host","path_key","status","count","window"],"properties":{"kind":{"type":"string","const":"rollup_daily"},"host":{"type":"string"},"path_key":{"type":"string"},"status":{"type":"integer"},"count":{"type":"integer","minimum":1},"window":{"type":"string"}}},{"type":"object","required":["kind","id"],"properties":{"kind":{"type":"string","const":"inspection"},"id":{"type":"string","format":"uuid"}}}]}},"fix_prompt":{"type":["string","null"]}}}}}},"Sources":{"type":"object","required":["sources"],"properties":{"sources":{"type":"array","items":{"$ref":"#/components/schemas/Source"}}}},"AccessCheck":{"type":"object","required":["evidence_type","url","checked_at","http_probe","robots"],"properties":{"evidence_type":{"type":"string","const":"current_policy_check"},"url":{"type":"string","format":"uri"},"checked_at":{"type":"string","format":"date-time"},"http_probe":{"type":"object","required":["requested_url","final_url","http_status","error","redirect_count"],"properties":{"requested_url":{"type":"string","format":"uri"},"final_url":{"type":"string","format":"uri"},"http_status":{"type":["integer","null"]},"error":{"type":["string","null"]},"redirect_count":{"type":"integer"}}},"robots":{"type":"object","required":["fetched","crawlers"],"properties":{"fetched":{"type":"boolean"},"crawlers":{"type":"array","items":{"type":"object","required":["crawler_id","token","decision","matched_rule"],"properties":{"crawler_id":{"type":"string"},"token":{"type":"string"},"decision":{"type":"string","enum":["allowed","disallowed","unknown"],"description":"unknown = robots.txt unreachable — never presented as allowed."},"matched_rule":{"type":["string","null"]}}}}}}}}}}}