{
  "openapi": "3.1.0",
  "info": {
    "title": "Sector Pulse Sector API",
    "version": "1.1.0",
    "description": "Live sector ranks, versioned basket rosters, and the daily sector rotation record for 30 US equity sector baskets. Derived aggregates only. The same data is available to agents over MCP at /api/mcp (get_sectors is free; get_roster and get_history need a key).",
    "contact": {
      "email": "support@apexinfrallc.com"
    }
  },
  "servers": [
    {
      "url": "https://sector-pulse.app"
    },
    {
      "url": "https://sector-pulse-omega.vercel.app",
      "description": "legacy host, kept for existing integrations"
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "SPK-\u2026 key. Founding tier or prepaid call packs ($10 = 2,000 calls): https://sector-pulse.app/pricing"
      }
    },
    "schemas": {
      "Breadth": {
        "type": "object",
        "properties": {
          "up": {
            "type": "integer"
          },
          "down": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          }
        }
      },
      "SectorState": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "pct": {
            "type": "number",
            "description": "Basket average % move, session-aware"
          },
          "median": {
            "type": "number"
          },
          "breadth": {
            "$ref": "#/components/schemas/Breadth"
          },
          "rank": {
            "type": "integer",
            "description": "1 = strongest, session basis (re-bases at 16:00 ET)"
          },
          "closeRank": {
            "type": "integer",
            "nullable": true,
            "description": "Regular-session basis, stable through 16:00"
          },
          "prevCloseRank": {
            "type": "integer",
            "nullable": true
          },
          "green": {
            "type": "boolean"
          },
          "session": {
            "type": "string",
            "enum": [
              "pre",
              "regular",
              "post"
            ]
          }
        }
      }
    }
  },
  "security": [
    {
      "ApiKey": []
    }
  ],
  "paths": {
    "/api/v1/sectors": {
      "get": {
        "summary": "Live sector board",
        "description": "All 30 baskets with session-aware aggregates and three rank bases. Rate limit 10 requests/min per key.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "asOf": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "basis": {
                      "type": "string",
                      "enum": [
                        "live"
                      ]
                    },
                    "sectors": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SectorState"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid or missing api key"
          },
          "429": {
            "description": "rate limit exceeded (10/min)"
          },
          "402": {
            "description": "out of credits (pay-as-you-go keys); body carries a topup link"
          }
        }
      }
    },
    "/api/v1/roster": {
      "get": {
        "summary": "Versioned basket roster",
        "description": "Ticker lists per basket. Versions are immutable; omit version for the current one.",
        "parameters": [
          {
            "name": "version",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "version": {
                      "type": "integer"
                    },
                    "currentVersion": {
                      "type": "integer"
                    },
                    "asOf": {
                      "type": "string"
                    },
                    "baskets": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "tickers": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "aliases": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "unknown version"
          },
          "402": {
            "description": "out of credits (pay-as-you-go keys); body carries a topup link"
          }
        }
      }
    },
    "/api/v1/history": {
      "get": {
        "summary": "Sector history for a date",
        "description": "Daily close record (from 2026-07-21; close ranks only before 2026-07-31) or 5-minute intraday rows (from 2026-08-19, never backfilled).",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "YYYY-MM-DD, ET trading day"
          },
          {
            "name": "intraday",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "date required"
          },
          "404": {
            "description": "no record for that date"
          },
          "402": {
            "description": "out of credits (pay-as-you-go keys); body carries a topup link"
          }
        }
      }
    }
  }
}
