{
  "openapi": "3.1.0",
  "info": {
    "title": "Cryptolive API",
    "version": "2.10.0",
    "description": "Read-only caching proxy over CoinGecko and related market feeds. API responses expose cache state through X-Cache, support conditional requests with ETags, and are rate limited per IP (429 with Retry-After). Upstream cooldowns return 503 with Retry-After. Tabular endpoints can return CSV with ?format=csv."
  },
  "servers": [
    {
      "url": "/"
    }
  ],
  "security": [
    {},
    {
      "apiKey": []
    }
  ],
  "paths": {
    "/api/push/config": {
      "get": {
        "summary": "Alert transport configuration",
        "responses": {
          "200": {
            "description": "Enabled transports and webhook providers",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "push": { "type": "boolean" },
                    "webhooks": { "type": "boolean" },
                    "providers": {
                      "type": "array",
                      "items": { "type": "string", "enum": ["discord", "slack", "telegram", "ntfy", "generic"] }
                    }
                  },
                  "required": ["push", "webhooks", "providers"]
                }
              }
            }
          },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/push/key": {
      "get": {
        "summary": "Web Push application server key",
        "responses": {
          "200": {
            "description": "VAPID public key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "publicKey": { "type": "string" } },
                  "required": ["publicKey"]
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/push/subscription": {
      "put": {
        "summary": "Create or replace Web Push or webhook alert rules",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": { "schema": { "$ref": "#/components/schemas/PushSubscriptionBody" } }
          }
        },
        "responses": {
          "200": {
            "description": "Subscription stored",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": { "type": "boolean", "const": true },
                    "rules": { "type": "integer", "minimum": 0 }
                  },
                  "required": ["ok", "rules"]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "413": { "description": "Request body exceeds 32 KB" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      },
      "delete": {
        "summary": "Remove a Web Push or webhook subscription",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": { "endpoint": { "type": "string", "format": "uri", "maxLength": 2048 } },
                    "required": ["endpoint"]
                  },
                  {
                    "type": "object",
                    "properties": { "url": { "type": "string", "format": "uri", "maxLength": 512 } },
                    "required": ["url"]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Removal result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": { "type": "boolean", "const": true },
                    "removed": { "type": "boolean" }
                  },
                  "required": ["ok", "removed"]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "413": { "description": "Request body exceeds 32 KB" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/push/test": {
      "post": {
        "summary": "Send a test alert",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "subscription": { "$ref": "#/components/schemas/PushSubscriptionBody/properties/subscription" }
                },
                "required": ["subscription"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Test alert delivery result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": { "type": "boolean" },
                    "status": { "type": "integer", "minimum": 0, "maximum": 599 }
                  },
                  "required": ["ok", "status"]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "413": { "description": "Request body exceeds 32 KB" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/global": {
      "get": {
        "summary": "Global market statistics",
        "responses": {
          "200": {
            "description": "CoinGecko global market data",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "properties": {
                    "history": {
                      "type": "object",
                      "properties": {
                        "market_cap_usd": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "date": { "type": "string", "format": "date" },
                              "value": { "type": "number" }
                            },
                            "required": ["date", "value"]
                          }
                        },
                        "volume_usd": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "date": { "type": "string", "format": "date" },
                              "value": { "type": "number" }
                            },
                            "required": ["date", "value"]
                          }
                        },
                        "btc_dominance": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "date": { "type": "string", "format": "date" },
                              "value": { "type": "number" }
                            },
                            "required": ["date", "value"]
                          }
                        },
                        "eth_dominance": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "date": { "type": "string", "format": "date" },
                              "value": { "type": "number" }
                            },
                            "required": ["date", "value"]
                          }
                        }
                      },
                      "required": ["market_cap_usd", "volume_usd", "btc_dominance", "eth_dominance"]
                    }
                  },
                  "required": ["history"]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/news": {
      "get": {
        "summary": "Aggregated crypto news headlines",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": { "type": "integer", "minimum": 1, "maximum": 200, "default": 50 }
          },
          {
            "name": "q",
            "in": "query",
            "description": "Case-insensitive title substring, at most 100 characters",
            "schema": { "type": "string", "maxLength": 100 }
          },
          {
            "name": "source",
            "in": "query",
            "schema": { "type": "string", "pattern": "^[a-z0-9-]{1,30}$" }
          },
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "Aggregated RSS/Atom news, or CSV",
            "headers": {
              "X-Cache": { "$ref": "#/components/headers/X-Cache" },
              "ETag": { "$ref": "#/components/headers/ETag" },
              "X-Request-Id": { "$ref": "#/components/headers/X-Request-Id" },
              "X-RateLimit-Remaining": { "$ref": "#/components/headers/X-RateLimit-Remaining" }
            },
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/News" } },
              "text/csv": { "schema": { "type": "string" } }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/derivatives": {
      "get": {
        "summary": "Perpetual futures by open interest",
        "parameters": [
          {
            "name": "view",
            "in": "query",
            "schema": { "type": "string", "enum": ["contracts", "assets"], "default": "contracts" }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": { "type": "integer", "minimum": 1, "maximum": 300, "default": 100 }
          },
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "Top perpetual contracts or per-asset aggregates, or CSV",
            "headers": {
              "X-Cache": { "$ref": "#/components/headers/X-Cache" },
              "ETag": { "$ref": "#/components/headers/ETag" },
              "X-Request-Id": { "$ref": "#/components/headers/X-Request-Id" },
              "X-RateLimit-Remaining": { "$ref": "#/components/headers/X-RateLimit-Remaining" }
            },
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Derivatives" } },
              "text/csv": { "schema": { "type": "string" } }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "503": { "$ref": "#/components/responses/Unavailable" }
        }
      }
    },
    "/api/treasuries": {
      "get": {
        "summary": "Public company cryptocurrency treasuries",
        "parameters": [
          {
            "name": "coin",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["bitcoin", "ethereum"],
              "default": "bitcoin"
            }
          },
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "Public companies holding Bitcoin or Ethereum, or CSV",
            "headers": {
              "X-Cache": { "$ref": "#/components/headers/X-Cache" },
              "ETag": { "$ref": "#/components/headers/ETag" },
              "X-Request-Id": { "$ref": "#/components/headers/X-Request-Id" },
              "X-RateLimit-Remaining": { "$ref": "#/components/headers/X-RateLimit-Remaining" }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "coin": { "type": "string", "enum": ["bitcoin", "ethereum"] },
                    "totalHoldings": { "type": ["number", "null"] },
                    "totalValueUsd": { "type": ["number", "null"] },
                    "marketCapDominance": { "type": ["number", "null"] },
                    "companies": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": { "type": ["string", "null"] },
                          "symbol": { "type": ["string", "null"] },
                          "country": { "type": ["string", "null"] },
                          "holdings": { "type": ["number", "null"] },
                          "entryValueUsd": { "type": ["number", "null"] },
                          "currentValueUsd": { "type": ["number", "null"] },
                          "supplyShare": { "type": ["number", "null"] }
                        },
                        "required": ["name", "symbol", "country", "holdings", "entryValueUsd", "currentValueUsd", "supplyShare"]
                      }
                    }
                  },
                  "required": ["coin", "totalHoldings", "totalValueUsd", "marketCapDominance", "companies"]
                }
              },
              "text/csv": { "schema": { "type": "string" } }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "503": { "$ref": "#/components/responses/Unavailable" }
        }
      }
    },
    "/api/fng": {
      "get": {
        "summary": "Fear and Greed Index",
        "responses": {
          "200": {
            "description": "Current index and 30-day history",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fng"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/altseason": {
      "get": {
        "summary": "Altcoin Season Index",
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "24h",
                "7d",
                "30d"
              ],
              "default": "30d"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Share of the top 50 eligible coins outperforming Bitcoin",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Altseason"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/trending": {
      "get": {
        "summary": "Trending coins, categories, and NFTs",
        "responses": {
          "200": {
            "description": "Trending results",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Trending"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/popular": {
      "get": {
        "summary": "Most viewed coins on this instance",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Popularity-ranked coins",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Popular"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/markets": {
      "get": {
        "summary": "Market coin list",
        "parameters": [
          {
            "$ref": "#/components/parameters/Vs"
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "ids",
            "in": "query",
            "description": "Comma-separated coin IDs, at most 100",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9-]+$"
            }
          },
          {
            "name": "order",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "market_cap_desc",
              "enum": [
                "market_cap_asc",
                "market_cap_desc",
                "volume_asc",
                "volume_desc",
                "id_asc",
                "id_desc"
              ]
            }
          },
          {
            "name": "sparkline",
            "in": "query",
            "description": "Set to false to omit the 7-day sparkline arrays",
            "schema": {
              "type": "boolean",
              "default": true
            }
          },
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "Market rows (or CSV)",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MarketRow"
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/coin/{id}": {
      "get": {
        "summary": "Coin detail",
        "parameters": [
          {
            "$ref": "#/components/parameters/CoinId"
          }
        ],
        "responses": {
          "200": {
            "description": "Coin metadata and market data",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Coin"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/coin/{id}/similar": {
      "get": {
        "summary": "Coins with nearby market-cap ranks",
        "parameters": [
          {
            "$ref": "#/components/parameters/CoinId"
          },
          {
            "$ref": "#/components/parameters/Vs"
          }
        ],
        "responses": {
          "200": {
            "description": "Up to eight similar market rows",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Similar"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/coin/{id}/chart": {
      "get": {
        "summary": "Historical market chart",
        "parameters": [
          {
            "$ref": "#/components/parameters/CoinId"
          },
          {
            "$ref": "#/components/parameters/Vs"
          },
          {
            "name": "days",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "7",
                "30",
                "90",
                "365",
                "max"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "Price, market-cap, and volume series (or CSV)",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Chart"
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/coin/{id}/ohlc": {
      "get": {
        "summary": "OHLC candlestick data",
        "parameters": [
          {
            "$ref": "#/components/parameters/CoinId"
          },
          {
            "$ref": "#/components/parameters/Vs"
          },
          {
            "name": "days",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "7",
                "14",
                "30",
                "90",
                "180",
                "365"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "OHLC tuples (or CSV)",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ohlc"
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/coin/{id}/tickers": {
      "get": {
        "summary": "Coin exchange tickers",
        "parameters": [
          {
            "$ref": "#/components/parameters/CoinId"
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Trading pairs sorted by volume",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Tickers"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/search": {
      "get": {
        "summary": "Search coins, categories, and exchanges",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search results",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/categories": {
      "get": {
        "summary": "Cryptocurrency categories",
        "parameters": [
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "Categories sorted by market cap (or CSV)",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Category"
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/exchanges": {
      "get": {
        "summary": "Exchange list",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "Exchange rows (or CSV)",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Exchange"
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/exchange/{id}": {
      "get": {
        "summary": "Exchange detail",
        "parameters": [
          {
            "$ref": "#/components/parameters/ExchangeId"
          }
        ],
        "responses": {
          "200": {
            "description": "Exchange profile and top 100 tickers",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExchangeDetail"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/exchange/{id}/volume": {
      "get": {
        "summary": "Exchange BTC volume chart",
        "parameters": [
          {
            "$ref": "#/components/parameters/ExchangeId"
          },
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "7",
                "14",
                "30",
                "90"
              ],
              "default": "30"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Timestamp and BTC-volume points",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/VolumePoint"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/simple-price": {
      "get": {
        "summary": "Prices and 24-hour changes",
        "parameters": [
          {
            "name": "ids",
            "in": "query",
            "required": true,
            "description": "Comma-separated coin IDs, at most 100",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "vs",
            "in": "query",
            "required": true,
            "description": "Comma-separated currencies. Each value must be one of: usd, eur, gbp, rub, jpy, cny, cad, aud, chf, krw, inr, brl, try, uah, pln, kzt, mxn, ars, clp, cop, idr, vnd, php, thb, myr, sgd, hkd, twd, nzd, zar, ngn, aed, sar, ils, sek, nok, dkk, czk, huf, pkr, bdt, btc, eth.",
            "schema": {
              "type": "string",
              "example": "usd,eur"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Objects keyed by coin ID and currency",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimplePrice"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/currencies": {
      "get": {
        "summary": "Supported display currencies",
        "responses": {
          "200": {
            "description": "Fiat and crypto currencies",
            "headers": {
              "X-Cache": {
                "$ref": "#/components/headers/X-Cache"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Currency"
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/stream": {
      "get": {
        "summary": "Live price stream",
        "description": "Server-Sent Events stream. A hello event announces tracked coin IDs; tick events arrive at most once per second with a timestamp and USD price (p) and 24-hour change (c) keyed by coin ID. Comment pings keep the connection alive.",
        "responses": {
          "200": {
            "description": "SSE hello and tick event stream",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "examples": [
                    "event: hello\ndata: {\"symbols\":[\"bitcoin\"]}\n\nevent: tick\ndata: {\"ts\":1710000000000,\"prices\":{\"bitcoin\":{\"p\":76318.9,\"c\":0.46}}}\n\n"
                  ]
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/healthz": {
      "get": {
        "summary": "Service health",
        "responses": {
          "200": {
            "description": "Runtime, cache, upstream, live-feed, and Web Push status",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          }
        }
      }
    },
    "/metrics": {
      "get": {
        "summary": "Prometheus metrics",
        "description": "Available unless metrics are disabled. If METRICS_TOKEN is configured, send it as a bearer token.",
        "security": [
          {},
          {
            "metricsToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Prometheus text exposition",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Bearer token required",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Optional consumer API key"
      },
      "metricsToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "Optional METRICS_TOKEN value"
      }
    },
    "parameters": {
      "Vs": {
        "name": "vs",
        "in": "query",
        "schema": {
          "type": "string",
          "default": "usd",
          "enum": [
            "usd",
            "eur",
            "gbp",
            "rub",
            "jpy",
            "cny",
            "cad",
            "aud",
            "chf",
            "krw",
            "inr",
            "brl",
            "try",
            "uah",
            "pln",
            "kzt",
            "mxn",
            "ars",
            "clp",
            "cop",
            "idr",
            "vnd",
            "php",
            "thb",
            "myr",
            "sgd",
            "hkd",
            "twd",
            "nzd",
            "zar",
            "ngn",
            "aed",
            "sar",
            "ils",
            "sek",
            "nok",
            "dkk",
            "czk",
            "huf",
            "pkr",
            "bdt",
            "btc",
            "eth"
          ]
        }
      },
      "Page": {
        "name": "page",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 1000,
          "default": 1
        }
      },
      "PerPage": {
        "name": "per_page",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 250,
          "default": 100
        }
      },
      "Format": {
        "name": "format",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": [
            "json",
            "csv"
          ],
          "default": "json"
        }
      },
      "CoinId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^[a-z0-9-]+$"
        }
      },
      "ExchangeId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^[a-z0-9_-]{1,60}$"
        }
      }
    },
    "headers": {
      "X-Cache": {
        "description": "Cache result: hit, miss, stale, universe, fallback, or aggregate",
        "schema": {
          "type": "string",
          "enum": [
            "hit",
            "miss",
            "stale",
            "universe",
            "fallback",
            "aggregate"
          ]
        }
      },
      "ETag": {
        "description": "Weak entity tag for conditional requests",
        "schema": {
          "type": "string"
        }
      },
      "X-Request-Id": {
        "description": "Request correlation identifier",
        "schema": {
          "type": "string"
        }
      },
      "X-RateLimit-Remaining": {
        "description": "Requests remaining in the current rate-limit window",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "X-RateLimit-Limit": {
        "description": "Maximum requests allowed in the current rate-limit window",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "X-RateLimit-Reset": {
        "description": "Unix timestamp in seconds when the current rate-limit window resets",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "Retry-After": {
        "description": "Seconds before retrying",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid query or path parameter",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Per-IP rate limit exceeded",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unavailable": {
        "description": "Upstream cooldown or live connection capacity reached",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          },
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "PushRule": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "id": { "type": "string", "pattern": "^[A-Za-z0-9_-]{1,64}$" },
              "coinId": { "type": "string", "pattern": "^[a-z0-9-]{1,100}$" },
              "condition": { "type": "string", "enum": ["above", "below", "change_up", "change_down"] },
              "price": { "type": "number", "exclusiveMinimum": 0 },
              "percent": { "type": "number", "exclusiveMinimum": 0, "maximum": 1000 },
              "repeat": { "type": "boolean", "default": false },
              "title": { "type": "string", "maxLength": 120 },
              "body": { "type": "string", "maxLength": 240, "description": "May contain the {price} placeholder." },
              "url": { "type": "string", "pattern": "^/[^/].*|^/$", "maxLength": 200 }
            },
            "required": ["id", "coinId", "condition", "title", "body"]
          },
          {
            "type": "object",
            "properties": {
              "id": { "type": "string", "pattern": "^[A-Za-z0-9_-]{1,64}$" },
              "kind": { "const": "macro" },
              "metric": { "type": "string", "enum": ["fng", "altseason", "btc_dominance", "funding"] },
              "asset": { "type": "string", "pattern": "^[A-Z0-9]{1,12}$" },
              "condition": { "type": "string", "enum": ["above", "below"] },
              "value": { "type": "number" },
              "repeat": { "type": "boolean", "default": false },
              "title": { "type": "string", "maxLength": 120 },
              "body": { "type": "string", "maxLength": 240, "description": "May contain the {value} placeholder." },
              "url": { "type": "string", "pattern": "^/[^/].*|^/$", "maxLength": 200 }
            },
            "required": ["id", "kind", "metric", "condition", "value", "title", "body"],
            "allOf": [
              {
                "if": { "properties": { "metric": { "const": "funding" } } },
                "then": {
                  "required": ["asset"],
                  "properties": { "value": { "minimum": -5, "maximum": 5 } }
                },
                "else": {
                  "properties": { "value": { "minimum": 0, "maximum": 100 } }
                }
              }
            ]
          }
        ]
      },
      "PushSubscriptionBody": {
        "type": "object",
        "properties": {
          "subscription": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "endpoint": { "type": "string", "format": "uri", "maxLength": 2048 },
                  "keys": {
                    "type": "object",
                    "properties": {
                      "p256dh": { "type": "string" },
                      "auth": { "type": "string" }
                    },
                    "required": ["p256dh", "auth"]
                  }
                },
                "required": ["endpoint", "keys"]
              },
              {
                "type": "object",
                "properties": {
                  "type": { "const": "webhook" },
                  "url": { "type": "string", "format": "uri", "maxLength": 512 }
                },
                "required": ["type", "url"]
              }
            ]
          },
          "rules": { "type": "array", "maxItems": 100, "items": { "$ref": "#/components/schemas/PushRule" } },
          "lang": { "type": "string", "pattern": "^[a-z]{2}(-[A-Za-z]{2,8})?$", "default": "en" },
          "currency": { "type": "string", "pattern": "^[a-z]{3,4}$", "default": "usd" }
        },
        "required": ["subscription", "rules"]
      },
      "NullableNumber": {
        "type": [
          "number",
          "null"
        ]
      },
      "NullableString": {
        "type": [
          "string",
          "null"
        ]
      },
      "News": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": { "type": "string" },
                "title": { "type": "string" },
                "link": { "type": "string", "format": "uri" },
                "published": { "type": ["integer", "null"] },
                "summary": { "type": "string" },
                "source": { "type": "string" },
                "sourceName": { "type": "string" }
              },
              "required": ["id", "title", "link", "published", "summary", "source", "sourceName"]
            }
          },
          "feeds": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": { "type": "string" },
                "name": { "type": "string" },
                "ok": { "type": "boolean" },
                "count": { "type": "integer", "minimum": 0 }
              },
              "required": ["id", "name", "ok", "count"]
            }
          },
          "updatedAt": { "type": "integer" }
        },
        "required": ["items", "feeds", "updatedAt"]
      },
      "Derivatives": {
        "type": "object",
        "properties": {
          "view": { "type": "string", "enum": ["contracts", "assets"] },
          "items": {
            "type": "array",
            "items": {
              "oneOf": [
                { "$ref": "#/components/schemas/DerivativeContract" },
                { "$ref": "#/components/schemas/DerivativeAsset" }
              ]
            }
          },
          "updatedAt": { "type": "integer" }
        },
        "required": ["view", "items", "updatedAt"]
      },
      "DerivativeContract": {
        "type": "object",
        "properties": {
          "market": { "type": "string" },
          "symbol": { "type": "string" },
          "indexId": { "type": "string" },
          "price": { "$ref": "#/components/schemas/NullableNumber" },
          "change24h": { "$ref": "#/components/schemas/NullableNumber" },
          "fundingRate": { "$ref": "#/components/schemas/NullableNumber" },
          "openInterest": { "type": "number" },
          "volume24h": { "$ref": "#/components/schemas/NullableNumber" },
          "basis": { "$ref": "#/components/schemas/NullableNumber" },
          "spread": { "$ref": "#/components/schemas/NullableNumber" },
          "lastTradedAt": { "type": ["integer", "null"] }
        },
        "required": ["market", "symbol", "indexId", "price", "change24h", "fundingRate", "openInterest", "volume24h", "basis", "spread", "lastTradedAt"]
      },
      "DerivativeAsset": {
        "type": "object",
        "properties": {
          "indexId": { "type": "string" },
          "contracts": { "type": "integer", "minimum": 1 },
          "openInterest": { "type": "number" },
          "volume24h": { "type": "number" },
          "fundingRate": { "$ref": "#/components/schemas/NullableNumber" },
          "change24h": { "$ref": "#/components/schemas/NullableNumber" },
          "topMarket": { "type": "string" }
        },
        "required": ["indexId", "contracts", "openInterest", "volume24h", "fundingRate", "change24h", "topMarket"]
      },
      "MarketRow": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "image": {
            "$ref": "#/components/schemas/NullableString"
          },
          "current_price": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "market_cap": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "market_cap_rank": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "fully_diluted_valuation": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "total_volume": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "high_24h": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "low_24h": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "price_change_percentage_24h": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "price_change_percentage_1h_in_currency": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "price_change_percentage_7d_in_currency": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "price_change_percentage_30d_in_currency": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "price_change_percentage_1y_in_currency": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "circulating_supply": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "total_supply": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "max_supply": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "ath": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "atl": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "last_updated": {
            "$ref": "#/components/schemas/NullableString"
          },
          "sparkline_in_7d": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "price": {
                "type": "array",
                "items": {
                  "type": "number"
                }
              }
            }
          }
        },
        "required": [
          "id",
          "symbol",
          "name"
        ]
      },
      "Coin": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "image": {
            "type": [
              "object",
              "string",
              "null"
            ],
            "additionalProperties": true
          },
          "market_cap_rank": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "description": {
            "type": [
              "object",
              "string"
            ],
            "additionalProperties": true
          },
          "links": {
            "type": "object",
            "additionalProperties": true
          },
          "market_data": {
            "type": "object",
            "additionalProperties": true
          },
          "partial": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "symbol",
          "name"
        ]
      },
      "ChartPoint": {
        "type": "array",
        "prefixItems": [
          {
            "type": "number"
          },
          {
            "type": "number"
          }
        ],
        "minItems": 2,
        "maxItems": 2
      },
      "Chart": {
        "type": "object",
        "properties": {
          "prices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChartPoint"
            }
          },
          "market_caps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChartPoint"
            }
          },
          "total_volumes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChartPoint"
            }
          }
        },
        "required": [
          "prices",
          "market_caps",
          "total_volumes"
        ]
      },
      "Ohlc": {
        "type": "array",
        "items": {
          "type": "array",
          "prefixItems": [
            {
              "type": "number"
            },
            {
              "type": "number"
            },
            {
              "type": "number"
            },
            {
              "type": "number"
            },
            {
              "type": "number"
            }
          ],
          "minItems": 5,
          "maxItems": 5
        }
      },
      "Ticker": {
        "type": "object",
        "properties": {
          "exchange": {
            "type": "string"
          },
          "exchange_id": {
            "type": "string"
          },
          "exchange_logo": {
            "$ref": "#/components/schemas/NullableString"
          },
          "base": {
            "type": "string"
          },
          "target": {
            "type": "string"
          },
          "coin_id": {
            "$ref": "#/components/schemas/NullableString"
          },
          "target_coin_id": {
            "$ref": "#/components/schemas/NullableString"
          },
          "last_usd": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "volume_usd": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "trust_score": {
            "$ref": "#/components/schemas/NullableString"
          },
          "spread": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "trade_url": {
            "$ref": "#/components/schemas/NullableString"
          }
        }
      },
      "Tickers": {
        "type": "object",
        "properties": {
          "tickers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Ticker"
            }
          }
        },
        "required": [
          "tickers"
        ]
      },
      "SearchResult": {
        "type": "object",
        "properties": {
          "coins": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "symbol": {
                  "type": "string"
                },
                "thumb": {
                  "$ref": "#/components/schemas/NullableString"
                },
                "rank": {
                  "$ref": "#/components/schemas/NullableNumber"
                },
                "price_usd": {
                  "$ref": "#/components/schemas/NullableNumber"
                },
                "change24h": {
                  "$ref": "#/components/schemas/NullableNumber"
                },
                "market_cap_usd": {
                  "$ref": "#/components/schemas/NullableNumber"
                }
              }
            }
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                }
              }
            }
          },
          "exchanges": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "thumb": {
                  "$ref": "#/components/schemas/NullableString"
                }
              }
            }
          },
          "partial": {
            "type": "boolean"
          }
        },
        "required": [
          "coins",
          "categories",
          "exchanges"
        ]
      },
      "Category": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "market_cap": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "market_cap_change_24h": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "volume_24h": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "top_3_coins": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "top_3_coins_id": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "Exchange": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "year_established": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "country": {
            "$ref": "#/components/schemas/NullableString"
          },
          "description": {
            "type": "string"
          },
          "url": {
            "$ref": "#/components/schemas/NullableString"
          },
          "image": {
            "$ref": "#/components/schemas/NullableString"
          },
          "trust_score": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "trust_score_rank": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "trade_volume_24h_btc": {
            "$ref": "#/components/schemas/NullableNumber"
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "ExchangeDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Exchange"
          },
          {
            "type": "object",
            "properties": {
              "facebook_url": {
                "$ref": "#/components/schemas/NullableString"
              },
              "reddit_url": {
                "$ref": "#/components/schemas/NullableString"
              },
              "twitter_handle": {
                "$ref": "#/components/schemas/NullableString"
              },
              "centralized": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "trade_volume_24h_btc_normalized": {
                "$ref": "#/components/schemas/NullableNumber"
              },
              "tickers": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Ticker"
                }
              }
            },
            "required": [
              "tickers"
            ]
          }
        ]
      },
      "VolumePoint": {
        "type": "array",
        "prefixItems": [
          {
            "type": "number"
          },
          {
            "type": "number"
          }
        ],
        "minItems": 2,
        "maxItems": 2
      },
      "SimplePrice": {
        "type": "object",
        "additionalProperties": {
          "type": "object",
          "additionalProperties": {
            "type": "number"
          }
        }
      },
      "Currency": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "usd",
              "eur",
              "gbp",
              "rub",
              "jpy",
              "cny",
              "cad",
              "aud",
              "chf",
              "krw",
              "inr",
              "brl",
              "try",
              "uah",
              "pln",
              "kzt",
              "mxn",
              "ars",
              "clp",
              "cop",
              "idr",
              "vnd",
              "php",
              "thb",
              "myr",
              "sgd",
              "hkd",
              "twd",
              "nzd",
              "zar",
              "ngn",
              "aed",
              "sar",
              "ils",
              "sek",
              "nok",
              "dkk",
              "czk",
              "huf",
              "pkr",
              "bdt",
              "btc",
              "eth"
            ]
          },
          "symbol": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        },
        "required": [
          "code",
          "symbol",
          "name"
        ]
      },
      "Fng": {
        "type": "object",
        "properties": {
          "value": {
            "type": "integer"
          },
          "classification": {
            "type": "string"
          },
          "timestamp": {
            "type": "integer"
          },
          "history": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "integer"
                },
                "timestamp": {
                  "type": "integer"
                }
              },
              "required": [
                "value",
                "timestamp"
              ]
            }
          }
        },
        "required": [
          "value",
          "classification",
          "timestamp",
          "history"
        ]
      },
      "Altseason": {
        "type": "object",
        "properties": {
          "windows": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "24h",
                "7d",
                "30d"
              ]
            }
          },
          "window": {
            "type": "string",
            "enum": [
              "24h",
              "7d",
              "30d"
            ]
          },
          "index": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "outperformers": {
            "type": "integer",
            "minimum": 0
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "btcChange": {
            "$ref": "#/components/schemas/NullableNumber"
          },
          "season": {
            "type": "string",
            "enum": [
              "altcoin",
              "bitcoin",
              "neutral"
            ]
          },
          "history": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "date": {
                  "type": "string",
                  "format": "date"
                },
                "index": {
                  "type": "integer"
                }
              },
              "required": [
                "date",
                "index"
              ]
            }
          },
          "leaders": {
            "type": "array",
            "maxItems": 5,
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "symbol": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "image": {
                  "$ref": "#/components/schemas/NullableString"
                },
                "change": {
                  "type": "number"
                }
              },
              "required": [
                "id",
                "symbol",
                "name",
                "change"
              ]
            }
          }
        },
        "required": [
          "windows",
          "window",
          "index",
          "outperformers",
          "total",
          "btcChange",
          "season",
          "history",
          "leaders"
        ]
      },
      "Trending": {
        "type": "object",
        "properties": {
          "coins": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "symbol": {
                  "type": "string"
                },
                "thumb": {
                  "$ref": "#/components/schemas/NullableString"
                },
                "rank": {
                  "$ref": "#/components/schemas/NullableNumber"
                },
                "price_usd": {
                  "$ref": "#/components/schemas/NullableNumber"
                },
                "change24h": {
                  "$ref": "#/components/schemas/NullableNumber"
                },
                "market_cap_usd": {
                  "$ref": "#/components/schemas/NullableNumber"
                },
                "volume_usd": {
                  "$ref": "#/components/schemas/NullableNumber"
                },
                "sparkline_url": {
                  "$ref": "#/components/schemas/NullableString"
                }
              }
            }
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "nfts": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "required": [
          "coins",
          "categories",
          "nfts"
        ]
      },
      "Popular": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "name": {
              "type": "string"
            },
            "symbol": {
              "type": "string"
            },
            "image": {
              "$ref": "#/components/schemas/NullableString"
            },
            "views": {
              "type": "integer"
            },
            "score": {
              "type": "number"
            },
            "price_usd": {
              "$ref": "#/components/schemas/NullableNumber"
            },
            "change24h": {
              "$ref": "#/components/schemas/NullableNumber"
            },
            "market_cap_rank": {
              "$ref": "#/components/schemas/NullableNumber"
            }
          },
          "required": [
            "id",
            "name",
            "symbol",
            "views",
            "score"
          ]
        }
      },
      "Similar": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/MarketRow"
        }
      },
      "Health": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "version": {
            "type": "string"
          },
          "node": {
            "type": "string"
          },
          "uptime": {
            "type": "integer"
          },
          "startedAt": {
            "type": "integer"
          },
          "now": {
            "type": "integer"
          },
          "memory": {
            "type": "object",
            "properties": {
              "rss": {
                "type": "integer"
              },
              "heapUsed": {
                "type": "integer"
              }
            },
            "required": [
              "rss",
              "heapUsed"
            ]
          },
          "cache": {
            "type": "object",
            "additionalProperties": true
          },
          "upstream": {
            "type": "object",
            "additionalProperties": true
          },
          "live": {
            "type": "object",
            "additionalProperties": true
          },
          "push": {
            "type": "object",
            "properties": {
              "enabled": { "type": "boolean" },
              "subscriptions": { "type": "integer", "minimum": 0 },
              "webhooks": { "type": "integer", "minimum": 0 },
              "rules": { "type": "integer", "minimum": 0 },
              "sent": { "type": "integer", "minimum": 0 },
              "failed": { "type": "integer", "minimum": 0 },
              "lastRunAt": { "type": ["integer", "null"] }
            },
            "required": ["enabled", "subscriptions", "webhooks", "rules", "sent", "failed", "lastRunAt"]
          }
        },
        "required": [
          "ok",
          "version",
          "node",
          "uptime",
          "startedAt",
          "now",
          "memory",
          "cache",
          "upstream",
          "live",
          "push"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        },
        "required": [
          "error"
        ]
      }
    }
  }
}
