{"openapi":"3.1.1","info":{"title":"Angeloi compact agent API","version":"1.0.0","description":"Additive read-only API. Existing /nodes, /registry.json and evidence URLs remain supported. Decimal values are strings; null means unavailable. Read health before using data. No public request triggers source collection. Do not retry a 503 in a tight loop: node collection policies are in the linked definition; use bounded backoff for service errors. No API key required. Responses have no visitor identifiers."},"servers":[{"url":"https://angeloi.net"}],"paths":{"/api/v1/catalog":{"get":{"operationId":"listCatalog","summary":"Discover compact node metadata","parameters":[{"in":"query","name":"limit","description":"Maximum items per page (1–100)","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}},{"in":"query","name":"after","description":"Exclusive node ID in lexicographic order","required":false,"schema":{"type":"string"}},{"in":"query","name":"oracle","description":"Exact case-sensitive oracle filter; no match returns an empty list","required":false,"schema":{"type":"string"}},{"in":"query","name":"frequency","description":"Exact case-sensitive frequency filter; no match returns an empty list","required":false,"schema":{"type":"string"}},{"in":"query","name":"geography","description":"Exact case-sensitive geography filter; no match returns an empty list","required":false,"schema":{"type":"string"}},{"in":"query","name":"category","description":"Exact case-sensitive category filter; no match returns an empty list","required":false,"schema":{"type":"string"}},{"in":"header","name":"If-None-Match","schema":{"type":"string"},"required":false,"description":"ETag from a prior successful response; every request revalidates current state."}],"responses":{"200":{"description":"Current representation","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/catalog.json"}}}},"304":{"description":"Unchanged successful representation; no body"},"400":{"description":"Invalid parameter","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}},"404":{"description":"Unknown route or node","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}},"409":{"description":"Change cursor identity or retained range mismatch","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}},"503":{"description":"Storage or service failure","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}}}}},"/api/v1/nodes/{id}":{"get":{"operationId":"getNode","summary":"Read one compact observation","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"}},{"in":"header","name":"If-None-Match","schema":{"type":"string"},"required":false,"description":"ETag from a prior successful response; every request revalidates current state."}],"responses":{"200":{"description":"Current representation","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/node.json"}}}},"304":{"description":"Unchanged successful representation; no body"},"400":{"description":"Invalid parameter","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}},"404":{"description":"Unknown route or node","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}},"409":{"description":"Change cursor identity or retained range mismatch","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}},"503":{"description":"Degraded node (may retain verified data) or service failure; inspect body.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"https://angeloi.net/schemas/v1/node.json"},{"$ref":"https://angeloi.net/schemas/v1/error.json"}]}}}}}}},"/api/v1/changes":{"get":{"operationId":"listChanges","summary":"Read durable changes in ascending journal order","parameters":[{"in":"query","name":"limit","description":"Maximum items per page (1–100)","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}},{"in":"query","name":"cursor","description":"Opaque feed-id:sequence cursor. Omit for retained events since recording began; follow poll after catching up. high_watermark can establish a current baseline. Not a publisher release feed.","required":false,"schema":{"type":"string"}},{"in":"header","name":"If-None-Match","schema":{"type":"string"},"required":false,"description":"ETag from a prior successful response; every request revalidates current state."}],"responses":{"200":{"description":"Current representation","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/changes.json"}}}},"304":{"description":"Unchanged successful representation; no body"},"400":{"description":"Invalid parameter","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}},"404":{"description":"Unknown route or node","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}},"409":{"description":"Change cursor identity or retained range mismatch","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}},"503":{"description":"Storage or service failure","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}}}}},"/api/v1/alerts/history":{"get":{"operationId":"listAlertHistory","summary":"Read compact alert transitions with evidence links","parameters":[{"in":"query","name":"limit","description":"Maximum items per page (1–100)","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}},{"in":"query","name":"before","description":"Exclusive alert event ID in descending order","required":false,"schema":{"type":"integer","minimum":1}},{"in":"header","name":"If-None-Match","schema":{"type":"string"},"required":false,"description":"ETag from a prior successful response; every request revalidates current state."}],"responses":{"200":{"description":"Current representation","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/alerts.json"}}}},"304":{"description":"Unchanged successful representation; no body"},"400":{"description":"Invalid parameter","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}},"404":{"description":"Unknown route or node","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}},"409":{"description":"Change cursor identity or retained range mismatch","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}},"503":{"description":"Storage or service failure","content":{"application/json":{"schema":{"$ref":"https://angeloi.net/schemas/v1/error.json"}}}}}}}},"externalDocs":{"url":"https://angeloi.net/guide","description":"Interpretation, original-source attribution and permanent URLs"}}