{
  "openapi": "3.1.0",
  "info": {
    "title": "Resolved Markets API",
    "version": "1.0.0",
    "summary": "High-fidelity orderbook data for Polymarket prediction markets and Hyperliquid perpetual futures.",
    "description": "REST API for live and historical orderbook snapshots, trades, and platform statistics. Public endpoints (health, public-stats, status, payment packs) require no authentication. All other endpoints require an `X-API-Key` header where the key starts with `rm_`. Get a key at https://resolvedmarkets.com/api-keys after signing up.\n\nProbabilities are USDC prices in 0.01..0.99. Each Polymarket binary market has two tokens — UP (Yes outcome) and DOWN (No outcome) — each with its own orderbook. UP price + DOWN price ≈ 1.00.",
    "termsOfService": "https://resolvedmarkets.com/pricing",
    "contact": {
      "name": "Resolved Markets",
      "email": "info@elcara.xyz",
      "url": "https://resolvedmarkets.com"
    },
    "license": {
      "name": "Commercial — see Pricing page",
      "url": "https://resolvedmarkets.com/pricing"
    }
  },
  "externalDocs": {
    "description": "Interactive API docs and getting-started guides",
    "url": "https://resolvedmarkets.com/docs"
  },
  "servers": [
    {
      "url": "https://api.resolvedmarkets.com",
      "description": "Production"
    }
  ],
  "tags": [
    { "name": "Public", "description": "No authentication required." },
    { "name": "Markets", "description": "Polymarket prediction market data." },
    { "name": "Snapshots", "description": "Point-in-time and time-series orderbook snapshots." },
    { "name": "Exchange", "description": "Hyperliquid perpetual futures L2 book." },
    { "name": "System", "description": "Platform-wide stats and diagnostics." },
    { "name": "Account", "description": "API key management and tier information." }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "API key prefixed with `rm_`. Generate at https://resolvedmarkets.com/api-keys."
      }
    },
    "parameters": {
      "ConditionId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Polymarket conditionId (hex string).",
        "schema": { "type": "string" }
      },
      "Slug": {
        "name": "slug",
        "in": "path",
        "required": true,
        "description": "Market slug (e.g. `btc-updown-5m`). Fuzzy matched.",
        "schema": { "type": "string" }
      },
      "Category": {
        "name": "category",
        "in": "query",
        "required": false,
        "description": "Filter by market category.",
        "schema": {
          "type": "string",
          "enum": ["crypto", "sports", "economics", "weather", "social", "exchange"]
        }
      },
      "Subcategory": {
        "name": "subcategory",
        "in": "query",
        "required": false,
        "description": "Filter by subcategory (e.g. BTC, NBA, FOMC).",
        "schema": { "type": "string" }
      },
      "From": {
        "name": "from",
        "in": "query",
        "required": false,
        "description": "ISO-8601 inclusive lower bound for capture timestamp.",
        "schema": { "type": "string", "format": "date-time" }
      },
      "To": {
        "name": "to",
        "in": "query",
        "required": false,
        "description": "ISO-8601 exclusive upper bound for capture timestamp.",
        "schema": { "type": "string", "format": "date-time" }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Maximum number of records to return (max 500).",
        "schema": { "type": "integer", "minimum": 1, "maximum": 500, "default": 100 }
      },
      "Side": {
        "name": "side",
        "in": "query",
        "required": false,
        "description": "Restrict to one token side.",
        "schema": { "type": "string", "enum": ["UP", "DOWN"] }
      }
    },
    "schemas": {
      "OrderbookLevel": {
        "type": "array",
        "minItems": 2,
        "maxItems": 2,
        "items": { "type": "number" },
        "description": "[price, size] tuple."
      },
      "TokenBook": {
        "type": "object",
        "properties": {
          "token_id": { "type": "string" },
          "side": { "type": "string", "enum": ["UP", "DOWN"] },
          "best_bid": { "type": "number" },
          "best_ask": { "type": "number" },
          "mid": { "type": "number" },
          "spread": { "type": "number" },
          "bids": { "type": "array", "items": { "$ref": "#/components/schemas/OrderbookLevel" } },
          "asks": { "type": "array", "items": { "$ref": "#/components/schemas/OrderbookLevel" } },
          "depth5_bid": { "type": "number" },
          "depth5_ask": { "type": "number" }
        }
      },
      "Snapshot": {
        "type": "object",
        "properties": {
          "condition_id": { "type": "string" },
          "token_id": { "type": "string" },
          "side": { "type": "string", "enum": ["UP", "DOWN"] },
          "event_timestamp": { "type": "string", "format": "date-time" },
          "capture_timestamp": { "type": "string", "format": "date-time" },
          "sequence_number": { "type": "integer" },
          "best_bid": { "type": "number" },
          "best_ask": { "type": "number" },
          "mid": { "type": "number" },
          "spread": { "type": "number" },
          "bids": { "type": "array", "items": { "$ref": "#/components/schemas/OrderbookLevel" } },
          "asks": { "type": "array", "items": { "$ref": "#/components/schemas/OrderbookLevel" } },
          "depth5_bid": { "type": "number" },
          "depth5_ask": { "type": "number" },
          "spot_crypto_usd": { "type": "number", "nullable": true },
          "spot_crypto_age_ms": { "type": "integer", "nullable": true }
        }
      },
      "Market": {
        "type": "object",
        "properties": {
          "condition_id": { "type": "string" },
          "slug": { "type": "string" },
          "question": { "type": "string" },
          "category": { "type": "string" },
          "subcategory": { "type": "string" },
          "timeframe": { "type": "string" },
          "active": { "type": "boolean" },
          "tokens": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "token_id": { "type": "string" },
                "side": { "type": "string", "enum": ["UP", "DOWN"] }
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string" },
          "message": { "type": "string" },
          "status": { "type": "integer" }
        },
        "required": ["error", "message", "status"]
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid API key.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "PaymentRequired": {
        "description": "Out of credits or tier does not permit this endpoint.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "NotFound": {
        "description": "Resource not found.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "RateLimited": {
        "description": "Rate limit exceeded.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    }
  },
  "security": [{ "ApiKeyAuth": [] }],
  "paths": {
    "/health": {
      "get": {
        "tags": ["Public"],
        "operationId": "getHealth",
        "summary": "Service health",
        "description": "Returns ClickHouse, Redis, pipeline, and WebSocket health. No authentication required.",
        "security": [],
        "responses": {
          "200": {
            "description": "Service health snapshot.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          }
        }
      }
    },
    "/v1/public-stats": {
      "get": {
        "tags": ["Public"],
        "operationId": "getPublicStats",
        "summary": "Public platform statistics",
        "description": "Snapshot count, active markets, current crypto prices, and exchange data freshness. No authentication required.",
        "security": [],
        "responses": {
          "200": {
            "description": "Public statistics.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          }
        }
      }
    },
    "/v1/status": {
      "get": {
        "tags": ["Public"],
        "operationId": "getStatus",
        "summary": "Per-service uptime",
        "description": "90-day uptime history per service plus current overall status. No authentication required.",
        "security": [],
        "responses": {
          "200": {
            "description": "Uptime snapshot.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          }
        }
      }
    },
    "/v1/payments/packs": {
      "get": {
        "tags": ["Public"],
        "operationId": "listCreditPacks",
        "summary": "Tier and credit pack pricing",
        "description": "Subscription tiers and prepaid credit pack pricing. No authentication required.",
        "security": [],
        "responses": {
          "200": {
            "description": "Tier and pack catalog.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          }
        }
      }
    },
    "/v1/categories": {
      "get": {
        "tags": ["Markets"],
        "operationId": "listCategories",
        "summary": "List enabled categories",
        "description": "All enabled categories with active market counts and capture rates.",
        "responses": {
          "200": {
            "description": "Category list.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/markets/live": {
      "get": {
        "tags": ["Markets"],
        "operationId": "listLiveMarkets",
        "summary": "List active markets",
        "description": "Returns markets currently being tracked. Filter with `category` and `subcategory`.",
        "parameters": [
          { "$ref": "#/components/parameters/Category" },
          { "$ref": "#/components/parameters/Subcategory" }
        ],
        "responses": {
          "200": {
            "description": "Markets array.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "markets": { "type": "array", "items": { "$ref": "#/components/schemas/Market" } }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/markets/by-slug/{slug}": {
      "get": {
        "tags": ["Markets"],
        "operationId": "getMarketBySlug",
        "summary": "Lookup market by slug",
        "description": "Fuzzy-matched slug lookup (e.g. `btc-updown-5m`).",
        "parameters": [{ "$ref": "#/components/parameters/Slug" }],
        "responses": {
          "200": {
            "description": "Market record.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Market" } } }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/markets/by-slug/{slug}/orderbook": {
      "get": {
        "tags": ["Markets"],
        "operationId": "getOrderbookBySlug",
        "summary": "Live orderbook by slug",
        "parameters": [{ "$ref": "#/components/parameters/Slug" }],
        "responses": {
          "200": {
            "description": "UP and DOWN orderbooks.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "up": { "$ref": "#/components/schemas/TokenBook" },
                    "down": { "$ref": "#/components/schemas/TokenBook" }
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/markets/{id}/orderbook": {
      "get": {
        "tags": ["Markets"],
        "operationId": "getOrderbook",
        "summary": "Live orderbook by conditionId",
        "description": "In-memory live orderbook for both UP and DOWN tokens.",
        "parameters": [{ "$ref": "#/components/parameters/ConditionId" }],
        "responses": {
          "200": {
            "description": "UP and DOWN orderbooks.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "up": { "$ref": "#/components/schemas/TokenBook" },
                    "down": { "$ref": "#/components/schemas/TokenBook" }
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/markets/{id}/snapshots": {
      "get": {
        "tags": ["Snapshots"],
        "operationId": "listMarketSnapshots",
        "summary": "Historical snapshots for a market",
        "description": "Paginated time-series of orderbook snapshots. Filter with `from`, `to`, `side`. Costs 10 credits.",
        "parameters": [
          { "$ref": "#/components/parameters/ConditionId" },
          { "$ref": "#/components/parameters/From" },
          { "$ref": "#/components/parameters/To" },
          { "$ref": "#/components/parameters/Limit" },
          { "$ref": "#/components/parameters/Side" }
        ],
        "responses": {
          "200": {
            "description": "Snapshot array.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "snapshots": { "type": "array", "items": { "$ref": "#/components/schemas/Snapshot" } }
                  }
                }
              }
            }
          },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/markets/{id}/summary": {
      "get": {
        "tags": ["Markets"],
        "operationId": "getMarketSummary",
        "summary": "Aggregated market stats",
        "description": "Spread, depth, price range, and per-side breakdown over the available history.",
        "parameters": [{ "$ref": "#/components/parameters/ConditionId" }],
        "responses": {
          "200": {
            "description": "Aggregated stats.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/markets/history/recent": {
      "get": {
        "tags": ["Markets"],
        "operationId": "listRecentMarkets",
        "summary": "All tracked markets (recent)",
        "description": "All tracked markets with snapshot counts and live status.",
        "responses": {
          "200": {
            "description": "Markets array.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/markets/history": {
      "get": {
        "tags": ["Markets"],
        "operationId": "listMarketHistory",
        "summary": "Full market history",
        "description": "All tracked markets — filter by category, subcategory, crypto, and timeframe.",
        "parameters": [
          { "$ref": "#/components/parameters/Category" },
          { "$ref": "#/components/parameters/Subcategory" }
        ],
        "responses": {
          "200": {
            "description": "Markets array.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/stats": {
      "get": {
        "tags": ["System"],
        "operationId": "getSystemStats",
        "summary": "Platform-wide statistics",
        "description": "Snapshot totals, per-category breakdown, and pipeline counters.",
        "responses": {
          "200": {
            "description": "Stats object.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/api/snapshot": {
      "get": {
        "tags": ["Snapshots"],
        "operationId": "getSnapshotAtTime",
        "summary": "Point-in-time snapshot",
        "description": "Snapshot closest to the given timestamp for a single market.",
        "parameters": [
          {
            "name": "timestamp",
            "in": "query",
            "required": true,
            "description": "ISO-8601 timestamp.",
            "schema": { "type": "string", "format": "date-time" }
          },
          {
            "name": "marketId",
            "in": "query",
            "required": true,
            "description": "Polymarket conditionId.",
            "schema": { "type": "string" }
          },
          {
            "name": "includebook",
            "in": "query",
            "required": false,
            "description": "Include full bid/ask arrays.",
            "schema": { "type": "boolean", "default": false }
          }
        ],
        "responses": {
          "200": {
            "description": "Snapshot record.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Snapshot" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/api/snapshot/latest": {
      "get": {
        "tags": ["Snapshots"],
        "operationId": "getLatestSnapshots",
        "summary": "Latest snapshots",
        "description": "Last 5 snapshots, optionally filtered by crypto and timeframe.",
        "parameters": [
          {
            "name": "crypto",
            "in": "query",
            "required": false,
            "schema": { "type": "string", "enum": ["BTC", "ETH", "SOL", "XRP"] }
          },
          {
            "name": "timeframe",
            "in": "query",
            "required": false,
            "schema": { "type": "string", "enum": ["5m", "15m", "1h", "1d"] }
          },
          {
            "name": "includebook",
            "in": "query",
            "required": false,
            "schema": { "type": "boolean", "default": false }
          }
        ],
        "responses": {
          "200": {
            "description": "Snapshot array.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/api/debug": {
      "get": {
        "tags": ["System"],
        "operationId": "getDebugStats",
        "summary": "Pipeline diagnostics",
        "description": "Capture rates, buffer depths, error counts.",
        "responses": {
          "200": {
            "description": "Debug stats.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/api-keys/validate": {
      "get": {
        "tags": ["Account"],
        "operationId": "validateApiKey",
        "summary": "Validate an API key",
        "description": "Verify that a key is active and report its tier and remaining credits.",
        "responses": {
          "200": {
            "description": "Validation result.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/exchange/orderbook": {
      "get": {
        "tags": ["Exchange"],
        "operationId": "getExchangeOrderbook",
        "summary": "Hyperliquid perpetual futures live book",
        "description": "Live L2 book for one of the supported Hyperliquid perpetuals.",
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": true,
            "schema": { "type": "string", "enum": ["BTC", "ETH", "SOL", "XRP"] }
          }
        ],
        "responses": {
          "200": {
            "description": "Live exchange orderbook.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/exchange/snapshots": {
      "get": {
        "tags": ["Exchange"],
        "operationId": "listExchangeSnapshots",
        "summary": "Hyperliquid historical snapshots",
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": true,
            "schema": { "type": "string", "enum": ["BTC", "ETH", "SOL", "XRP"] }
          },
          { "$ref": "#/components/parameters/From" },
          { "$ref": "#/components/parameters/To" },
          { "$ref": "#/components/parameters/Limit" }
        ],
        "responses": {
          "200": {
            "description": "Snapshot array.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/api-keys": {
      "get": {
        "tags": ["Account"],
        "operationId": "listApiKeys",
        "summary": "List your API keys",
        "description": "Requires a Clerk session (browser-only) — not callable with an `rm_` key.",
        "security": [],
        "responses": {
          "200": {
            "description": "Keys with previews and usage stats.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          }
        }
      },
      "post": {
        "tags": ["Account"],
        "operationId": "createApiKey",
        "summary": "Generate a new API key",
        "description": "Requires a Clerk session. Plaintext key is returned once and never again.",
        "security": [],
        "responses": {
          "201": {
            "description": "Newly created key.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          }
        }
      }
    },
    "/v1/api-keys/{key_id}": {
      "delete": {
        "tags": ["Account"],
        "operationId": "revokeApiKey",
        "summary": "Revoke an API key",
        "description": "Requires a Clerk session.",
        "security": [],
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "204": { "description": "Key revoked." }
        }
      }
    },
    "/v1/user/tier": {
      "get": {
        "tags": ["Account"],
        "operationId": "getUserTier",
        "summary": "Current tier and credits",
        "description": "Requires a Clerk session.",
        "security": [],
        "responses": {
          "200": {
            "description": "Tier and credit info.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          }
        }
      }
    },
    "/v1/payments/create-invoice": {
      "post": {
        "tags": ["Account"],
        "operationId": "createInvoice",
        "summary": "Create a NOWPayments crypto invoice",
        "description": "Requires a Clerk session.",
        "security": [],
        "responses": {
          "200": {
            "description": "Invoice details.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          }
        }
      }
    }
  }
}
