{
  "openapi": "3.0.1",
  "info": {
    "title": "BtcForecaster API",
    "description": "Free, read-only Bitcoin price range forecasts (1h, 4h, 24h) and their live track record, from BtcForecaster. No API key. Rate limit: 60 requests per minute per IP. Times are UTC (ISO 8601); percentages are plain numbers. Information only, not financial advice. Attribution appreciated: \"Data: BtcForecaster\".",
    "termsOfService": "https://btcforecaster.com/developers#terms",
    "contact": {
      "name": "BtcForecaster developers page",
      "url": "https://btcforecaster.com/developers"
    },
    "version": "v1"
  },
  "servers": [
    {
      "url": "https://btcforecaster.com"
    }
  ],
  "paths": {
    "/api/v1/forecast": {
      "get": {
        "tags": [
          "BtcForecaster API v1"
        ],
        "summary": "Latest forecast for every horizon",
        "description": "The 50% and 90% price ranges the site currently shows for 1, 4 and 24 hours ahead, with the reference price they're centred on, when each forecast was made and the model release. Updated every 5 minutes; cached for 60 seconds.",
        "operationId": "GetForecast",
        "parameters": [
          {
            "name": "horizon",
            "in": "query",
            "description": "Only this horizon: 1h, 4h or 24h. Omit for all three.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiForecastResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/forecasts": {
      "get": {
        "tags": [
          "BtcForecaster API v1"
        ],
        "summary": "Historical forecasts with their outcomes",
        "description": "Live forecasts made in [from, to), oldest first, each with its ranges and, once known, whether the price landed inside the 50% and 90% ranges. At most 7 days per request; paginated. Forecasts are made every 5 minutes for each horizon, so a day holds up to 288 per horizon.",
        "operationId": "GetForecastHistory",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "description": "Start (inclusive), UTC ISO 8601, e.g. 2026-11-10T00:00:00Z. Default: 24 hours before `to`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "End (exclusive), UTC ISO 8601. Default: now (the end of the current 5-minute slot).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "horizon",
            "in": "query",
            "description": "Only this horizon: 1h, 4h or 24h. Omit for all three.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "model",
            "in": "query",
            "description": "Model release: v1-baseline, v2-har or v3-har-cal90 (shadow). Default: the model the site shows.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number, from 1. Default 1.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "description": "Forecasts per page, 1–1000. Default 500.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiForecastPage"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/live-stats": {
      "get": {
        "tags": [
          "BtcForecaster API v1"
        ],
        "summary": "Live track record per model and horizon",
        "description": "The same content as /api/live-stats: hit rates of the 50% and 90% ranges with their 95% margins (using an effective sample size of n ÷ overlap), average width, interval score, misses above and below, and daily and rolling 7-day breakdowns. Live forecasts only. Refreshed about once a minute.",
        "operationId": "GetLiveStats",
        "parameters": [
          {
            "name": "model",
            "in": "query",
            "description": "Only this model release, e.g. v2-har or v1-baseline. Omit for all.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiLiveStats"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/status": {
      "get": {
        "tags": [
          "BtcForecaster API v1"
        ],
        "summary": "Service health",
        "description": "Whether prices and forecasts are up to date, when the data last changed and which price feed is in use (Binance, or the CoinGecko fallback). Always 200 while the service answers; read the status field.",
        "operationId": "GetStatus",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiStatus"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ApiError": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string"
          },
          "terms": {
            "type": "string"
          },
          "error": {
            "$ref": "#/components/schemas/ApiErrorBody"
          }
        },
        "additionalProperties": false
      },
      "ApiErrorBody": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "format": "int32"
          },
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "ApiForecast": {
        "type": "object",
        "properties": {
          "horizon": {
            "type": "string"
          },
          "horizonMinutes": {
            "type": "integer",
            "format": "int32"
          },
          "modelRelease": {
            "type": "string"
          },
          "forecastMadeUtc": {
            "type": "string",
            "format": "date-time"
          },
          "targetUtc": {
            "type": "string",
            "format": "date-time"
          },
          "referencePrice": {
            "type": "number",
            "format": "double"
          },
          "referenceTimeUtc": {
            "type": "string",
            "format": "date-time"
          },
          "range50": {
            "$ref": "#/components/schemas/ApiRange"
          },
          "range90": {
            "$ref": "#/components/schemas/ApiRange"
          },
          "priceSource": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "ApiForecastPage": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string"
          },
          "terms": {
            "type": "string"
          },
          "generatedUtc": {
            "type": "string",
            "format": "date-time"
          },
          "modelRelease": {
            "type": "string"
          },
          "fromUtc": {
            "type": "string",
            "format": "date-time"
          },
          "toUtc": {
            "type": "string",
            "format": "date-time"
          },
          "horizon": {
            "type": "string",
            "nullable": true
          },
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalCount": {
            "type": "integer",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32"
          },
          "nextPage": {
            "type": "string",
            "nullable": true
          },
          "note": {
            "type": "string"
          },
          "forecasts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiHistoricalForecast"
            }
          }
        },
        "additionalProperties": false
      },
      "ApiForecastResponse": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string"
          },
          "terms": {
            "type": "string"
          },
          "generatedUtc": {
            "type": "string",
            "format": "date-time"
          },
          "modelRelease": {
            "type": "string"
          },
          "modelName": {
            "type": "string"
          },
          "note": {
            "type": "string"
          },
          "forecasts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiForecast"
            }
          }
        },
        "additionalProperties": false
      },
      "ApiHistoricalForecast": {
        "type": "object",
        "properties": {
          "horizon": {
            "type": "string"
          },
          "horizonMinutes": {
            "type": "integer",
            "format": "int32"
          },
          "modelRelease": {
            "type": "string"
          },
          "forecastMadeUtc": {
            "type": "string",
            "format": "date-time"
          },
          "targetUtc": {
            "type": "string",
            "format": "date-time"
          },
          "referencePrice": {
            "type": "number",
            "format": "double"
          },
          "referenceTimeUtc": {
            "type": "string",
            "format": "date-time"
          },
          "range50": {
            "$ref": "#/components/schemas/ApiRange"
          },
          "range90": {
            "$ref": "#/components/schemas/ApiRange"
          },
          "priceSource": {
            "type": "string"
          },
          "outcome": {
            "$ref": "#/components/schemas/ApiOutcome"
          }
        },
        "additionalProperties": false
      },
      "ApiLiveStats": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string"
          },
          "terms": {
            "type": "string"
          },
          "modelRelease": {
            "type": "string"
          },
          "generatedUtc": {
            "type": "string",
            "format": "date-time"
          },
          "headlineModelRelease": {
            "type": "string"
          },
          "note": {
            "type": "string"
          },
          "models": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModelLiveStats"
            }
          },
          "priceSource": {
            "type": "string",
            "nullable": true
          },
          "fallbackPricePeriods": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SourcePeriod"
            },
            "nullable": true
          },
          "shadowReleases": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "ApiOutcome": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "actualPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "inside50": {
            "type": "boolean",
            "nullable": true
          },
          "inside90": {
            "type": "boolean",
            "nullable": true
          },
          "miss90": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "ApiRange": {
        "type": "object",
        "properties": {
          "low": {
            "type": "number",
            "format": "double"
          },
          "high": {
            "type": "number",
            "format": "double"
          },
          "lowPct": {
            "type": "number",
            "format": "double"
          },
          "highPct": {
            "type": "number",
            "format": "double"
          }
        },
        "additionalProperties": false
      },
      "ApiStatus": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string"
          },
          "terms": {
            "type": "string"
          },
          "generatedUtc": {
            "type": "string",
            "format": "date-time"
          },
          "apiVersion": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "modelRelease": {
            "type": "string"
          },
          "lastPriceUpdateUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "lastForecastUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "priceSource": {
            "type": "string",
            "nullable": true
          },
          "priceSourceIsFallback": {
            "type": "boolean"
          },
          "forecastsPaused": {
            "type": "boolean"
          },
          "forecastIntervalMinutes": {
            "type": "integer",
            "format": "int32"
          }
        },
        "additionalProperties": false
      },
      "DailyStats": {
        "type": "object",
        "properties": {
          "day": {
            "type": "string",
            "format": "date"
          },
          "samples": {
            "type": "integer",
            "format": "int32"
          },
          "hit90Pct": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "hit50Pct": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "HorizonLiveStats": {
        "type": "object",
        "properties": {
          "horizonMinutes": {
            "type": "integer",
            "format": "int32"
          },
          "horizonHours": {
            "type": "integer",
            "format": "int32"
          },
          "samples": {
            "type": "integer",
            "format": "int32"
          },
          "firstTargetUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "lastTargetUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "hit90Pct": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "hit50Pct": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "meanWidth90Pct": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "intervalScorePct": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "intervalScore90Pct": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "intervalScore50Pct": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "range90": {
            "$ref": "#/components/schemas/RangeCalibration"
          },
          "range50": {
            "$ref": "#/components/schemas/RangeCalibration"
          },
          "misses90Above": {
            "type": "integer",
            "format": "int32"
          },
          "misses90Below": {
            "type": "integer",
            "format": "int32"
          },
          "mapePct": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "daily": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DailyStats"
            }
          },
          "fallbackForecasts": {
            "type": "integer",
            "format": "int32"
          },
          "sourceMismatchExcluded": {
            "type": "integer",
            "format": "int32"
          },
          "fallbackPeriods": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SourcePeriod"
            },
            "nullable": true
          },
          "rolling7d": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RollingStats"
            },
            "nullable": true
          },
          "dailyNote": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "ModelLiveStats": {
        "type": "object",
        "properties": {
          "modelRelease": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "isHeadline": {
            "type": "boolean"
          },
          "liveSinceUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "liveDays": {
            "type": "number",
            "format": "double"
          },
          "horizons": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HorizonLiveStats"
            }
          }
        },
        "additionalProperties": false
      },
      "RangeCalibration": {
        "type": "object",
        "properties": {
          "targetPct": {
            "type": "number",
            "format": "double"
          },
          "samples": {
            "type": "integer",
            "format": "int32"
          },
          "hitRatePct": {
            "type": "number",
            "format": "double"
          },
          "margin95": {
            "type": "number",
            "format": "double"
          },
          "meanWidthPct": {
            "type": "number",
            "format": "double"
          },
          "isCalibrated": {
            "type": "boolean",
            "readOnly": true
          },
          "tooNarrow": {
            "type": "boolean",
            "readOnly": true
          }
        },
        "additionalProperties": false
      },
      "RollingStats": {
        "type": "object",
        "properties": {
          "day": {
            "type": "string",
            "format": "date"
          },
          "samples": {
            "type": "integer",
            "format": "int32"
          },
          "effectiveSamples": {
            "type": "number",
            "format": "double"
          },
          "hit90Pct": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "margin90": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "hit50Pct": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "margin50": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "fullWindow": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "SourcePeriod": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string"
          },
          "startUtc": {
            "type": "string",
            "format": "date-time"
          },
          "endUtc": {
            "type": "string",
            "format": "date-time"
          },
          "count": {
            "type": "integer",
            "format": "int32"
          }
        },
        "additionalProperties": false
      }
    }
  }
}