{
  "openapi": "3.1.0",
  "info": {
    "title": "WorldScore API",
    "version": "1.0.0",
    "description": "Read-only access to sourced 0–100 country scores. Every score is returned with full provenance — source, license, dates, confidence tier, and the normalization method + parameters. Missing values are omitted (never fabricated).",
    "license": {
      "name": "Mixed — per source; see each observation's provenance.source.license",
      "url": "https://worldscore-pearl.vercel.app/methodology"
    }
  },
  "servers": [
    {
      "url": "https://worldscore-pearl.vercel.app",
      "description": "This deployment"
    }
  ],
  "security": [],
  "tags": [
    {
      "name": "countries",
      "description": "Country list and per-country scores"
    },
    {
      "name": "metrics",
      "description": "Metric catalog and rankings"
    },
    {
      "name": "compare",
      "description": "Side-by-side comparison"
    }
  ],
  "paths": {
    "/api/v1/countries": {
      "get": {
        "tags": [
          "countries"
        ],
        "summary": "List all countries (ISO 3166-1 alpha-3).",
        "operationId": "listCountries",
        "responses": {
          "200": {
            "description": "Country list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "apiVersion": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "countries": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Country"
                      }
                    }
                  }
                }
              }
            }
          },
          "4XX": {
            "$ref": "#/components/responses/ClientError"
          }
        }
      }
    },
    "/api/v1/countries/{iso3}": {
      "get": {
        "tags": [
          "countries"
        ],
        "summary": "All metric scores for one country, each with provenance.",
        "operationId": "getCountry",
        "parameters": [
          {
            "name": "iso3",
            "in": "path",
            "required": true,
            "description": "ISO 3166-1 alpha-3 code (case-insensitive), e.g. ESP.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{3}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Country with its scores",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "apiVersion": {
                      "type": "string"
                    },
                    "country": {
                      "$ref": "#/components/schemas/Country"
                    },
                    "scoreCount": {
                      "type": "integer"
                    },
                    "scores": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Score"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/metrics": {
      "get": {
        "tags": [
          "metrics"
        ],
        "summary": "Metric catalog, including tier, direction, scale meaning, and methodology.",
        "operationId": "listMetrics",
        "responses": {
          "200": {
            "description": "Metric catalog",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "apiVersion": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "metrics": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Metric"
                      }
                    }
                  }
                }
              }
            }
          },
          "4XX": {
            "$ref": "#/components/responses/ClientError"
          }
        }
      }
    },
    "/api/v1/metrics/{slug}/ranking": {
      "get": {
        "tags": [
          "metrics"
        ],
        "summary": "Full country ranking for a metric (best first), each row with provenance.",
        "description": "Use the virtual slug `crime` with `?crimeType=` to select a crime metric by type. Types with no reliable source return an empty ranking and `sourced:false` — never fabricated data.",
        "operationId": "getMetricRanking",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Metric slug, or `crime` for the crime family.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "crimeType",
            "in": "query",
            "required": false,
            "description": "Only for slug=crime. One of: homicide, assault, robbery, theft, kidnapping, sexual-violence, drug-offenses, cybercrime, corruption-offenses.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ranking",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "apiVersion": {
                      "type": "string"
                    },
                    "metric": {
                      "$ref": "#/components/schemas/Metric"
                    },
                    "coverage": {
                      "type": "object",
                      "properties": {
                        "withData": {
                          "type": "integer"
                        },
                        "totalCountries": {
                          "type": "integer"
                        }
                      }
                    },
                    "count": {
                      "type": "integer"
                    },
                    "ranking": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Score"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/compare": {
      "get": {
        "tags": [
          "compare"
        ],
        "summary": "Compare 2+ countries across metrics; cells carry provenance.",
        "operationId": "compare",
        "parameters": [
          {
            "name": "countries",
            "in": "query",
            "required": true,
            "description": "Comma-separated ISO3 codes, e.g. ESP,PRT,FRA (min 2).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "metrics",
            "in": "query",
            "required": false,
            "description": "Comma-separated metric slugs. Omit for the full catalog.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Comparison payload",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    }
  },
  "components": {
    "responses": {
      "ClientError": {
        "description": "Client error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "BadRequest": {
        "description": "Invalid parameters",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "status": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "Country": {
        "type": "object",
        "properties": {
          "iso3": {
            "type": "string"
          },
          "iso2": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "officialName": {
            "type": [
              "string",
              "null"
            ]
          },
          "region": {
            "type": [
              "string",
              "null"
            ]
          },
          "subregion": {
            "type": [
              "string",
              "null"
            ]
          },
          "unMember": {
            "type": "boolean"
          },
          "independent": {
            "type": "boolean"
          },
          "centroid": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "lat": {
                "type": "number"
              },
              "lng": {
                "type": "number"
              }
            }
          }
        }
      },
      "Metric": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "unit": {
            "type": [
              "string",
              "null"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "higher_better",
              "higher_worse"
            ]
          },
          "scaleMeaning": {
            "type": "string"
          },
          "confidenceTier": {
            "type": "string",
            "enum": [
              "A",
              "B",
              "C",
              "D"
            ]
          },
          "isPredictive": {
            "type": "boolean"
          },
          "methodology": {
            "type": "string"
          }
        }
      },
      "Source": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "license": {
            "type": "string"
          },
          "publisher": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          }
        }
      },
      "Score": {
        "type": "object",
        "description": "A scored observation with full provenance (no bare numbers).",
        "properties": {
          "metricId": {
            "type": "string"
          },
          "metricName": {
            "type": "string"
          },
          "iso3": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "raw": {
            "type": "object",
            "properties": {
              "value": {
                "type": "number"
              },
              "unit": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "rank": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          },
          "scaleMeaning": {
            "type": "string"
          },
          "direction": {
            "type": "string"
          },
          "confidenceTier": {
            "type": "string",
            "enum": [
              "A",
              "B",
              "C",
              "D"
            ]
          },
          "isEstimate": {
            "type": "boolean"
          },
          "provenance": {
            "type": "object",
            "properties": {
              "source": {
                "$ref": "#/components/schemas/Source"
              },
              "sourceYear": {
                "type": "integer"
              },
              "sourcePubDate": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "retrievedAt": {
                "type": "string"
              },
              "normalization": {
                "type": "object",
                "properties": {
                  "method": {
                    "type": "string"
                  },
                  "params": {
                    "type": "object"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}