{
  "externalDocs": {
    "description": "The same thing in prose.",
    "url": "https://www.carryroom.com/api"
  },
  "info": {
    "description": "Read-only. No key and no sign-up.\n\nTHROTTLING (free, which is the only plan in this release): at most ONE call PER SECOND, and at most 60 calls per 5 minutes. Counted per API key, or — with no key — per client IP address. Going over gives 429 with Retry-After (in seconds), a `limits` object stating the rule, and `bulk_endpoint`. Waiting the seconds in Retry-After and repeating the same call always works: refused calls are not counted against you.\n\nFetching one symbol at a time is ALSO refused by shape once it looks like a sweep, even while inside those numbers. Ask /api/v1/latest once instead.\n\nEvery path also exists under a /ja and /zh prefix, which only changes the language of the prose fields.\n\nAn agent skill (what the numbers mean and how to add them up without getting the sign wrong) is at https://www.carryroom.com/skills/carryroom/SKILL.md .\n\nOn the rate endpoints the only query parameter is ?venues= . Anything else is ignored SILENTLY there, so ?venue=  (singular), ?symbol= and ?limit= return the whole response. /api/v1/events takes ?kind=, ?since_ms= and ?limit=.",
    "license": {
      "name": "Data from each exchange's own public API"
    },
    "summary": "Perpetual futures funding rates and cross-exchange carry, as JSON.",
    "title": "carryroom",
    "version": "v1"
  },
  "openapi": "3.1.0",
  "paths": {
    "/api/v1": {
      "get": {
        "description": "Lists every endpoint, live or not, with the units every numeric field is in.",
        "operationId": "getIndex",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "description": "OK"
          }
        },
        "summary": "Index of the endpoints in this release"
      }
    },
    "/api/v1/carry": {
      "get": {
        "description": "Sell one exchange, buy another, same underlying. Rows with too little history are returned with evaluable=false rather than dropped. ?venues= keeps only pairs whose BOTH legs are in the set, so a single exchange usually returns nothing.",
        "operationId": "getCarry",
        "parameters": [
          {
            "description": "Comma-separated exchange slugs. Omit for the default set. A slug that is not recognised is REPORTED in unreadable_venue_tokens and otherwise IGNORED, so a typo returns the unfiltered response rather than an empty one — check that field before trusting row_count. Naming an exchange explicitly also un-hides the few that are withheld from the default response.",
            "in": "query",
            "name": "venues",
            "required": false,
            "schema": {
              "examples": [
                "hyperliquid,bybit"
              ],
              "type": "string"
            },
            "x-known-values": [
              "bitget",
              "hyperliquid",
              "hl_hip3",
              "aster",
              "edgex2",
              "kucoin",
              "bingx",
              "dydx",
              "extended",
              "derive_perp",
              "lighter",
              "variational",
              "gmx",
              "grvt",
              "apex_omni",
              "pacifica",
              "vest",
              "antarctic",
              "mexc",
              "backpack",
              "evedex",
              "sunx",
              "binance_perp",
              "okx",
              "paradex",
              "aevo",
              "reya",
              "woofi",
              "coinw",
              "btcc",
              "txflow",
              "gate",
              "bybit",
              "risex",
              "ondo",
              "hibachi",
              "gmtrade",
              "nado",
              "decibel",
              "sodex",
              "perpl",
              "standx",
              "qfex",
              "htx",
              "kraken_futures",
              "crypto_com",
              "lighter_rh",
              "arcus",
              "deribit_perp"
            ]
          },
          {
            "description": "Keep one coin, related tickers included: XAUT, PAXG and GOLD all mean XAU; 1000PEPE and kPEPE mean PEPE; XBT means BTC. Letters, digits and : . _ - only. A value that cannot be read is REPORTED in unreadable_coin and the response is NOT filtered — check that field before trusting row_count.",
            "in": "query",
            "name": "coin",
            "required": false,
            "schema": {
              "examples": [
                "XAU"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "api_version": {
                      "type": "string"
                    },
                    "coin": {
                      "description": "the coin the rows were kept to, after folding related tickers (null = every coin).",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "documentation_url": {
                      "type": "string"
                    },
                    "generated_at_ms": {
                      "description": "when this response was built (epoch ms, UTC).",
                      "type": "integer"
                    },
                    "generated_at_utc": {
                      "type": "string"
                    },
                    "key_required": {
                      "type": "boolean"
                    },
                    "language": {
                      "description": "en / ja / zh-Hans, from the URL prefix.",
                      "type": "string"
                    },
                    "matched_count": {
                      "description": "rows that matched before any cap.",
                      "type": "integer"
                    },
                    "plan": {
                      "description": "\"free\". There is no key and no paid tier in this release.",
                      "type": "string"
                    },
                    "row_count": {
                      "type": "integer"
                    },
                    "rows": {
                      "items": {
                        "additionalProperties": true,
                        "properties": {
                          "breakeven_days": {
                            "description": "days for the carry to earn round_trip_cost_bps back.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "buy_leg_api_url": {
                            "description": "path of that leg's own /api/v1/latest endpoint.",
                            "type": "string"
                          },
                          "buy_symbol": {
                            "description": "that leg's own symbol on its exchange.",
                            "type": "string"
                          },
                          "buy_venue": {
                            "description": "exchange slug of that leg.",
                            "type": "string"
                          },
                          "buy_venue_name": {
                            "description": "exchange name of that leg.",
                            "type": "string"
                          },
                          "canonical": {
                            "description": "the underlying coin with any scale prefix removed (1000PEPE -> PEPE). Join on this across exchanges.",
                            "type": "string"
                          },
                          "convergence_days": {
                            "description": "days over which the two legs' prices have converged historically.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "detail_url": {
                            "description": "path of the human-readable page for this row.",
                            "type": "string"
                          },
                          "evaluable": {
                            "description": "false when the pair has less history than the stability windows need. Such rows are still returned; they are not scored.",
                            "type": "boolean"
                          },
                          "expected_net_30d_bps": {
                            "description": "basis points over 30 days implied by the current gap, after the same costs.",
                            "type": "number"
                          },
                          "giveback_ratio": {
                            "description": "share of the gross carry given back to price convergence.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "min_oi_usd": {
                            "description": "open interest in USD of the thinner of the two legs.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "min_vol24h_usd": {
                            "description": "24h volume in USD of the thinner of the two legs.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "observed_days": {
                            "description": "days of history behind this row.",
                            "type": "number"
                          },
                          "rank": {
                            "description": "position in this response's ordering. Null when the row is not scored.",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "realised_apy_pct": {
                            "description": "percent per year from settlements that actually happened over the last 30 days (the whole observed period when shorter), after borrowing interest — the same figure as the realised annual rate on the pair page. Not a forecast.",
                            "type": "number"
                          },
                          "round_trip_cost_bps": {
                            "description": "basis points to open and close both legs.",
                            "type": "number"
                          },
                          "sell_leg_api_url": {
                            "description": "path of that leg's own /api/v1/latest endpoint.",
                            "type": "string"
                          },
                          "sell_symbol": {
                            "description": "that leg's own symbol on its exchange.",
                            "type": "string"
                          },
                          "sell_venue": {
                            "description": "exchange slug of that leg.",
                            "type": "string"
                          },
                          "sell_venue_name": {
                            "description": "exchange name of that leg.",
                            "type": "string"
                          },
                          "settled_count": {
                            "description": "number of realised funding settlements counted.",
                            "type": "integer"
                          }
                        },
                        "required": [
                          "canonical",
                          "sell_venue",
                          "sell_venue_name",
                          "sell_symbol",
                          "sell_leg_api_url",
                          "buy_venue",
                          "buy_venue_name",
                          "buy_symbol",
                          "buy_leg_api_url",
                          "detail_url",
                          "evaluable",
                          "observed_days",
                          "settled_count",
                          "realised_apy_pct",
                          "expected_net_30d_bps",
                          "round_trip_cost_bps",
                          "rank",
                          "breakeven_days",
                          "convergence_days",
                          "giveback_ratio",
                          "min_oi_usd",
                          "min_vol24h_usd"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "skill_url": {
                      "description": "the agent skill served by this site.",
                      "type": "string"
                    },
                    "surface": {
                      "type": "string"
                    },
                    "truncated": {
                      "type": "boolean"
                    },
                    "unreadable_coin": {
                      "description": "?coin= value that could not be read. NON-NULL MEANS THE COIN FILTER DID NOT APPLY.",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "unreadable_venue_tokens": {
                      "description": "slugs in ?venues= that were not recognised. NON-EMPTY MEANS THE FILTER DID NOT APPLY.",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "withheld": {
                      "description": "counts of rows kept out, by reason.",
                      "type": "object"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "OK"
          }
        },
        "summary": "Cross-exchange pairs ranked by realised carry"
      }
    },
    "/api/v1/events": {
      "get": {
        "description": "The same list /news shows (last 14 days), newest first. Re-read within 5 seconds of an event being written. For a push instead of polling, open the stream at /api/v1/events/stream.",
        "operationId": "getEvents",
        "parameters": [
          {
            "description": "comma-separated kinds (announcement, peg_move, dislocation, options_daily) or dislocation types (price_gap, funding_gap, lst_move, wrapper_gap, pool_gap, fxstable_gap, oracle_gap). Unknown tokens are reported in unreadable_kind_tokens and otherwise ignored.",
            "in": "query",
            "name": "kind",
            "required": false,
            "schema": {
              "examples": [
                "pool_gap,oracle_gap"
              ],
              "type": "string"
            }
          },
          {
            "description": "keep rows with at_ms greater than this (epoch ms). Announcements carry the exchange's own publication time, so poll with an overlap and de-duplicate by id.",
            "in": "query",
            "name": "since_ms",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "rows to return, default 100, at most 500.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "description": "return only this event (row_count 0 once it has left the 14-day window).",
            "in": "query",
            "name": "id",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "api_version": {
                      "type": "string"
                    },
                    "documentation_url": {
                      "type": "string"
                    },
                    "generated_at_ms": {
                      "description": "when this response was built (epoch ms, UTC).",
                      "type": "integer"
                    },
                    "generated_at_utc": {
                      "type": "string"
                    },
                    "key_required": {
                      "type": "boolean"
                    },
                    "language": {
                      "description": "en / ja / zh-Hans, from the URL prefix.",
                      "type": "string"
                    },
                    "matched_count": {
                      "description": "rows that matched before any cap.",
                      "type": "integer"
                    },
                    "meta": {
                      "description": "units of every number in data, the kinds, and how fresh the list is.",
                      "type": "object"
                    },
                    "plan": {
                      "description": "\"free\". There is no key and no paid tier in this release.",
                      "type": "string"
                    },
                    "refreshed_at_ms": {
                      "description": "when the list was last checked for new events.",
                      "type": "integer"
                    },
                    "row_count": {
                      "type": "integer"
                    },
                    "rows": {
                      "items": {
                        "additionalProperties": true,
                        "properties": {
                          "at_ms": {
                            "description": "epoch milliseconds UTC when the site recorded the event. For announcements it is the exchange's own publication time.",
                            "type": "integer"
                          },
                          "at_utc": {
                            "description": "at_ms as RFC 3339.",
                            "type": "string"
                          },
                          "data": {
                            "description": "the numbers of the event. Field names carry their unit (…_pct, …_pct_per_year); meta.units explains each.",
                            "type": "object"
                          },
                          "detail_url": {
                            "description": "path of the human-readable page for this row.",
                            "type": "string"
                          },
                          "id": {
                            "description": "stable id of the event; the same event always has the same id (also the SSE `id:`). De-duplicate on this.",
                            "type": "string"
                          },
                          "kind": {
                            "description": "announcement / peg_move / dislocation / options_daily.",
                            "type": "string"
                          },
                          "subject": {
                            "description": "what the event is about: a coin, a pair, or an exchange.",
                            "type": "string"
                          },
                          "summary": {
                            "description": "one line in the language of the URL — the same text /news shows.",
                            "type": "string"
                          },
                          "type": {
                            "description": "for a dislocation, which gap it is (price_gap, funding_gap, lst_move, wrapper_gap, pool_gap, fxstable_gap, oracle_gap); otherwise the same as kind.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "kind",
                          "type",
                          "at_ms",
                          "at_utc",
                          "subject",
                          "summary",
                          "detail_url",
                          "data"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "skill_url": {
                      "description": "the agent skill served by this site.",
                      "type": "string"
                    },
                    "stream_url": {
                      "type": "string"
                    },
                    "surface": {
                      "type": "string"
                    },
                    "truncated": {
                      "type": "boolean"
                    },
                    "unreadable_kind_tokens": {
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "unreadable_venue_tokens": {
                      "description": "slugs in ?venues= that were not recognised. NON-EMPTY MEANS THE FILTER DID NOT APPLY.",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "window_days": {
                      "type": "integer"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "OK"
          }
        },
        "summary": "Events: exchange notices, stablecoin peg moves, gaps between venues and pools"
      }
    },
    "/api/v1/events/stream": {
      "get": {
        "description": "Opens a text/event-stream. First an `event: ready` with the heartbeat and retry settings, then one SSE message per NEW event: `id:` is the event id, `event:` its kind, `data:` the same JSON row as /api/v1/events. A comment line (`:ping`) every 20 seconds keeps proxies from closing the connection. On reconnect, send Last-Event-ID (or ?last_event_id=) to get what you missed; if that id is no longer known you get `event: gap` and should call /api/v1/events to catch up. At most 4 open streams per client and 200 in total (503 with Retry-After beyond that). A stream is closed after 3600 seconds; reconnect with Last-Event-ID (a standard EventSource does this by itself).",
        "operationId": "streamEvents",
        "parameters": [
          {
            "description": "same as /api/v1/events.",
            "in": "query",
            "name": "kind",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "resume after this event id (for clients that cannot set the Last-Event-ID header).",
            "in": "query",
            "name": "last_event_id",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Last-Event-ID",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "an open event stream"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "description": "too many open streams"
          }
        },
        "summary": "Push of new events as Server-Sent Events"
      }
    },
    "/api/v1/history": {
      "get": {
        "deprecated": false,
        "description": "Planned for the next release. Until then this path answers 501 with a notice; it never answers with an empty list, so an empty result from this site always means \"no rows\", never \"not implemented\".",
        "operationId": "getHistory",
        "responses": {
          "501": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "description": "Not implemented yet"
          }
        },
        "summary": "Rate history — NOT BUILT YET",
        "x-status": "not_yet"
      }
    },
    "/api/v1/latest": {
      "get": {
        "description": "One row per (exchange, contract) from the most recent snapshot. A few exchanges are withheld from the default response; name them in ?venues= to include them.",
        "operationId": "getLatest",
        "parameters": [
          {
            "description": "Comma-separated exchange slugs. Omit for the default set. A slug that is not recognised is REPORTED in unreadable_venue_tokens and otherwise IGNORED, so a typo returns the unfiltered response rather than an empty one — check that field before trusting row_count. Naming an exchange explicitly also un-hides the few that are withheld from the default response.",
            "in": "query",
            "name": "venues",
            "required": false,
            "schema": {
              "examples": [
                "hyperliquid,bybit"
              ],
              "type": "string"
            },
            "x-known-values": [
              "bitget",
              "hyperliquid",
              "hl_hip3",
              "aster",
              "edgex2",
              "kucoin",
              "bingx",
              "dydx",
              "extended",
              "derive_perp",
              "lighter",
              "variational",
              "gmx",
              "grvt",
              "apex_omni",
              "pacifica",
              "vest",
              "antarctic",
              "mexc",
              "backpack",
              "evedex",
              "sunx",
              "binance_perp",
              "okx",
              "paradex",
              "aevo",
              "reya",
              "woofi",
              "coinw",
              "btcc",
              "txflow",
              "gate",
              "bybit",
              "risex",
              "ondo",
              "hibachi",
              "gmtrade",
              "nado",
              "decibel",
              "sodex",
              "perpl",
              "standx",
              "qfex",
              "htx",
              "kraken_futures",
              "crypto_com",
              "lighter_rh",
              "arcus",
              "deribit_perp"
            ]
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "api_version": {
                      "type": "string"
                    },
                    "documentation_url": {
                      "type": "string"
                    },
                    "generated_at_ms": {
                      "description": "when this response was built (epoch ms, UTC).",
                      "type": "integer"
                    },
                    "generated_at_utc": {
                      "type": "string"
                    },
                    "key_required": {
                      "type": "boolean"
                    },
                    "language": {
                      "description": "en / ja / zh-Hans, from the URL prefix.",
                      "type": "string"
                    },
                    "matched_count": {
                      "description": "rows that matched before any cap.",
                      "type": "integer"
                    },
                    "meta": {
                      "description": "units, coverage, and what this release does not return.",
                      "type": "object"
                    },
                    "plan": {
                      "description": "\"free\". There is no key and no paid tier in this release.",
                      "type": "string"
                    },
                    "row_count": {
                      "type": "integer"
                    },
                    "rows": {
                      "items": {
                        "additionalProperties": true,
                        "properties": {
                          "api_url": {
                            "description": "path of this row's own endpoint.",
                            "type": "string"
                          },
                          "canonical": {
                            "description": "the underlying coin with any scale prefix removed (1000PEPE -> PEPE). Join on this across exchanges.",
                            "type": "string"
                          },
                          "carry_model": {
                            "description": "\"symmetric\" when one rate applies to both sides; \"directional\" when the exchange quotes each side separately (then funding_return_8h_long/short are present instead of funding_rate_8h).",
                            "type": "string"
                          },
                          "contract_scale": {
                            "description": "coins per contract baked into the venue symbol (1000PEPE = 1000).",
                            "type": "number"
                          },
                          "detail_url": {
                            "description": "path of the human-readable page for this row.",
                            "type": "string"
                          },
                          "expires_at_ms": {
                            "description": "epoch milliseconds, UTC. Null for a perpetual.",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "funding_interval_h": {
                            "description": "hours between the venue's own funding settlements.",
                            "type": "number"
                          },
                          "funding_rate_8h": {
                            "description": "fraction of position notional per 8 hours (0.0001 = 1 basis point). Already normalised from the venue's own settlement interval.",
                            "type": "number"
                          },
                          "funding_rate_annualised_pct": {
                            "description": "percent per year, simple (funding_rate_8h x 3 x 365 x 100). No compounding.",
                            "type": "number"
                          },
                          "funding_return_8h_long": {
                            "description": "fraction per 8 hours received (+) or paid (-) while holding this leg LONG. Only on venues that quote each side separately.",
                            "type": "number"
                          },
                          "funding_return_8h_short": {
                            "description": "fraction per 8 hours received (+) or paid (-) while holding this leg SHORT. Only on venues that quote each side separately.",
                            "type": "number"
                          },
                          "instrument": {
                            "description": "\"perp\" for a perpetual, \"dated\" for a contract with an expiry.",
                            "type": "string"
                          },
                          "mark_price_scaled": {
                            "description": "the venue's mark price in the contract's own units. Divide by contract_scale for the price of one coin.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "settlement": {
                            "description": "what the contract settles in: usdt / usdc / usd / coin_m.",
                            "type": "string"
                          },
                          "symbol": {
                            "description": "the exchange's own symbol for the contract.",
                            "type": "string"
                          },
                          "venue": {
                            "description": "exchange slug, as used in the ?venues= filter.",
                            "type": "string"
                          },
                          "venue_name": {
                            "description": "exchange name as displayed.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "venue",
                          "venue_name",
                          "symbol",
                          "canonical",
                          "instrument",
                          "settlement",
                          "carry_model",
                          "funding_interval_h",
                          "contract_scale",
                          "api_url",
                          "detail_url",
                          "mark_price_scaled",
                          "expires_at_ms"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "skill_url": {
                      "description": "the agent skill served by this site.",
                      "type": "string"
                    },
                    "surface": {
                      "type": "string"
                    },
                    "truncated": {
                      "type": "boolean"
                    },
                    "unreadable_venue_tokens": {
                      "description": "slugs in ?venues= that were not recognised. NON-EMPTY MEANS THE FILTER DID NOT APPLY.",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "OK"
          }
        },
        "summary": "Latest funding rate and price for every contract"
      }
    },
    "/api/v1/latest/{venue}/{symbol}": {
      "get": {
        "description": "The same row as /api/v1/latest, for a single contract. Do NOT loop this to build a board — ask for /api/v1/latest once instead.",
        "operationId": "getLatestOne",
        "parameters": [
          {
            "in": "path",
            "name": "venue",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "symbol",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "api_version": {
                      "type": "string"
                    },
                    "documentation_url": {
                      "type": "string"
                    },
                    "generated_at_ms": {
                      "description": "when this response was built (epoch ms, UTC).",
                      "type": "integer"
                    },
                    "generated_at_utc": {
                      "type": "string"
                    },
                    "key_required": {
                      "type": "boolean"
                    },
                    "language": {
                      "description": "en / ja / zh-Hans, from the URL prefix.",
                      "type": "string"
                    },
                    "matched_count": {
                      "description": "rows that matched before any cap.",
                      "type": "integer"
                    },
                    "plan": {
                      "description": "\"free\". There is no key and no paid tier in this release.",
                      "type": "string"
                    },
                    "row_count": {
                      "type": "integer"
                    },
                    "rows": {
                      "items": {
                        "additionalProperties": true,
                        "properties": {
                          "api_url": {
                            "description": "path of this row's own endpoint.",
                            "type": "string"
                          },
                          "canonical": {
                            "description": "the underlying coin with any scale prefix removed (1000PEPE -> PEPE). Join on this across exchanges.",
                            "type": "string"
                          },
                          "carry_model": {
                            "description": "\"symmetric\" when one rate applies to both sides; \"directional\" when the exchange quotes each side separately (then funding_return_8h_long/short are present instead of funding_rate_8h).",
                            "type": "string"
                          },
                          "contract_scale": {
                            "description": "coins per contract baked into the venue symbol (1000PEPE = 1000).",
                            "type": "number"
                          },
                          "detail_url": {
                            "description": "path of the human-readable page for this row.",
                            "type": "string"
                          },
                          "expires_at_ms": {
                            "description": "epoch milliseconds, UTC. Null for a perpetual.",
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "funding_interval_h": {
                            "description": "hours between the venue's own funding settlements.",
                            "type": "number"
                          },
                          "funding_rate_8h": {
                            "description": "fraction of position notional per 8 hours (0.0001 = 1 basis point). Already normalised from the venue's own settlement interval.",
                            "type": "number"
                          },
                          "funding_rate_annualised_pct": {
                            "description": "percent per year, simple (funding_rate_8h x 3 x 365 x 100). No compounding.",
                            "type": "number"
                          },
                          "funding_return_8h_long": {
                            "description": "fraction per 8 hours received (+) or paid (-) while holding this leg LONG. Only on venues that quote each side separately.",
                            "type": "number"
                          },
                          "funding_return_8h_short": {
                            "description": "fraction per 8 hours received (+) or paid (-) while holding this leg SHORT. Only on venues that quote each side separately.",
                            "type": "number"
                          },
                          "instrument": {
                            "description": "\"perp\" for a perpetual, \"dated\" for a contract with an expiry.",
                            "type": "string"
                          },
                          "mark_price_scaled": {
                            "description": "the venue's mark price in the contract's own units. Divide by contract_scale for the price of one coin.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "settlement": {
                            "description": "what the contract settles in: usdt / usdc / usd / coin_m.",
                            "type": "string"
                          },
                          "symbol": {
                            "description": "the exchange's own symbol for the contract.",
                            "type": "string"
                          },
                          "venue": {
                            "description": "exchange slug, as used in the ?venues= filter.",
                            "type": "string"
                          },
                          "venue_name": {
                            "description": "exchange name as displayed.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "venue",
                          "venue_name",
                          "symbol",
                          "canonical",
                          "instrument",
                          "settlement",
                          "carry_model",
                          "funding_interval_h",
                          "contract_scale",
                          "api_url",
                          "detail_url",
                          "mark_price_scaled",
                          "expires_at_ms"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "skill_url": {
                      "description": "the agent skill served by this site.",
                      "type": "string"
                    },
                    "surface": {
                      "type": "string"
                    },
                    "truncated": {
                      "type": "boolean"
                    },
                    "unreadable_venue_tokens": {
                      "description": "slugs in ?venues= that were not recognised. NON-EMPTY MEANS THE FILTER DID NOT APPLY.",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "OK"
          }
        },
        "summary": "Latest row for one contract"
      }
    },
    "/api/v1/venues": {
      "get": {
        "description": "Does NOT honour ?venues=; it always lists every exchange the site shows.",
        "operationId": "getVenues",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "api_version": {
                      "type": "string"
                    },
                    "documentation_url": {
                      "type": "string"
                    },
                    "generated_at_ms": {
                      "description": "when this response was built (epoch ms, UTC).",
                      "type": "integer"
                    },
                    "generated_at_utc": {
                      "type": "string"
                    },
                    "key_required": {
                      "type": "boolean"
                    },
                    "language": {
                      "description": "en / ja / zh-Hans, from the URL prefix.",
                      "type": "string"
                    },
                    "matched_count": {
                      "description": "rows that matched before any cap.",
                      "type": "integer"
                    },
                    "plan": {
                      "description": "\"free\". There is no key and no paid tier in this release.",
                      "type": "string"
                    },
                    "row_count": {
                      "type": "integer"
                    },
                    "rows": {
                      "items": {
                        "additionalProperties": true,
                        "properties": {
                          "in_default_response": {
                            "description": "whether /api/v1/latest returns this exchange WITHOUT ?venues=. False means the rows exist (in_latest_snapshot can still be true) but are held back from the default response; name the exchange in ?venues= to get them. This is the one place the two endpoints would otherwise disagree.",
                            "type": "boolean"
                          },
                          "in_latest_snapshot": {
                            "description": "whether this exchange has rows in the most recent snapshot, counting every exchange.",
                            "type": "boolean"
                          },
                          "symbols_in_latest_snapshot": {
                            "description": "how many of this exchange's contracts are in that snapshot.",
                            "type": "integer"
                          },
                          "venue": {
                            "description": "exchange slug, as used in the ?venues= filter.",
                            "type": "string"
                          },
                          "venue_name": {
                            "description": "exchange name as displayed.",
                            "type": "string"
                          }
                        },
                        "required": [
                          "venue",
                          "venue_name",
                          "in_latest_snapshot",
                          "in_default_response",
                          "symbols_in_latest_snapshot"
                        ],
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "skill_url": {
                      "description": "the agent skill served by this site.",
                      "type": "string"
                    },
                    "surface": {
                      "type": "string"
                    },
                    "truncated": {
                      "type": "boolean"
                    },
                    "unreadable_venue_tokens": {
                      "description": "slugs in ?venues= that were not recognised. NON-EMPTY MEANS THE FILTER DID NOT APPLY.",
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "OK"
          }
        },
        "summary": "Exchanges, and how many contracts each has in the latest snapshot"
      }
    }
  },
  "servers": [
    {
      "url": "https://www.carryroom.com"
    }
  ]
}