{
  "openapi": "3.0.3",
  "info": {
    "title": "Wolf.Solar Explorer API",
    "version": "1.0.0",
    "description": "Read-only access to the solar observations published by the Wolf.Solar community: daily activity aggregates, observations, images and observers. All timestamps are UTC. Data © the Wolf.Solar community observers — attribution required."
  },
  "servers": [{ "url": "https://explorer.wolf.solar/api/v1" }],
  "security": [{ "bearerAuth": [] }],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Tokens are issued manually — see https://explorer.wolf.solar/en/api"
      }
    },
    "parameters": {
      "from": { "name": "from", "in": "query", "schema": { "type": "string", "format": "date" } },
      "to": { "name": "to", "in": "query", "schema": { "type": "string", "format": "date" } },
      "cursor": { "name": "cursor", "in": "query", "schema": { "type": "string" }, "description": "Opaque cursor from a previous response's next_cursor" },
      "limit": { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 500, "default": 100 } }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": { "code": { "type": "string" }, "message": { "type": "string" } }
          }
        }
      },
      "DailyActivity": {
        "type": "object",
        "properties": {
          "day": { "type": "string", "format": "date" },
          "carrington_rotation": { "type": "integer" },
          "obs_count": { "type": "integer" },
          "observer_count": { "type": "integer" },
          "wolf_mean": { "type": "number", "nullable": true },
          "wolf_min": { "type": "integer", "nullable": true },
          "wolf_max": { "type": "integer", "nullable": true },
          "a_mean": { "type": "number", "nullable": true },
          "a_min": { "type": "integer", "nullable": true },
          "a_max": { "type": "integer", "nullable": true },
          "wolf_north_mean": { "type": "number", "nullable": true },
          "wolf_south_mean": { "type": "number", "nullable": true },
          "image_count": { "type": "integer" }
        }
      },
      "Observation": {
        "type": "object",
        "description": "One published observation. Counts are nullable; wolf = 10×groups + spots; a_number is the naked-eye active-region count.",
        "properties": {
          "id": { "type": "string" },
          "observer": { "type": "string" },
          "type": { "type": "integer", "enum": [0, 1, 2], "description": "0 whitelight, 1 H-Alpha, 2 CaK" },
          "date_of_observation": { "type": "string" },
          "title": { "type": "string", "nullable": true },
          "gt": { "type": "integer", "nullable": true },
          "gn": { "type": "integer", "nullable": true },
          "gs": { "type": "integer", "nullable": true },
          "st": { "type": "integer", "nullable": true },
          "sn": { "type": "integer", "nullable": true },
          "ss": { "type": "integer", "nullable": true },
          "wolf": { "type": "integer", "nullable": true },
          "wolf_north": { "type": "integer", "nullable": true },
          "wolf_south": { "type": "integer", "nullable": true },
          "a_number": { "type": "integer", "nullable": true },
          "seeing": { "type": "integer", "nullable": true },
          "transparency": { "type": "integer", "nullable": true },
          "cloud_cover": { "type": "integer", "nullable": true },
          "comments": { "type": "string", "nullable": true }
        }
      },
      "Image": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "observer": { "type": "string" },
          "title": { "type": "string", "nullable": true },
          "date_of_observation": { "type": "string" },
          "cdn_id": { "type": "string" },
          "urls": { "type": "object", "additionalProperties": { "type": "string" } },
          "site_lat": { "type": "number", "nullable": true, "description": "Observing site, rounded to ~0.1°" },
          "site_lng": { "type": "number", "nullable": true },
          "mount": { "type": "string", "nullable": true, "enum": ["EQUATORIAL", "ALTAZ", null] }
        }
      },
      "Observer": {
        "type": "object",
        "properties": {
          "nickname": { "type": "string" },
          "observations": { "type": "integer" },
          "images": { "type": "integer" },
          "first_seen": { "type": "string", "nullable": true }
        }
      }
    },
    "responses": {
      "Unauthorized": { "description": "Missing or invalid token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "RateLimited": { "description": "Rate limit exceeded (Retry-After header set)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    }
  },
  "paths": {
    "/meta": {
      "get": {
        "summary": "Dataset boundaries and freshness",
        "responses": { "200": { "description": "OK" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "429": { "$ref": "#/components/responses/RateLimited" } }
      }
    },
    "/activity/daily": {
      "get": {
        "summary": "Daily community activity aggregates",
        "parameters": [
          { "$ref": "#/components/parameters/from" },
          { "$ref": "#/components/parameters/to" },
          { "$ref": "#/components/parameters/cursor" },
          { "$ref": "#/components/parameters/limit" }
        ],
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/DailyActivity" } }, "next_cursor": { "type": "string", "nullable": true } } } } } } }
      }
    },
    "/observations": {
      "get": {
        "summary": "Published observations",
        "parameters": [
          { "$ref": "#/components/parameters/from" },
          { "$ref": "#/components/parameters/to" },
          { "name": "type", "in": "query", "schema": { "type": "integer", "enum": [0, 1, 2] } },
          { "name": "observer", "in": "query", "schema": { "type": "string" } },
          { "name": "tag", "in": "query", "schema": { "type": "string" } },
          { "$ref": "#/components/parameters/cursor" },
          { "$ref": "#/components/parameters/limit" }
        ],
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Observation" } }, "next_cursor": { "type": "string", "nullable": true } } } } } } }
      }
    },
    "/observations/{id}": {
      "get": {
        "summary": "One published observation",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Observation" } } } }, "404": { "description": "Not found" } }
      }
    },
    "/images": {
      "get": {
        "summary": "Published image metadata",
        "parameters": [
          { "$ref": "#/components/parameters/from" },
          { "$ref": "#/components/parameters/to" },
          { "name": "observer", "in": "query", "schema": { "type": "string" } },
          { "name": "tag", "in": "query", "schema": { "type": "string" } },
          { "$ref": "#/components/parameters/cursor" },
          { "$ref": "#/components/parameters/limit" }
        ],
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Image" } }, "next_cursor": { "type": "string", "nullable": true } } } } } } }
      }
    },
    "/observers": {
      "get": {
        "summary": "Observers with publication counts",
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Observer" } } } } } } } }
      }
    },
    "/observers/{nickname}": {
      "get": {
        "summary": "One observer with summary stats",
        "parameters": [{ "name": "nickname", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "OK" }, "404": { "description": "Not found" } }
      }
    }
  }
}
