{
  "openapi": "3.0.3",
  "info": {
    "title": "Voidly Atlas API",
    "version": "1.0.0",
    "description": "Real-time global censorship detection, prediction, and intelligence. The Hydra API provides machine-learning-powered censorship analysis using data from OONI, CensoredPlanet, IODA, and the Voidly Network across 126+ countries profiled in the Censorship Index.",
    "contact": {
      "name": "Voidly Research",
      "email": "research@voidly.ai",
      "url": "https://voidly.ai"
    },
    "license": {
      "name": "CC BY 4.0 (data endpoints)",
      "url": "https://creativecommons.org/licenses/by/4.0/"
    }
  },
  "servers": [
    {
      "url": "https://voidly.ai/api",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    { "name": "Detection", "description": "Real-time censorship detection and prediction" },
    { "name": "Intelligence", "description": "Threat levels, scores, and model metadata" },
    { "name": "Health", "description": "Service health" },
    { "name": "Public Data", "description": "Open censorship index data (no auth required, CC BY 4.0)" }
  ],
  "paths": {
    "/hydra/v1/detect": {
      "post": {
        "operationId": "detectCensorship",
        "summary": "Detect active censorship",
        "description": "Check whether a target domain is actively blocked in a given country. Optionally includes per-ISP breakdown for research/enterprise tiers.",
        "tags": ["Detection"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DetectRequest"
              },
              "example": {
                "country": "CN",
                "target": "google.com",
                "includeISPs": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Detection result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DetectResponse"
                },
                "example": {
                  "country": "CN",
                  "target": "google.com",
                  "blocked": true,
                  "confidence": 0.95,
                  "blockType": "dpi_block",
                  "lastChecked": "2025-01-15T12:00:00.000Z",
                  "sources": ["ooni", "sensor", "telemetry"],
                  "isps": [
                    { "asn": 4134, "name": "China Telecom", "blocked": true, "blockRate": 0.98 },
                    { "asn": 4837, "name": "China Unicom", "blocked": true, "blockRate": 0.97 },
                    { "asn": 9808, "name": "China Mobile", "blocked": true, "blockRate": 0.99 }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/hydra/v1/predict": {
      "post": {
        "operationId": "predictCensorship",
        "summary": "Predict censorship risk",
        "description": "Predict the likelihood and trend of censorship for a country over a given time horizon using the GradientBoosting classifier.",
        "tags": ["Detection"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PredictRequest"
              },
              "example": {
                "country": "RU",
                "target": "telegram.org",
                "horizon": 7
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Prediction result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PredictResponse"
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/hydra/v1/threat-level/{country}": {
      "get": {
        "operationId": "getThreatLevel",
        "summary": "Get country threat level",
        "description": "Returns the censorship threat level for a country, including score, trend, recommendations, and optional 30-day history.",
        "tags": ["Intelligence"],
        "parameters": [
          {
            "name": "country",
            "in": "path",
            "required": true,
            "description": "ISO 3166-1 alpha-2 country code",
            "schema": {
              "type": "string",
              "pattern": "^[A-Z]{2}$",
              "example": "CN"
            }
          },
          {
            "name": "includeHistory",
            "in": "query",
            "required": false,
            "description": "Include 30-day score history",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Threat level result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreatLevelResponse"
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/hydra/v1/scores": {
      "get": {
        "operationId": "getCensorshipScores",
        "summary": "Get all censorship scores",
        "description": "Returns censorship scores for all tracked countries, sorted by score descending. Supports filtering by minimum confidence and limiting results.",
        "tags": ["Intelligence"],
        "parameters": [
          {
            "name": "minConfidence",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "default": 0.5,
              "minimum": 0,
              "maximum": 1
            },
            "description": "Minimum confidence threshold"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1
            },
            "description": "Maximum number of results"
          }
        ],
        "responses": {
          "200": {
            "description": "Censorship scores",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScoresResponse"
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/hydra/v1/model/info": {
      "get": {
        "operationId": "getModelInfo",
        "summary": "Get ML model metadata",
        "description": "Returns information about the current production ML model, including accuracy metrics, feature importance, and training details.",
        "tags": ["Intelligence"],
        "responses": {
          "200": {
            "description": "Model information",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelInfoResponse"
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/hydra/v1/health": {
      "get": {
        "operationId": "healthCheck",
        "summary": "Health check",
        "description": "Returns service health status. No authentication required.",
        "tags": ["Health"],
        "security": [],
        "responses": {
          "200": {
            "description": "Service is healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          }
        }
      }
    },
    "/data/censorship-index.json": {
      "get": {
        "operationId": "getCensorshipIndex",
        "summary": "Global Censorship Index (JSON)",
        "description": "The canonical censorship index dataset with schema.org structured data. No authentication required. Licensed under CC BY 4.0.",
        "tags": ["Public Data"],
        "security": [],
        "responses": {
          "200": {
            "description": "Censorship index dataset",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CensorshipIndexResponse"
                }
              }
            }
          }
        }
      }
    },
    "/data/censorship-index.csv": {
      "get": {
        "operationId": "getCensorshipIndexCSV",
        "summary": "Global Censorship Index (CSV)",
        "description": "CSV export of the censorship index for researchers and spreadsheet users. No authentication required. Licensed under CC BY 4.0.",
        "tags": ["Public Data"],
        "security": [],
        "responses": {
          "200": {
            "description": "CSV file download",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "headers": {
              "Content-Disposition": {
                "schema": { "type": "string" },
                "example": "attachment; filename=\"voidly-censorship-index.csv\""
              }
            }
          }
        }
      }
    },
    "/data/country/{code}": {
      "get": {
        "operationId": "getCountryData",
        "summary": "Individual country censorship data",
        "description": "Returns detailed censorship data for a single country with schema.org structured data. No authentication required. Licensed under CC BY 4.0.",
        "tags": ["Public Data"],
        "security": [],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "ISO 3166-1 alpha-2 country code",
            "schema": {
              "type": "string",
              "pattern": "^[A-Z]{2}$",
              "example": "CN"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Country censorship data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CountryDataResponse"
                }
              }
            }
          },
          "404": {
            "description": "Country not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": { "type": "string" },
                    "code": { "type": "string" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/data/methodology": {
      "get": {
        "operationId": "getMethodology",
        "summary": "Index methodology",
        "description": "Machine-readable methodology for the Global Censorship Index, including data sources, model details, scoring interpretation, and citation format. No authentication required.",
        "tags": ["Public Data"],
        "security": [],
        "responses": {
          "200": {
            "description": "Methodology document",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MethodologyResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "API key for authenticated endpoints. Use `hydra_demo_key` for testing."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Bad request",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "BAD_REQUEST",
              "message": "country and target are required"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Invalid or missing API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "UNAUTHORIZED",
              "message": "Invalid or missing API key"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string" },
          "message": { "type": "string" }
        },
        "required": ["error", "message"]
      },
      "DetectRequest": {
        "type": "object",
        "required": ["country", "target"],
        "properties": {
          "country": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2 country code",
            "example": "CN"
          },
          "target": {
            "type": "string",
            "description": "Domain to check",
            "example": "google.com"
          },
          "includeISPs": {
            "type": "boolean",
            "description": "Include per-ISP breakdown (research/enterprise tiers only)",
            "default": false
          }
        }
      },
      "DetectResponse": {
        "type": "object",
        "properties": {
          "country": { "type": "string" },
          "target": { "type": "string" },
          "blocked": { "type": "boolean" },
          "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
          "blockType": {
            "type": "string",
            "enum": ["dpi_block", "dns_block", "ip_block", "none"]
          },
          "lastChecked": { "type": "string", "format": "date-time" },
          "sources": {
            "type": "array",
            "items": { "type": "string" }
          },
          "isps": {
            "type": "array",
            "description": "Per-ISP data (research/enterprise tiers only)",
            "items": {
              "$ref": "#/components/schemas/ISPData"
            }
          }
        },
        "required": ["country", "target", "blocked", "confidence", "blockType", "lastChecked", "sources"]
      },
      "ISPData": {
        "type": "object",
        "properties": {
          "asn": { "type": "integer" },
          "name": { "type": "string" },
          "blocked": { "type": "boolean" },
          "blockRate": { "type": "number", "minimum": 0, "maximum": 1 }
        }
      },
      "PredictRequest": {
        "type": "object",
        "required": ["country"],
        "properties": {
          "country": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2 country code"
          },
          "target": {
            "type": "string",
            "description": "Optional domain to predict risk for"
          },
          "horizon": {
            "type": "integer",
            "description": "Prediction horizon in days",
            "default": 7,
            "minimum": 1
          }
        }
      },
      "PredictResponse": {
        "type": "object",
        "properties": {
          "country": { "type": "string" },
          "target": { "type": "string", "nullable": true },
          "currentRisk": { "type": "number", "minimum": 0, "maximum": 1 },
          "predictedRisk": { "type": "number", "minimum": 0, "maximum": 1 },
          "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
          "trend": {
            "type": "string",
            "enum": ["increasing", "stable", "decreasing"]
          },
          "horizon": { "type": "integer" },
          "factors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "factor": { "type": "string" },
                "importance": { "type": "number" }
              }
            }
          },
          "modelVersion": { "type": "string" },
          "timestamp": { "type": "string", "format": "date-time" }
        },
        "required": ["country", "currentRisk", "predictedRisk", "confidence", "trend", "horizon", "factors", "modelVersion", "timestamp"]
      },
      "ThreatLevelResponse": {
        "type": "object",
        "properties": {
          "country": { "type": "string" },
          "threatLevel": {
            "type": "string",
            "enum": ["severe", "high", "medium", "low"]
          },
          "score": { "type": "number", "minimum": 0, "maximum": 1 },
          "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
          "recentBlocks": { "type": "integer" },
          "trend": {
            "type": "string",
            "enum": ["stable", "improving", "worsening"]
          },
          "recommendations": {
            "type": "array",
            "items": { "type": "string" }
          },
          "lastUpdated": { "type": "string", "format": "date-time" },
          "history": {
            "type": "array",
            "description": "30-day score history (only when includeHistory=true)",
            "items": {
              "type": "object",
              "properties": {
                "date": { "type": "string", "format": "date" },
                "score": { "type": "number" }
              }
            }
          }
        },
        "required": ["country", "threatLevel", "score", "confidence", "recentBlocks", "trend", "recommendations", "lastUpdated"]
      },
      "ScoresResponse": {
        "type": "object",
        "properties": {
          "scores": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "country": { "type": "string" },
                "score": { "type": "number" },
                "confidence": { "type": "number" },
                "samples": { "type": "integer" },
                "lastUpdated": { "type": "string", "format": "date-time" }
              }
            }
          },
          "totalCountries": { "type": "integer" },
          "modelVersion": { "type": "string" },
          "timestamp": { "type": "string", "format": "date-time" }
        },
        "required": ["scores", "totalCountries", "modelVersion", "timestamp"]
      },
      "ModelInfoResponse": {
        "type": "object",
        "properties": {
          "version": { "type": "string" },
          "type": { "type": "string" },
          "accuracy": { "type": "number" },
          "aucRoc": { "type": "number" },
          "features": { "type": "integer" },
          "featureImportance": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "feature": { "type": "string" },
                "importance": { "type": "number" }
              }
            }
          },
          "trainingSamples": { "type": "integer" },
          "dataSources": {
            "type": "object",
            "properties": {
              "ooni": { "type": "integer" },
              "telemetry": { "type": "integer" },
              "sensors": { "type": "integer" }
            }
          },
          "lastTraining": { "type": "string", "format": "date-time" },
          "nextTraining": { "type": "string" },
          "isProduction": { "type": "boolean" }
        },
        "required": ["version", "type", "accuracy", "aucRoc", "features", "featureImportance", "trainingSamples", "dataSources", "lastTraining", "isProduction"]
      },
      "HealthResponse": {
        "type": "object",
        "properties": {
          "status": { "type": "string", "enum": ["healthy"] },
          "service": { "type": "string" },
          "version": { "type": "string" },
          "nodes": { "type": "integer" },
          "modelVersion": { "type": "string" },
          "timestamp": { "type": "string", "format": "date-time" }
        }
      },
      "CensorshipIndexResponse": {
        "type": "object",
        "properties": {
          "@context": { "type": "string" },
          "@type": { "type": "string" },
          "name": { "type": "string" },
          "description": { "type": "string" },
          "url": { "type": "string" },
          "license": { "type": "string" },
          "dateModified": { "type": "string", "format": "date-time" },
          "version": { "type": "string" },
          "publisher": {
            "type": "object",
            "properties": {
              "@type": { "type": "string" },
              "name": { "type": "string" },
              "url": { "type": "string" }
            }
          },
          "metadata": {
            "type": "object",
            "properties": {
              "totalCountries": { "type": "integer" },
              "totalMeasurements": { "type": "integer" },
              "modelVersion": { "type": "string" },
              "modelAccuracy": { "type": "number" },
              "dataSources": { "type": "array", "items": { "type": "string" } },
              "updateFrequency": { "type": "string" },
              "lastUpdated": { "type": "string", "format": "date-time" }
            }
          },
          "summary": {
            "type": "object",
            "properties": {
              "severeCount": { "type": "integer" },
              "highCount": { "type": "integer" },
              "mediumCount": { "type": "integer" },
              "lowCount": { "type": "integer" },
              "freeCount": { "type": "integer" },
              "worseningCount": { "type": "integer" },
              "improvingCount": { "type": "integer" }
            }
          },
          "countries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CensorshipIndexEntry"
            }
          }
        }
      },
      "CensorshipIndexEntry": {
        "type": "object",
        "properties": {
          "rank": { "type": "integer" },
          "country": { "type": "string" },
          "code": { "type": "string" },
          "score": { "type": "integer", "minimum": 0, "maximum": 100 },
          "level": {
            "type": "string",
            "enum": ["severe", "high", "medium", "low", "free"]
          },
          "trend": {
            "type": "string",
            "enum": ["stable", "worsening", "improving"]
          },
          "samples": { "type": "integer" },
          "blocked": {
            "type": "array",
            "items": { "type": "string" }
          }
        }
      },
      "CountryDataResponse": {
        "type": "object",
        "properties": {
          "@context": { "type": "string" },
          "@type": { "type": "string" },
          "name": { "type": "string" },
          "identifier": { "type": "string" },
          "url": { "type": "string" },
          "additionalProperty": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "@type": { "type": "string" },
                "name": { "type": "string" },
                "value": {},
                "description": { "type": "string" }
              }
            }
          },
          "data": { "$ref": "#/components/schemas/CensorshipIndexEntry" },
          "source": { "type": "string" },
          "methodology": { "type": "string" },
          "lastUpdated": { "type": "string", "format": "date-time" }
        }
      },
      "MethodologyResponse": {
        "type": "object",
        "properties": {
          "@context": { "type": "string" },
          "@type": { "type": "string" },
          "name": { "type": "string" },
          "url": { "type": "string" },
          "datePublished": { "type": "string", "format": "date" },
          "dateModified": { "type": "string", "format": "date-time" },
          "author": {
            "type": "object",
            "properties": {
              "@type": { "type": "string" },
              "name": { "type": "string" }
            }
          },
          "methodology": {
            "type": "object",
            "description": "Full methodology details including data sources, model info, scoring, and limitations"
          },
          "citation": {
            "type": "object",
            "properties": {
              "format": { "type": "string" },
              "text": { "type": "string" }
            }
          },
          "license": { "type": "string" },
          "contact": { "type": "string" }
        }
      }
    }
  }
}