{
 "openapi": "3.0.3",
 "info": {
  "title": "Bitcoin Arena node API",
  "version": "2026-11-01",
  "description": "Every request a Bitcoin Arena node (`arena-node`) answers, generated from `packages/arena-node/src/server.js` by `src/website/docs/gen-docs.py`. Concepts and guides: https://docs.bitcoinarena.io/"
 },
 "servers": [
  {
   "url": "https://tn4.bitcoin-arena.io/guardian-1",
   "description": "testnet4 federation A, seat 1"
  },
  {
   "url": "https://tn4.bitcoin-arena.io/guardian-2",
   "description": "testnet4 federation A, seat 2"
  },
  {
   "url": "https://tn4.bitcoin-arena.io/guardian-3",
   "description": "testnet4 federation A, seat 3"
  },
  {
   "url": "https://tn4.bitcoin-arena.io/guardian-4",
   "description": "testnet4 federation A, seat 4"
  },
  {
   "url": "https://tn4.bitcoin-arena.io/guardian-5",
   "description": "testnet4 federation A, seat 5"
  },
  {
   "url": "https://tn4.bitcoin-arena.io/guardian-6",
   "description": "testnet4 federation A, seat 6"
  },
  {
   "url": "https://tn4.bitcoin-arena.io/guardian-7",
   "description": "testnet4 federation A, seat 7"
  },
  {
   "url": "https://tn4.bitcoin-arena.io/fed2-1",
   "description": "testnet4 federation B, seat 1"
  },
  {
   "url": "https://tn4.bitcoin-arena.io/fed2-2",
   "description": "testnet4 federation B, seat 2"
  },
  {
   "url": "https://tn4.bitcoin-arena.io/fed2-3",
   "description": "testnet4 federation B, seat 3"
  },
  {
   "url": "https://tn4.bitcoin-arena.io/fed2-4",
   "description": "testnet4 federation B, seat 4"
  },
  {
   "url": "https://tn4.bitcoin-arena.io/fed2-5",
   "description": "testnet4 federation B, seat 5"
  },
  {
   "url": "https://tn4.bitcoin-arena.io/fed2-6",
   "description": "testnet4 federation B, seat 6"
  },
  {
   "url": "https://tn4.bitcoin-arena.io/fed2-7",
   "description": "testnet4 federation B, seat 7"
  }
 ],
 "tags": [
  {
   "name": "Builders",
   "description": "List your game, read its rounds, follow results and, for a market, report the outcome."
  },
  {
   "name": "Players",
   "description": "What the game page uses: the lobby, joining, stake locks, winnings, leaderboards and results."
  },
  {
   "name": "Operators",
   "description": "The dashboard, the owner area, operator tokens, the census and the node's health."
  },
  {
   "name": "Nodes",
   "description": "Signing ceremonies, shares and gossip between the nodes of a committee. You do not call these yourself; they are listed so nothing is hidden."
  }
 ],
 "components": {
  "securitySchemes": {
   "operatorToken": {
    "type": "http",
    "scheme": "bearer",
    "description": "An operator token minted in the owner area (POST /owner/operator/mint)."
   }
  }
 },
 "paths": {
  "/absence": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Hand over an absence attestation",
    "description": "Hands over a signed attestation that a guardian peer is absent.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: signature by the attester\n\nReturns: 201 (kept) / 200 JSON {ok, kept}; 400/422\n\nSource: `packages/arena-node/src/server.js` line 6034.",
    "operationId": "post_absence",
    "requestBody": {
     "required": true,
     "description": "Absence attestation: encoding + signature, hex.",
     "content": {
      "text/plain": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "{ok, kept}.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Held already.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "422": {
      "description": "Does not stand.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/absences": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Absences and departures held",
    "description": "Absence attestations and departure notices this seat holds.\n\nAccess: none\n\nReturns: 200 JSON {node, absences[], departures[]} (hex)\n\nSource: `packages/arena-node/src/server.js` line 6039.",
    "operationId": "get_absences",
    "parameters": [
     {
      "name": "federation",
      "in": "query",
      "required": false,
      "description": "Federation id, 64 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{node, absences[], departures[]}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/address-announcement": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Take a node's address announcement",
    "description": "A node's signed off-chain address announcement (address-book.js, spec \u00a725): where it is reached now, newer than its advertisement; refused when dated over 10 min ahead.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: the announcement is signed by the node key it names\n\nReturns: 200 {ok, ...} when kept; 400 with why\n\nSource: `packages/arena-node/src/server.js` line 8137.",
    "operationId": "post_address_announcement",
    "requestBody": {
     "required": true,
     "description": "{ node, endpoint, atMs, sig } signed by the node key.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "Kept.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not a valid announcement, with why.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/address-announcements": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "The address announcements this seat holds",
    "description": "Every address announcement this seat holds: where the nodes it knows are reached now.\n\nAccess: none\n\nReturns: 200 {announcements}\n\nSource: `packages/arena-node/src/server.js` line 8142.",
    "operationId": "get_address_announcements",
    "responses": {
     "200": {
      "description": "{announcements:[{node, endpoint, atMs, sig}]}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/api/round-result": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Players, outcomes and winnings of a round",
    "description": "Who played a round, their signed outcome/score and what they won or lost.\n\nAccess: none\n\nReturns: 200 JSON {id, state, free (development rounds only), players:[{entry, player, name, stakeMsat, outcome, score, signedBy, wonMsat, winningsState, ...balance}], match (head-to-head record or null)}; 400/404\n\nSource: `packages/arena-node/src/server.js` line 4258.",
    "operationId": "get_api_round_result",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{id, state, free, players[], match}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/api/rounds": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Upcoming and finished rounds",
    "description": "Upcoming and finished rounds of hosted games, with times, committee, game and outcome.\n\nAccess: none\n\nReturns: 200 JSON {node, nowMs, upcoming[] (rows as /rounds, with event for a template round), finished[] (up to 200), games}\n\nSource: `packages/arena-node/src/server.js` line 4225.",
    "operationId": "get_api_rounds",
    "parameters": [
     {
      "name": "ahead",
      "in": "query",
      "required": false,
      "description": "Only rounds starting within this many ms, or hours with an h suffix (e.g. 72h).",
      "schema": {
       "type": "string"
      },
      "example": "72h"
     },
     {
      "name": "next",
      "in": "query",
      "required": false,
      "description": "At most this many upcoming rounds per series.",
      "schema": {
       "type": "integer"
      },
      "example": 8
     }
    ],
    "responses": {
     "200": {
      "description": "{node, nowMs, upcoming[], finished[] (up to 200), games}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/attestation-word": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "A drawn seat's attestation word",
    "description": "What this drawn seat signed for a round, for the round's other drawn attestors to combine (kanban #630).\n\nAccess: none\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 8350.",
    "operationId": "get_attestation_word",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "round id, 64 hex",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/badge-definitions": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Badge definitions (NIP-58)",
    "description": "The node's signed NIP-58 Badge Definition events (kind 30009), one per catalogue badge: first win, five rounds, perfect run, leaderboard top 3.\n\nAccess: none\n\nReturns: 200 JSON {node, on, version, definitions[{event, publishedMs}]}\n\nSource: `packages/arena-node/src/server.js` line 4503.",
    "operationId": "get_badge_definitions",
    "responses": {
     "200": {
      "description": "The definitions, in catalogue order.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/badge-image/{file}": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "A badge's image",
    "description": "A badge's image, as its definition's image tag names it under the node's public base.\n\nAccess: none\n\nReturns: 200 image/svg+xml; 404\n\nSource: `packages/arena-node/src/server.js` line 4517.",
    "operationId": "get_badge_image_file",
    "parameters": [
     {
      "name": "file",
      "in": "path",
      "required": true,
      "description": "The badge's d and .svg, e.g. arena-first-win.svg.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The badge's SVG.",
      "content": {
       "image/svg+xml": {}
      }
     },
     "404": {
      "description": "No such badge image.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/badges": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "A player's badges (NIP-58)",
    "description": "The NIP-58 badges this node awarded to one player identity: the kind-8 award events and their kind-30009 definitions, exactly as signed, so a client can check ids and signatures itself. Each award names the round ids or the board week that earned it. A week's place also names how many nodes the network board was merged from and the 3 that had to agree on a round. on=false: the node awards no badges (ARENA_NOSTR_BADGES unset).\n\nAccess: none\n\nReturns: 200 JSON {node, player, on, awards[{d, game, scope, evidence, event, awardedMs, publishedMs}], definitions[{event, publishedMs}]}; 400\n\nSource: `packages/arena-node/src/server.js` line 4507.",
    "operationId": "get_badges",
    "parameters": [
     {
      "name": "player",
      "in": "query",
      "required": true,
      "description": "The player's identity key, 64 hex (an x-only Nostr key). A bare round key holds no badge.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The awards (oldest first) and the definitions they name.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not a 64-hex player key.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/batch": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Leader's set for batch k",
    "description": "The leader's set for batch k; this seat holds and signs it or refuses.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: BIP-340 signature by the batch's leader seat; orders must have verified locks here\n\nReturns: 201 JSON {ok, seat, signature, storedAtMs, fresh}; 200 when held already; 400/403/409\n\nSource: `packages/arena-node/src/server.js` line 5175.",
    "operationId": "post_batch",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "{k, orders, cancels, sells, leader, leaderSig}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "{ok, seat, signature, storedAtMs, fresh}.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Held already.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "403": {
      "description": "Leader signature does not verify.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/batch-certificate": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Hand over a certified batch",
    "description": "Hands over a certified batch; it is in the book from then on.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: threshold of the round's seats' signatures over the batch id\n\nReturns: 201 {ok, fresh:true}; 200 held already; 400/403/409\n\nSource: `packages/arena-node/src/server.js` line 5176.",
    "operationId": "post_batch_certificate",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "{record, sigs:[{seat, signature}]}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "{ok, fresh:true}.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Held already.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "403": {
      "description": "Signatures short of the threshold.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/batch-proposal": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Seat's proposal for batch k",
    "description": "This seat's unbatched orders, cancels and sells before batch k's cutoff (market order book).\n\nAccess: none\n\nReturns: 200 JSON {seat, k, orders[], cancels[], sells[], pending[]}; 400\n\nSource: `packages/arena-node/src/server.js` line 5159.",
    "operationId": "get_batch_proposal",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "k",
      "in": "query",
      "required": true,
      "description": "Batch number.",
      "schema": {
       "type": "integer"
      },
      "example": 0
     }
    ],
    "responses": {
     "200": {
      "description": "{seat, k, orders[], cancels[], sells[], pending[]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/batch-void": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Void batch k",
    "description": "Voids batch k; its orders wait for a later batch.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: enough seats' signed declines that the threshold cannot be reached\n\nReturns: 201/200 JSON result; 400/403/409\n\nSource: `packages/arena-node/src/server.js` line 5177.",
    "operationId": "post_batch_void",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "{k, declines:[{seat, signature}]}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "Void applied.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Held already.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "403": {
      "description": "Declines do not prove the void.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/batch-void-ask": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Ask a seat to sign or decline batch k",
    "description": "Asks this seat for its signature on batch k, else its signed decline (it never signs k after).\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none\n\nReturns: 201 JSON {ok, seat, signed, batchId} or {ok, seat, declined}; 400\n\nSource: `packages/arena-node/src/server.js` line 5179.",
    "operationId": "post_batch_void_ask",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "k",
      "in": "query",
      "required": true,
      "description": "Batch number.",
      "schema": {
       "type": "integer"
      },
      "example": 0
     }
    ],
    "responses": {
     "201": {
      "description": "{ok, seat, signed, batchId} or {ok, seat, declined}.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Same answer, held already.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/block-random": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Randomness from a block",
    "description": "Numbers drawn from the hash of a block that is deep enough, labelled with what they are for. Anyone with the chain can reproduce them.\n\nAccess: none\n\nReturns: 200 JSON {node, tip, depth, ...draw}; 400/409/503\n\nSource: `packages/arena-node/src/server.js` line 5317.",
    "operationId": "get_block_random",
    "parameters": [
     {
      "name": "height",
      "in": "query",
      "required": true,
      "description": "The block height.",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "label",
      "in": "query",
      "required": false,
      "description": "What the draw is for.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "n",
      "in": "query",
      "required": true,
      "description": "The range drawn from.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "count",
      "in": "query",
      "required": false,
      "description": "How many numbers, 1..1000.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{node, tip, depth, values...}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Bad parameters.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "That block is not deep enough yet.",
      "content": {
       "text/plain": {}
      }
     },
     "503": {
      "description": "This node reads no chain.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/bond": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Node bond proof",
    "description": "Serves this node's bond proof so a client can check it against headers.\n\nAccess: none\n\nReturns: 200 JSON bond proof (transaction + merkle branch); 404 if none\n\nSource: `packages/arena-node/src/server.js` line 3767.",
    "operationId": "get_bond",
    "responses": {
     "200": {
      "description": "Bond proof: transaction + merkle branch.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "No bond proof configured.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/book": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Market order book as cleared here",
    "description": "The market order book as this seat clears it, with every position.\n\nAccess: none\n\nReturns: 200 JSON {ok, batches[], refused, resting, pending, positions[]}; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5164.",
    "operationId": "get_book",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{ok, batches[], refused, resting, pending, positions[]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/book-certificates": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Certified batches of a market",
    "description": "Every certified batch of a market round, for a seat that missed one.\n\nAccess: none\n\nReturns: 200 JSON {certificates[]}; 400\n\nSource: `packages/arena-node/src/server.js` line 5163.",
    "operationId": "get_book_certificates",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{certificates[]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/cancel": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "[signed] Cancel a market order",
    "description": "A market player cancels an order before its round's entry close, at no cost: the entry leaves the round and its stake and fee locks come back at once (GET /forfeit, GET /forfeit?lock=fee). Post it to every seat.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: the entry's session key\n\nReturns: 201 JSON {cancelled:true, fresh:true}; 200 {cancelled:true, fresh:false} (held already); for an order-book order 202/200 {cancelled:false, inNextBatch:true, id} (takes effect in a batch); 400/403/404/409\n\nSource: `packages/arena-node/src/server.js` line 5193.",
    "operationId": "post_cancel",
    "parameters": [
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "64-byte Ed25519 signature of the entry's session key over cancelId(round, entry).",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "{cancelled:true, fresh:true}.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Held already; or an order-book order {cancelled:false, inNextBatch:true, id}.",
      "content": {
       "application/json": {}
      }
     },
     "202": {
      "description": "Order-book order: {cancelled:false, inNextBatch:true, id}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "403": {
      "description": "Not signed by the session key.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such entry or round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not a market, or entries closed.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/cancels": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Cancels held for a market round",
    "description": "Every cancel this seat holds for a market round; the other seats pull them before they settle.\n\nAccess: none\n\nReturns: 200 JSON {round, cancels:[{entry, signature}]}; 400/404\n\nSource: `packages/arena-node/src/server.js` line 5225.",
    "operationId": "get_cancels",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{round, cancels:[{entry, signature}]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/canonical": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Canonical transcript of a run",
    "description": "Returns the committee-carried canonical transcript of a run.\n\nAccess: none\n\nReturns: 200 octet-stream canonical transcript, headers x-transcript-hash, x-ticks, x-marks, x-dropped, x-through-tick; 409\n\nHeaders: `x-transcript-hash`, `x-ticks`, `x-marks`, `x-dropped`, `x-through-tick`\n\nSource: `packages/arena-node/src/server.js` line 4782.",
    "operationId": "get_canonical",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Canonical transcript.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/capacity": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Capacity pressure: bands, the bonds and peg-ins that relieve it",
    "description": "Capacity pressure (spec \u00a723A.3a). For each federation: how full it is against what its bonds cover; its band (CALM; PRESSURE from 70 %, CRITICAL from 90 %, FULL at 100 %; each left only below 60 / 80 / 100 %); the bond B* each guardian would need for 50 % load, and who is below it with the sats to add; the peg-in P* its gateways should hold. For the network: its band (that of the OPEN federation with the lowest load), B*_net and the installer's minimum bond.\n\nAccess: none\n\nReturns: 200 JSON {ok, node, censusHeight, federations[{federation, status, load, band, reserveSats, exposureCapSats, headroomSats, targetBondSats, guardians, guardiansBelowTarget[{node, bondSats, addSats}], targetPegInSats, gateways, gatewaysBelowTarget[{node, pegInSats, addSats}]}], network{lowestLoad, lowestFederation, band, targetBondSats, installMinimumBondSats}}\n\nSource: `packages/arena-node/src/server.js` line None.",
    "operationId": "get_capacity",
    "responses": {
     "200": {
      "description": "The ranking; amounts are decimal strings.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "{ok:false, why:\"this node runs no guardian, so it ranks no gateways\"}.",
      "content": {
       "application/json": {}
      }
     },
     "503": {
      "description": "The view could not be read now.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/census": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Round census evidence",
    "description": "The round's census as evidence, so a client can build the committee itself.\n\nAccess: none\n\nReturns: 200 JSON census evidence (bonds, merkle branches, updates) (cache 60 s); 404\n\nSource: `packages/arena-node/src/server.js` line 3815.",
    "operationId": "get_census",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Census evidence: bonds, merkle branches, updates (cache 60 s).",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "No census for that round.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/census-health": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Stake against the census ceiling",
    "description": "A round's stake against the ceiling its census supports; enforced only off test networks.\n\nAccess: none\n\nReturns: 200 JSON {ok, stakeSats, ceilingSats, why, enforced}; 400/404/409\n\nSource: `packages/arena-node/src/server.js` line 5681.",
    "operationId": "get_census_health",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{ok, stakeSats, ceilingSats, why, enforced}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "No census read.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/census-median": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Bond-weighted census medians",
    "description": "Bond-weighted medians of what the round's census nodes declare.\n\nAccess: none\n\nReturns: 200 JSON {bondMinSats, proposalDepositSats, declaring, of}; 400/404/409\n\nSource: `packages/arena-node/src/server.js` line 5656.",
    "operationId": "get_census_median",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{bondMinSats, proposalDepositSats, declaring, of}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "No census read.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/census-objection": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "Object to a round's census",
    "description": "Objects to a round's census; if upheld the round takes no new entry here.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; checked against this seat's own chain and the explorer\n\nReturns: 200 JSON {upheld:true, round, why}; 400/404/409 (not upheld)/503\n\nSource: `packages/arena-node/src/server.js` line 4452.",
    "operationId": "post_census_objection",
    "requestBody": {
     "required": true,
     "description": "{round: 64 hex, explorer: https URL}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{upheld:true, round, why}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not JSON, or bad round or explorer.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not upheld, with the reason.",
      "content": {
       "text/plain": {}
      }
     },
     "503": {
      "description": "Seat cannot read its chain.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/checkpoints": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Checkpoints of a run",
    "description": "Checkpoints (marks) of a run as received.\n\nAccess: none\n\nReturns: 200 octet-stream checkpoints, header x-checkpoints\n\nHeaders: `x-checkpoints`\n\nSource: `packages/arena-node/src/server.js` line 6277.",
    "operationId": "get_checkpoints",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Checkpoints back to back.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     }
    }
   }
  },
  "/claim-key": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Signed claim key of a round",
    "description": "This assigned signer node's signed claim key for the round (players lock to it).\n\nAccess: none\n\nReturns: 200 octet-stream claim-key attestation + BIP-340 signature; 404/409\n\nSource: `packages/arena-node/src/server.js` line 5850.",
    "operationId": "get_claim_key",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Claim-key attestation + BIP-340 signature.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not assigned, or the key is being made: ask again.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/closing": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Runs not signed at close",
    "description": "Runs this node could not sign at close and their state.\n\nAccess: none\n\nReturns: 200 JSON array of close states (HOLDING/SIGNED)\n\nSource: `packages/arena-node/src/server.js` line 4945.",
    "operationId": "get_closing",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": false,
      "description": "Round id (hex) to filter by.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Array of close states (HOLDING/SIGNED).",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/committee": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Round committee from the census",
    "description": "The round's committee drawn from the chain census.\n\nAccess: none\n\nReturns: 200 octet-stream 32-byte pubkeys, headers x-eligible, x-signer-nodes, x-census-root; 409\n\nHeaders: `x-eligible`, `x-signer-nodes`, `x-census-root`\n\nSource: `packages/arena-node/src/server.js` line 6391.",
    "operationId": "get_committee",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "role",
      "in": "query",
      "required": false,
      "description": "\"game\" (default) or \"settlement\".",
      "schema": {
       "type": "string"
      },
      "example": "game"
     }
    ],
    "responses": {
     "200": {
      "description": "32-byte public keys back to back.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "No committee, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/config": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "The config live on the chain",
    "description": "The game config in force on this seat's chain and its history (genesis first): what a round created now names, and what a repeal is read against (\u00a727A.7.5).\n\nAccess: none\n\nReturns: 200 JSON {configHash, since, by, history}; 400; 404\n\nSource: `packages/arena-node/src/server.js` line 4546.",
    "operationId": "get_config",
    "parameters": [
     {
      "name": "network",
      "in": "query",
      "required": false,
      "description": "Network id, 64 hex; this seat's chain by default.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{configHash, since, by, history}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "No network.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "This seat counts no ballot.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/dashboard": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Operator dashboard page",
    "description": "Serves the operator dashboard page (earned, spent, activity).\n\nAccess: none\n\nReturns: 200 text/html, no-store\n\nSource: `packages/arena-node/src/server.js` line 3461.",
    "operationId": "get_dashboard",
    "responses": {
     "200": {
      "description": "The dashboard page (no-store).",
      "content": {
       "text/html": {}
      }
     }
    }
   }
  },
  "/dashboard.json": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Dashboard data",
    "description": "Data behind the dashboard: node earnings, pools, hosts, hosted games, dev clients.\n\nAccess: none\n\nReturns: 200 JSON dashboard data (cached 30 s)\n\nSource: `packages/arena-node/src/server.js` line 3736.",
    "operationId": "get_dashboard_json",
    "responses": {
     "200": {
      "description": "Dashboard figures (rebuilt at most every 30 s).",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/dashboard/owner": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Owner page",
    "description": "Serves the node owner page (claim, leave/stay, plugin and network store).\n\nAccess: none\n\nReturns: 200 text/html owner page, no-store; 404 when the node runs without an owner area\n\nSource: `packages/arena-node/src/server.js` line 3466.",
    "operationId": "get_dashboard_owner",
    "responses": {
     "200": {
      "description": "The owner page (no-store).",
      "content": {
       "text/html": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/dashboard/react.js": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "The dashboard's React bundle",
    "description": "The node dashboard's React bundle (packages/arena-web/dist/dashboard.js). /dashboard draws with it when this release has it.\n\nAccess: none\n\nReturns: 200 JavaScript module; 404 when this release carries no React dashboard\n\nSource: `packages/arena-node/src/server.js` line 4757.",
    "operationId": "get_dashboard_react_js",
    "responses": {
     "200": {
      "description": "The bundle.",
      "content": {
       "text/javascript": {}
      }
     },
     "404": {
      "description": "This release carries no React dashboard.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/departure": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Hand over a departure notice",
    "description": "A guardian's notice that it leaves its federation.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: signature by the node key the notice names\n\nReturns: 201 (kept) / 200 JSON {ok, kept}; 400/422\n\nSource: `packages/arena-node/src/server.js` line 6043.",
    "operationId": "post_departure",
    "requestBody": {
     "required": true,
     "description": "Departure notice: encoding + signature, hex.",
     "content": {
      "text/plain": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "{ok, kept}.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Held already.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "422": {
      "description": "Does not stand.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/dkg": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Hand over a DKG contribution",
    "description": "Hands over a signer node's contribution to the committee key.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; checked by dkg.accept\n\nReturns: 201 \"taken\" / 200 \"already\"; 409\n\nSource: `packages/arena-node/src/server.js` line 6363.",
    "operationId": "post_dkg",
    "requestBody": {
     "required": true,
     "description": "DKG contribution.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "\"taken\"",
      "content": {
       "text/plain": {}
      }
     },
     "200": {
      "description": "\"already\"",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   },
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "This node's DKG contribution",
    "description": "Serves this node's own DKG contribution for an epoch.\n\nAccess: none\n\nReturns: 200 octet-stream this node's contribution; 404\n\nSource: `packages/arena-node/src/server.js` line 6370.",
    "operationId": "get_dkg",
    "parameters": [
     {
      "name": "epoch",
      "in": "query",
      "required": true,
      "description": "Epoch id, 64 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Contribution bytes.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "Nothing dealt.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/dkg-agreement": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Signed DKG agreement",
    "description": "Which contributions this node combined, signed.\n\nAccess: none\n\nReturns: 200 octet-stream signed agreement bytes; 409\n\nSource: `packages/arena-node/src/server.js` line 6382.",
    "operationId": "get_dkg_agreement",
    "parameters": [
     {
      "name": "epoch",
      "in": "query",
      "required": true,
      "description": "Epoch id, 64 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Signed agreement bytes.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/donation-ballot": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "[signed] Submit a developers' ballot record",
    "description": "Keeps a signed proposal or approval of the developers' donation set and hands it on once.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: the record's signature (a recipient of the set in force)\n\nReturns: 200 JSON {ok, ...}; 4xx; 501\n\nSource: `packages/arena-node/src/server.js` line 6968.",
    "operationId": "post_donation_ballot",
    "requestBody": {
     "required": true,
     "description": "{kind: proposal|approval, hex}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok: true, id, fresh}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not JSON or not a record.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "This node keeps no ballots.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/donation-ballots": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Developers' ballots",
    "description": "Every proposal and approval of the protocol developers' donation set this seat holds, with its tally, and the sets approved (\u00a727A.4.1).\n\nAccess: none\n\nReturns: 200 JSON {ballots[], approved[{serial, validFrom, setId, approvedBy}]}\n\nSource: `packages/arena-node/src/server.js` line 6913.",
    "operationId": "get_donation_ballots",
    "responses": {
     "200": {
      "description": "{ballots, approved}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/donation-gift": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "[signed] Record a donation gift",
    "description": "Checks and keeps a donor's signed gift record to a hosted game's donation set, the network's set in force, or a player (a zap). It is checked against the set and the federation output by output, indexed for GET /donations?key= and passed on to every seat.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: the donor's signature\n\nReturns: 200 JSON {id, kept, outputs}; 400/404/422/503\n\nSource: `packages/arena-node/src/server.js` line 5257.",
    "operationId": "post_donation_gift",
    "requestBody": {
     "required": true,
     "description": "{gift: hex, signature: hex}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{id, kept, outputs}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not a gift record.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such game set here.",
      "content": {
       "text/plain": {}
      }
     },
     "503": {
      "description": "No network donation authority known.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/donation-gifts": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "A donor's gifts",
    "description": "The donations a donor made outside any round (to a game's set, the protocol developers, or a player as a zap), as this seat keeps them.\n\nAccess: none\n\nReturns: 200 JSON {donor, gifts[]}; 400\n\nSource: `packages/arena-node/src/server.js` line 5290.",
    "operationId": "get_donation_gifts",
    "parameters": [
     {
      "name": "donor",
      "in": "query",
      "required": true,
      "description": "The donor's 32-byte key, 64 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{donor, gifts}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "No valid donor key.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/donation-rotations": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Donation-authority rotations",
    "description": "Donation-authority rotations held for the round's network.\n\nAccess: none\n\nReturns: 200 JSON {rotations:[{body, signature}]}; 404\n\nSource: `packages/arena-node/src/server.js` line 5796.",
    "operationId": "get_donation_rotations",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{rotations:[{body, signature}]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/donation-set": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Round's signed network donation set",
    "description": "The signed network donation set the round names.\n\nAccess: none\n\nReturns: 200 octet-stream donation set body + 64-byte Ed25519 signature; 404\n\nSource: `packages/arena-node/src/server.js` line 5835.",
    "operationId": "get_donation_set",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Donation set body + 64-byte Ed25519 signature.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round or set.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/donations": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Donations verified for a key",
    "description": "Donation outputs this node verified for a recipient key.\n\nAccess: none\n\nReturns: 200 JSON {key, donations[]}; 400\n\nSource: `packages/arena-node/src/server.js` line 5248.",
    "operationId": "get_donations",
    "parameters": [
     {
      "name": "key",
      "in": "query",
      "required": true,
      "description": "Recipient key, 66 hex compressed secp256k1 point.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "since",
      "in": "query",
      "required": false,
      "description": "Only rows from this time on, ms.",
      "schema": {
       "type": "integer"
      },
      "example": 0
     }
    ],
    "responses": {
     "200": {
      "description": "{key, donations[]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not a compressed key.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/donations/read": {
   "post": {
    "tags": [
     "Builders"
    ],
    "summary": "[signed] Acknowledge donations read",
    "description": "Recipient acknowledges donations read; node deletes those rows.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: ECDSA (DER) signature by the recipient key over donationsReadMessage; time window enforced\n\nReturns: 200 JSON {deleted}; 400/403/409\n\nSource: `packages/arena-node/src/server.js` line 5259.",
    "operationId": "post_donations_read",
    "requestBody": {
     "required": true,
     "description": "{key, atMs, outpoints[txid:index], signature: DER ECDSA hex by the recipient key}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{deleted}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "403": {
      "description": "Not signed by that recipient key.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Receipt too old or from the future.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/duty": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Who posts the rounds",
    "description": "Who posts the rounds (spec 5A.5, kanban #702): for the day covering today and the one covering the next 24 h, the duty order's first three nodes (rank 1 posts the primary grid from 00:00 UTC, rank 2 the backup grid from 02:00), for each app and grid who posted it (the series' creator key, its rank, whether a fallback node did), what this node posted or would post, whether its wallet can pay, and its last error. From the node's last look, so it is cheap.\n\nAccess: none\n\nReturns: 200 JSON {ok, node, nowMs, setting, on, wallet{canPay, why, confirmedSats, wallet}, feeRate, maxFeeRate, rankCap, days[{slot, covers, period, anchor, order[{rank, key, endpoint, self, dueFrom, backupDueFrom}], apps[{app, name, role, state, postings[{txid, height, emergency, role, poster, posterEndpoint, posterRank, fallback}]}]}], mine{posted, wouldPost}, lastError}; 404 when the node runs no round poster\n\nSource: `packages/arena-node/src/server.js` line 5298.",
    "operationId": "get_duty",
    "responses": {
     "200": {
      "description": "The duty as this node sees it.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "{ok:false, why:\"this node runs no round poster\"}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/emergency-departure": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Owner's emergency leave request",
    "description": "The owner's emergency leave request (spec \u00a723A.5a, protocol 17) takes an offline node out. A node without a guardian role leaves every seating; a guardian, if in time, becomes DEPARTED and its federation's succession starts. Taken only when fresh (posted at most 6 blocks before the tip), then passed on to every seat.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: the node's emergency key (BIP-340), which its census advertisement names\n\nReturns: 201 {ok, kept, node, postedAt} when taken, 200 when held already; 400/422/503\n\nSource: `packages/arena-node/src/server.js` line 7544.",
    "operationId": "post_emergency_departure",
    "requestBody": {
     "required": true,
     "description": "Hex: type 0x35, version, node key (32), emergency key (32), posted_at (u32), then the BIP-340 signature (64) by the emergency key.",
     "content": {
      "text/plain": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "{ok, kept: true, node, postedAt}: taken and passed on.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "{ok, kept: false, ...}: an earlier request for that node is held.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not a leave request in hex.",
      "content": {
       "text/plain": {}
      }
     },
     "422": {
      "description": "It does not stand: no census node names that emergency key, a wrong signature, ahead of the tip, or not fresh.",
      "content": {
       "text/plain": {}
      }
     },
     "503": {
      "description": "This seat reads no census yet.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/emergency-departures": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Held emergency leave requests",
    "description": "The leave requests this seat holds and its tip; with key, the census node whose bond advertisement names that emergency key (spec \u00a723A.5a).\n\nAccess: none\n\nReturns: 200 {node, tip, named?, requests}\n\nSource: `packages/arena-node/src/server.js` line 7552.",
    "operationId": "get_emergency_departures",
    "parameters": [
     {
      "name": "key",
      "in": "query",
      "required": false,
      "description": "An emergency public key (x-only, 64 hex).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{node, tip, named: {node, endpoint, operatorId, roles, guardianOf, held} | null, requests: [hex]}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/emergency/react.js": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "The \"my node is offline\" page's React bundle",
    "description": "The React steps of /Dashboard/emergency (packages/arena-web/dist/emergency.js). The page mounts them with its own /owner/client.js, which still makes the key and the signature; without the bundle, the page uses its own steps.\n\nAccess: none\n\nReturns: 200 JavaScript module; 404 when this release carries no React emergency page\n\nSource: `packages/arena-node/src/server.js` line 4753.",
    "operationId": "get_emergency_react_js",
    "responses": {
     "200": {
      "description": "The bundle.",
      "content": {
       "text/javascript": {}
      }
     },
     "404": {
      "description": "This release carries no React emergency page.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/entry": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "Join a player into a round",
    "description": "Joins a player into a round (federation, gateway, fee-lock and donation-output checks for paying rounds).\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none checked at this door; paying entry must be fundable (402 otherwise)\n\nReturns: 201 entry id bytes; 402/409/503 text (409 also: round not seated yet or seated twice when seating is on, census objected, stake over the census-health ceiling off test networks)\n\nSource: `packages/arena-node/src/server.js` line 4471.",
    "operationId": "post_entry",
    "requestBody": {
     "required": true,
     "description": "Encoded entry contract.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Entry id.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Not an entry contract.",
      "content": {
       "text/plain": {}
      }
     },
     "402": {
      "description": "Entry not funded.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused (game, seating, census objection or ceiling, federation, gateways, fees, fee lock, donation outputs).",
      "content": {
       "text/plain": {}
      }
     },
     "503": {
      "description": "Federation fee rule unreadable.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   },
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Entry contract by id",
    "description": "Returns a stored entry contract (makes equivocation proofs portable).\n\nAccess: none\n\nReturns: 200 octet-stream entry contract; 404\n\nSource: `packages/arena-node/src/server.js` line 4705.",
    "operationId": "get_entry",
    "parameters": [
     {
      "name": "id",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Encoded entry contract.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "404": {
      "description": "No such entry.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/entry-void": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "ENTRY_VOID record of an entry",
    "description": "Serves the ENTRY_VOID record this node holds for an entry.\n\nAccess: none\n\nReturns: 200 JSON {outcome:ENTRY_VOID, why, firstMark, evidenceKind, evidence, receipt, receipts[], offers}; 404\n\nSource: `packages/arena-node/src/server.js` line 4042.",
    "operationId": "get_entry_void",
    "parameters": [
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{outcome:ENTRY_VOID, why, firstMark, evidenceKind, evidence, receipt, receipts[], offers}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No ENTRY_VOID held.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/equivocation": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Two-marks equivocation proof",
    "description": "Publishes proof that a player signed two marks for the same tick.\n\nAccess: none\n\nReturns: 200 octet-stream pairs of signed marks, headers x-equivocations, x-ticks-at; 204 none\n\nHeaders: `x-equivocations`, `x-ticks-at`\n\nSource: `packages/arena-node/src/server.js` line 4733.",
    "operationId": "get_equivocation",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Pairs of signed marks.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "204": {
      "description": "None held.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/evidence-blocks": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Marks held as evidence, with blocks",
    "description": "Lists each mark of an entry held as evidence with the block it names.\n\nAccess: none\n\nReturns: 200 JSON {marks:[{mark, block, seenMs}]}\n\nSource: `packages/arena-node/src/server.js` line 4109.",
    "operationId": "get_evidence_blocks",
    "parameters": [
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{marks:[{mark, block, seenMs}]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/exchange": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "Exchange e-cash between federations",
    "description": "Moves money into another federation without Lightning: e-cash of `from` in, the same amount of the seat's e-cash of `to` out. A retry with the same e-cash is answered the same and never paid twice.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; the e-cash is the payment\n\nReturns: 200 JSON { ok, msat, ecash, federation }; 400/409/429/503\n\nSource: `packages/arena-node/src/server.js` line 7748.",
    "operationId": "post_exchange",
    "requestBody": {
     "required": true,
     "description": "{ from: federation id hex, to: federation id hex, ecash: e-cash string of `from`, amountMsat: the amount it carries }",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ ok, msat, ecash (of `to`), federation }",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not an exchange request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused before anything was taken (too little held, over the limit, e-cash spent), with the reason.",
      "content": {
       "text/plain": {}
      }
     },
     "429": {
      "description": "This seat's hourly exchange limit is spent.",
      "content": {
       "text/plain": {}
      }
     },
     "503": {
      "description": "Taken, the payout failed: ask again with the same e-cash.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   },
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Read a seat's exchange offer",
    "description": "What this seat can exchange: its limits and the e-cash it holds in each named federation.\n\nAccess: none\n\nReturns: 200 JSON { maxMsat, perHourMsat, holds: { federation: msat } }\n\nSource: `packages/arena-node/src/server.js` line 7748.",
    "operationId": "get_exchange",
    "parameters": [
     {
      "name": "federations",
      "in": "query",
      "required": false,
      "description": "Federation ids, 64 hex, comma-separated.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{ maxMsat, perHourMsat, holds }",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "This seat runs no exchange.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/expected": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Grids on their way, as published",
    "description": "The grids this node's publisher put on chain and the seats do not list yet, as the publisher states them (ARENA_EXPECTED_FILE); a market page says when the next round comes from it.\n\nAccess: none\n\nReturns: 200 JSON {nowMs, tip, expected[{game, gameId, firstWindowMs, firstCloseMs, lastCloseMs, slots, committeeTimeMs, publication{txid, height}, federation}]}\n\nSource: `packages/arena-node/src/server.js` line 4324.",
    "operationId": "get_expected",
    "responses": {
     "200": {
      "description": "The ranking; amounts are decimal strings.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "{ok:false, why:\"this node runs no guardian, so it ranks no gateways\"}.",
      "content": {
       "application/json": {}
      }
     },
     "503": {
      "description": "The view could not be read now.",
      "content": {
       "application/json": {}
      }
     }
    }
   },
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "Announce a published grid",
    "description": "A publisher announces a grid it put on chain: body JSON {line, tx} - its signed series line and its publication transaction, hex. The node checks the creator's signature over the series id and that the transaction carries the series' publication output, then names the grid at GET /expected and GET /pending until its last round closes. Anyone may post it.\n\nAccess: none\n\nReturns: 200 JSON {ok, series, publication, firstCloseMs, slots}; 400 not a series line / not a grid / not a transaction; 403 the creator signature does not stand; 409 an invalid lead; 410 its last round closed; 422 the transaction does not publish the series\n\nSource: `packages/arena-node/src/server.js` line 4324.",
    "operationId": "post_expected",
    "responses": {
     "200": {
      "description": "The ranking; amounts are decimal strings.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "{ok:false, why:\"this node runs no guardian, so it ranks no gateways\"}.",
      "content": {
       "application/json": {}
      }
     },
     "503": {
      "description": "The view could not be read now.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/favicon.ico": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Page icon",
    "description": "The icon of the node's own pages.\n\nAccess: none\n\nReturns: 200 image/x-icon, or 204\n\nSource: `packages/arena-node/src/server.js` line 5638.",
    "operationId": "get_favicon_ico",
    "responses": {
     "200": {
      "description": "200 image/x-icon, or 204",
      "content": {
       "image/x-icon": {}
      }
     }
    }
   }
  },
  "/federation-invoice": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Federation invoice for a stake",
    "description": "Gets a federation LNv2 invoice for the entry's net stake before joining a paying round.\n\nAccess: none\n\nReturns: 200 JSON {round, paymentHash, amountMsat, request}; 400/404/409/502/503\n\nSource: `packages/arena-node/src/server.js` line 4657.",
    "operationId": "get_federation_invoice",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "donation",
      "in": "query",
      "required": false,
      "description": "Donation in whole msat (0 or more).",
      "schema": {
       "type": "integer"
      },
      "example": 0
     }
    ],
    "responses": {
     "200": {
      "description": "{round, paymentHash, amountMsat, request}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Bad donation.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Round asks no stake, or no invoice is made here.",
      "content": {
       "text/plain": {}
      }
     },
     "502": {
      "description": "Federation invoice is for the wrong amount.",
      "content": {
       "text/plain": {}
      }
     },
     "503": {
      "description": "Federation or invoice decoder unavailable.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/federation-record": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Guardian signature over a federation record",
    "description": "This guardian node's signature over its federation record (optionally with named guardians gone).\n\nAccess: none\n\nReturns: 200 JSON {ok, height, nodePubkey, body, signature, leaving, leaveSig}; 400/404 {ok:false, why}\n\nSource: `packages/arena-node/src/server.js` line 6001.",
    "operationId": "get_federation_record",
    "parameters": [
     {
      "name": "federation",
      "in": "query",
      "required": true,
      "description": "Federation id, 64 hex.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "gone",
      "in": "query",
      "required": false,
      "description": "Comma list of guardians gone.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "height",
      "in": "query",
      "required": false,
      "description": "Census height of the body.",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "reserve",
      "in": "query",
      "required": false,
      "description": "Reserve in whole sats.",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "absent",
      "in": "query",
      "required": false,
      "description": "Comma list of absence attestations, hex.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "departed",
      "in": "query",
      "required": false,
      "description": "Comma list of departure notices, hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{ok, height, nodePubkey, body, signature, leaving, leaveSig}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "{ok:false, why}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/federations": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Federation records mirrored here",
    "description": "Every federation record this seat mirrors, and who a drain pays.\n\nAccess: none\n\nReturns: 200 JSON {node, federations[], drainPools}\n\nSource: `packages/arena-node/src/server.js` line 6083.",
    "operationId": "get_federations",
    "parameters": [
     {
      "name": "fresh",
      "in": "query",
      "required": false,
      "description": "\"1\" gathers again now.",
      "schema": {
       "type": "string"
      },
      "example": "1"
     }
    ],
    "responses": {
     "200": {
      "description": "{node, federations[], drainPools}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/fee-lock": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "Hand over a fee lock",
    "description": "Hands over a player's fee lock for verification.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; verified against the federation and the entry\n\nReturns: 201 text \"fee lock verified ...\"; 400/404/409\n\nSource: `packages/arena-node/src/server.js` line 5314.",
    "operationId": "post_fee_lock",
    "parameters": [
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Fee-lock contract fields.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "\"fee lock verified ...\"",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "Bad entry or not a lock.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such entry.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Lock refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/fees": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Fees in force and fee proposals",
    "description": "The protocol fees in force at this seat's tip (and at a named height), each fee's limits and the sums, and every fee proposal with its signal, vote, the protocol developers' answers and its decision.\n\nAccess: none\n\nReturns: 200 JSON {tip, inForce, today, height?, atHeight?, schedule, limits{fee:{min,max,today,donation}}, sums{roundMaxBps,itemPct,marketMaxBps}, proposals[]}\n\nSource: `packages/arena-node/src/server.js` line 6948.",
    "operationId": "get_fees",
    "parameters": [
     {
      "name": "height",
      "in": "query",
      "required": false,
      "description": "A block height: the answer adds atHeight, the set in force there (a round's census height is what a joining page pays its entry with).",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{tip, inForce, today, height?, atHeight?, schedule, limits, sums, proposals}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/final-sig": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "This seat's FINAL signature on a run",
    "description": "This seat's FINAL signature on a run once the window has closed.\n\nAccess: none\n\nReturns: 200 octet-stream signed FINAL record; 409 text reason\n\nSource: `packages/arena-node/src/server.js` line 6183.",
    "operationId": "get_final_sig",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Signed FINAL record.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "409": {
      "description": "Not signable yet, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    }
   },
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Push a FINAL signature",
    "description": "Peer pushes its FINAL signature on a run.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; signature checked on arrival\n\nReturns: 201 \"kept\"; 400/409\n\nSource: `packages/arena-node/src/server.js` line 6197.",
    "operationId": "post_final_sig",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Signed FINAL signature (fixed size).",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "\"kept\"",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "Round not held or wrong size.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/first-mark": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Forward a player's first mark",
    "description": "Takes a player's first signed mark forwarded by another signer node and receipts it, or records VOID/FORFEIT.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: mark must carry the player's valid signature; no request auth\n\nReturns: 200 {receipt}; 400/404/409 {why, forfeit?/entryVoid?}\n\nSource: `packages/arena-node/src/server.js` line 3988.",
    "operationId": "post_first_mark",
    "requestBody": {
     "required": true,
     "description": "{mark hex, batches[] hex, receipt hex?, entryVoid?, ask?}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{receipt}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "{why}: not a signed first mark.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "{why}: no such entry.",
      "content": {
       "application/json": {}
      }
     },
     "409": {
      "description": "{why, forfeit?|entryVoid?}: refused.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/foreign-receipts": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Receipts for marks not held",
    "description": "Lists receipts seen for marks this node does not hold (gossip signal).\n\nAccess: none\n\nReturns: 200 octet-stream receipts, header x-foreign-receipts; 204 none\n\nHeaders: `x-foreign-receipts`\n\nSource: `packages/arena-node/src/server.js` line 4718.",
    "operationId": "get_foreign_receipts",
    "responses": {
     "200": {
      "description": "Receipts back to back.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "204": {
      "description": "None.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/forfeit": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Get or make a lock forfeit",
    "description": "Returns the forfeit of a qualifier's lock, or of a cancelled market order's stake and fee locks. If needed, the node makes it with the other signer nodes first.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none\n\nReturns: 200 JSON {signature, contractId, claimPk, kept}; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5772.",
    "operationId": "get_forfeit",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex; a handout id for a refused-round lock.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "lock",
      "in": "query",
      "required": false,
      "description": "\"fee\" for the fee lock (a cancelled market order or a refunded market); omit for the stake lock.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{signature, contractId, claimPk, kept}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not due, or a loser's lock.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/forfeit-commit": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Forfeit signing, round one",
    "description": "Round one of the committee signing of a qualifier's lock forfeit.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; node answers only for a forfeit it rebuilt itself\n\nReturns: 200 octet-stream nonce commitment; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5423.",
    "operationId": "post_forfeit_commit",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "lock",
      "in": "query",
      "required": false,
      "description": "\"fee\" for the fee lock (a cancelled market order or a refunded market); omit for the stake lock.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Nonce commitment.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/forfeit-share": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Forfeit signing, round two",
    "description": "Round two of the forfeit signing.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; same rule\n\nReturns: 200 octet-stream signature share; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5429.",
    "operationId": "post_forfeit_share",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "lock",
      "in": "query",
      "required": false,
      "description": "\"fee\" for the fee lock (a cancelled market order or a refunded market); omit for the stake lock.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Encoded commitment list.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Signature share.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/forfeit-signature": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Hand over the forfeit signature",
    "description": "Hands over the combined forfeit signature.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; checked\n\nReturns: 201 \"forfeit kept\"; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5437.",
    "operationId": "post_forfeit_signature",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "lock",
      "in": "query",
      "required": false,
      "description": "\"fee\" for the fee lock (a cancelled market order or a refunded market); omit for the stake lock.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "64-byte combined signature.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "\"forfeit kept\"",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/founding": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Hand in a federation setup code",
    "description": "A drawn node hands in its signed federation setup code.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: signature by the drawn node over the setup code\n\nReturns: 201/200 JSON {ok, kept}; 400/404/409 text (404 when the seat runs no founding, ARENA_FOUNDING)\n\nSource: `packages/arena-node/src/server.js` line 6025.",
    "operationId": "post_founding",
    "requestBody": {
     "required": true,
     "description": "{id, node, code, signature}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "{ok, kept}.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Held already.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "Seat runs no founding (ARENA_FOUNDING).",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   },
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Founding state of this seat",
    "description": "This seat's view of a federation founding.\n\nAccess: none\n\nReturns: 200 JSON {node, ...founding state} or {node, off:true} / {none:true}\n\nSource: `packages/arena-node/src/server.js` line 6031.",
    "operationId": "get_founding",
    "responses": {
     "200": {
      "description": "{node, ...state} or {node, off:true} / {node, none:true}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/funding": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Funding proposals and leaderboard payouts",
    "description": "Every project funding proposal with its signal, comments and vote, every leaderboard payout request and its 25 % vote, and every player's newest name.\n\nAccess: none\n\nReturns: 200 JSON {tip, schedule, signalPct, proposals[], leaderboards[], names[]}\n\nSource: `packages/arena-node/src/server.js` line 6920.",
    "operationId": "get_funding",
    "responses": {
     "200": {
      "description": "{tip, schedule, signalPct: 15, proposals, leaderboards, names}.",
      "content": {
       "application/json": {}
      }
     }
    }
   },
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "[signed] Submit a funding record",
    "description": "Checks and keeps a signed funding record (proposal, signal, comment, vote, fee proposal, fee approval or leaderboard payout request), and passes a new one on to every seat once.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: the record carries its author's signature\n\nReturns: 200 JSON {ok, id, fresh, ...}; 4xx {ok:false, why}; 501\n\nSource: `packages/arena-node/src/server.js` line 6920.",
    "operationId": "post_funding",
    "requestBody": {
     "required": true,
     "description": "{kind: proposal|signal|comment|vote|fee|fee-approval|leaderboard, hex: the signed record}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok: true, id, fresh}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not JSON, unknown kind, or the record does not decode.",
      "content": {
       "application/json": {}
      }
     },
     "422": {
      "description": "The record breaks a rule (limits, heights, signature).",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "This node keeps no funding proposals.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/game-donation-set": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Round's game donation set",
    "description": "The round's game developer donation set.\n\nAccess: none\n\nReturns: 200 octet-stream encoded game donation set; 404\n\nSource: `packages/arena-node/src/server.js` line 5810.",
    "operationId": "get_game_donation_set",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Encoded game donation set.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round or set.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/game-icon": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Game icon",
    "description": "Serves a hosted game's square icon.\n\nAccess: none\n\nReturns: 200 image/svg+xml (cache 1 h); 404\n\nSource: `packages/arena-node/src/server.js` line 4135.",
    "operationId": "get_game_icon",
    "parameters": [
     {
      "name": "game",
      "in": "query",
      "required": true,
      "description": "Game id, 64 hex (case-insensitive).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Square SVG icon (cache 1 h).",
      "content": {
       "image/svg+xml": {}
      }
     },
     "404": {
      "description": "No such game or no icon.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/game-manifest": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Round's signed game manifest",
    "description": "The signed manifest of the round's game.\n\nAccess: none\n\nReturns: 200 octet-stream signed game manifest; 404\n\nSource: `packages/arena-node/src/server.js` line 5824.",
    "operationId": "get_game_manifest",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Signed game manifest.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round or game.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/game-outcome": {
   "post": {
    "tags": [
     "Builders"
    ],
    "summary": "[signed] Hand in a market-on-a-game outcome",
    "description": "Hands a seat the source round's signed result for a market on a game's outcome (protocol 2026.0.6). The seat checks it and holds it where it would hold an attestation; the market then settles like an attested one (pari-mutuel). A refund (Tick Tock FLAT), or a source that can never fit, is held as VOID at once. Seats also fetch the result themselves.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: the source round's settlement committee (as this node draws it) must have signed the result, at its threshold (5 of 7); a source round this node does not hold is fetched from other seats and checked against its id\n\nReturns: 201/200 JSON {round, held, fresh, ok, outcome?, label?, refund?, void?, value, signers, threshold, source, voided, why, state, ...}; 400/404/409\n\nSource: `packages/arena-node/src/server.js` line 5226.",
    "operationId": "post_game_outcome",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "The market round's id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "{openCents, closeCents, front?, sigs:[{key, signature}]}: the source round's RoundResult and the seats' signatures over its id.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "{round, held, fresh, outcome?, label?, refund?, void?, signers, threshold, source, voided, why, state, ...}: held now - an outcome, or VOID.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Held already.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "No round named, or not a JSON round result.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round, or no seat answered its source round as the round the market names.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not a market on a game, the source round has not ended, no committee drawn, or the result does not stand.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/games": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Games this node hosts",
    "description": "Lists the games this node hosts, each with its signed manifest.\n\nAccess: none\n\nReturns: 200 JSON {node, games:[{id, name, title, icon, attested, type, version, info, live:{rounds, players}, manifest hex}]} (cache 10 s)\n\nSource: `packages/arena-node/src/server.js` line 4172.",
    "operationId": "get_games",
    "responses": {
     "200": {
      "description": "{node, games:[{id, name, title, icon, attested, type, version, info, live, manifest}]} (cache 10 s).",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/gateway-claim": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "This node's gateway claim",
    "description": "This node's claim to a gateway seat of its federation (2026.0.15, spec \u00a723A.9), signed by its custody agent with the node key. It names the federation, where the gateway answers, its Lightning node key, inbound and outbound of its public channels (inbound from outside the federation counted separately), its peg-in, and the time. The federation's guardians read it, probe the gateway and rank the claims. Measured on seat guardian-1 (2026-10-18 22:20Z): 404 {\"ok\":false,\"why\":\"this node stands for no gateway seat\"}.\n\nAccess: none (the claim is signed by the node key)\n\nReturns: 200 JSON signed gateway claim {node, federationId, gatewayUrl, lightningPubkey, capacitySats, pegInSats, atMs, inboundSats, outboundSats, lightningAddr, outsideInboundSats, signature}; 404 JSON {ok:false, why}\n\nSource: `packages/arena-node/src/server.js` line 4305.",
    "operationId": "get_gateway_claim",
    "responses": {
     "200": {
      "description": "The signed claim; amounts are decimal strings. Minimums on testnet4: inbound 100,000, outbound 100,000, peg-in 50,000 sat (mainnet 250,000 / 250,000 / 2,000,000).",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "{ok:false, why:\"this node stands for no gateway seat\"}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/gateway-seating": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "A guardian's signed gateway seating",
    "description": "The gateway seats this guardian signed for a federation and epoch (2026.0.15): at most 2 seated gateways, drawn by ticket from the eligible claims; a seating holds when 7 of the 10 guardians sign the same one. The gateways share a third of the custody pool. Measured on guardian-1, federation 337ae01a, epoch 1089: seats [] (no eligible claim yet).\n\nAccess: none (signed by the guardian)\n\nReturns: 200 JSON {federationId, epoch, seats[], guardian, signature}; 404 JSON {ok:false, why}\n\nSource: `packages/arena-node/src/server.js` line 4320.",
    "operationId": "get_gateway_seating",
    "parameters": [
     {
      "name": "federation",
      "in": "query",
      "required": true,
      "description": "Federation id, 64 hex.",
      "schema": {
       "type": "string"
      },
      "example": "337ae01ad1e9bb35b5628faad3457e62d69d036efe8a34bcfc20cb31b42bb75e"
     },
     {
      "name": "epoch",
      "in": "query",
      "required": true,
      "description": "Gateway epoch: block height / 144 (2026.0.15).",
      "schema": {
       "type": "integer"
      },
      "example": 1089
     }
    ],
    "responses": {
     "200": {
      "description": "{\"federationId\":\"337ae01a\u2026\",\"epoch\":1089,\"seats\":[],\"guardian\":\"2fca1090\u2026\",\"signature\":\"3474e0c8\u2026\"}.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "This guardian signed none for that federation and epoch.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/gateway-seats": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "This guardian's gateway ranking",
    "description": "How this guardian ranks its federation's gateway claims in the current epoch: who is seated, how many seats are empty, the ranked candidates and why the others are ineligible (minimums, availability, not serving the federation). Measured on guardian-1 (22:20Z): {\"ok\":true,\"federationId\":\"337ae01a\u2026\",\"epoch\":1089,\"measuredEpoch\":\"whole\",\"seated\":[],\"empty\":2,\"ranked\":[],\"ineligible\":[],\"why\":\"0 of 2 gateway seats filled from 0 eligible operators\",\"gateways\":{}}.\n\nAccess: none\n\nReturns: 200 JSON {ok, federationId, epoch, measuredEpoch, seated[], empty, ranked[], ineligible[], why, gateways{}}; 503 when the view cannot be read; 404 JSON on a node with no guardian\n\nSource: `packages/arena-node/src/server.js` line 4324.",
    "operationId": "get_gateway_seats",
    "responses": {
     "200": {
      "description": "The ranking; amounts are decimal strings.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "{ok:false, why:\"this node runs no guardian, so it ranks no gateways\"}.",
      "content": {
       "application/json": {}
      }
     },
     "503": {
      "description": "The view could not be read now.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/gateway/{rest}": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "The node's Lightning gateway (passthrough)",
    "description": "The node's Lightning gateway at the node's public address. /gateway/... is passed byte for byte to the gateway on the same machine (ARENA_GATEWAY_PORT, set by the installer on a custody node). Clients of its federation reach the gateway at its api-addr (<public address>/gateway/), the same way /guardian reaches the guardian (spec \u00a723A.9).\n\nAccess: none here; the gateway's own admin calls need its own password\n\nReturns: the gateway's own answer, byte for byte; 502 text when the gateway on this machine does not answer; 404 \"no such door\" on a seat without ARENA_GATEWAY_PORT\n\nSource: `packages/arena-node/src/server.js` line 4272.",
    "operationId": "get_gateway_rest",
    "parameters": [
     {
      "name": "rest",
      "in": "path",
      "required": true,
      "description": "The gateway API path, e.g. v1/info.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The gateway's answer.",
      "content": {
       "*/*": {}
      }
     },
     "404": {
      "description": "This seat runs no gateway (\"no such door\").",
      "content": {
       "text/plain": {}
      }
     },
     "502": {
      "description": "The gateway on this machine does not answer.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/guardian": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Whether this node is a guardian",
    "description": "Says whether this node runs a federation guardian and its public endpoint.\n\nAccess: none\n\nReturns: 200 JSON {guardian:true, endpoint} or {guardian:false}\n\nSource: `packages/arena-node/src/server.js` line 3451.",
    "operationId": "get_guardian",
    "responses": {
     "200": {
      "description": "{guardian:true, endpoint} or {guardian:false}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/guardian-bonds": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Bonds of a round's guardians",
    "description": "Lists the round's guardians' bond transactions and merkle branches for the page to verify.\n\nAccess: none\n\nReturns: 200 JSON bonds of the round's guardians; 404 with reason\n\nSource: `packages/arena-node/src/server.js` line 3821.",
    "operationId": "get_guardian_bonds",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Guardian bond transactions and merkle branches.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "None, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/h2h-want": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "When each head-to-head game was wanted",
    "description": "When each head-to-head game was last wanted.\n\nAccess: none\n\nReturns: 200 JSON {nowMs, wants:{game: atMs}}\n\nSource: `packages/arena-node/src/server.js` line 5033.",
    "operationId": "get_h2h_want",
    "responses": {
     "200": {
      "description": "{nowMs, wants:{game: atMs}}.",
      "content": {
       "application/json": {}
      }
     }
    }
   },
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "Ask for a head-to-head table",
    "description": "A page says it wants a head-to-head table; the grid keeper reads it to publish rounds (memory only).\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none\n\nReturns: 200 JSON {ok, game, atMs}; 404\n\nSource: `packages/arena-node/src/server.js` line 5037.",
    "operationId": "post_h2h_want",
    "parameters": [
     {
      "name": "game",
      "in": "query",
      "required": true,
      "description": "Hosted head-to-head game id, 64 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{ok, game, atMs}.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Not a head-to-head game hosted here.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/halt-observations": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Hand over a halt observation",
    "description": "A peer seat's signed observation of a federation halt.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: signature by an active census seat (the observer)\n\nReturns: 201/200 JSON {ok, status, kept}; 400/409; 503 without a chain\n\nSource: `packages/arena-node/src/server.js` line 6094.",
    "operationId": "post_halt_observations",
    "requestBody": {
     "required": true,
     "description": "{observation, signature} hex.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "Kept.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Held already.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     },
     "503": {
      "description": "Seat reads no chain.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   },
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Halt observations of a federation",
    "description": "Halt observations held for a federation and the halt proof if one stands.\n\nAccess: none\n\nReturns: 200 JSON {node, federation, observations[], seen, proof}; 400\n\nSource: `packages/arena-node/src/server.js` line 6100.",
    "operationId": "get_halt_observations",
    "parameters": [
     {
      "name": "federation",
      "in": "query",
      "required": true,
      "description": "Federation id, 64 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{node, federation, observations[], seen, proof}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/handout": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "Hand in sealed stake shares",
    "description": "Accepts a player's sealed stake-preimage shares dealt at the round's threshold.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: node opens only its own sealed share and checks it against the commitments; no request signature\n\nReturns: 201 handout id bytes, header x-signer-node; 400/404/409\n\nHeaders: `x-signer-node`\n\nSource: `packages/arena-node/src/server.js` line 4404.",
    "operationId": "post_handout",
    "requestBody": {
     "required": true,
     "description": "Encoded stake-share handout.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Handout id.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Not a handout.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Wrong threshold, refused round, or this node's share does not check.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   },
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Handout this node accepted",
    "description": "Returns a handout this node accepted.\n\nAccess: none\n\nReturns: 200 octet-stream handout bytes; 404\n\nSource: `packages/arena-node/src/server.js` line 4442.",
    "operationId": "get_handout",
    "parameters": [
     {
      "name": "id",
      "in": "query",
      "required": true,
      "description": "Handout id, hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Handout bytes.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "404": {
      "description": "No such handout.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/headers": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Bitcoin header chain",
    "description": "Serves a Bitcoin header chain only when the operator configured one (ARENA_ATTACH_PROOF_DIR headers.bin).\n\nAccess: none\n\nReturns: 200 octet-stream: 80-byte Bitcoin headers back to back; 404 if the operator gave no chain\n\nSource: `packages/arena-node/src/server.js` line 3754.",
    "operationId": "get_headers",
    "responses": {
     "200": {
      "description": "80-byte headers back to back.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "404": {
      "description": "No chain configured.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/here": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Who sits at a table",
    "description": "Who sits at a head-to-head round's table now.\n\nAccess: none\n\nReturns: 200 JSON {round, here:[{key, name, agoMs}]}; 400/404/409\n\nSource: `packages/arena-node/src/server.js` line 5044.",
    "operationId": "get_here",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{round, here:[{key, name, agoMs}]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not a head-to-head round.",
      "content": {
       "text/plain": {}
      }
     }
    }
   },
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "[signed] Say this tab sits at a table",
    "description": "Says this tab sits at a head-to-head round's table (memory only).\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: BIP-340 signature by the identity key over the presence id (round, key)\n\nReturns: 200 JSON {round, here:[{key, name, agoMs}]}; 400/403/404/409/503\n\nSource: `packages/arena-node/src/server.js` line 5055.",
    "operationId": "post_here",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "{key: 64 hex identity key, sig: 128 hex BIP-340 signature over the presence id}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{round, here:[{key, name, agoMs}]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "403": {
      "description": "Presence not signed by its key.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not a head-to-head round.",
      "content": {
       "text/plain": {}
      }
     },
     "503": {
      "description": "Table or table count full.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/identity": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Node identity public key",
    "description": "Returns this node's identity public key.\n\nAccess: none\n\nReturns: 200 raw bytes: the node public key\n\nSource: `packages/arena-node/src/server.js` line 3455.",
    "operationId": "get_identity",
    "responses": {
     "200": {
      "description": "The node's 32-byte identity public key.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     }
    }
   }
  },
  "/item-purchase": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "[signed] Record an item purchase",
    "description": "Keeps a buyer's signed item purchase record after checking it against the hosted game's terms, the donation sets and the federation output by output; hands a new one on to every seat.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: the buyer's signature over the record\n\nReturns: 200 JSON {id, kept}; 400/404/422\n\nSource: `packages/arena-node/src/server.js` line 5206.",
    "operationId": "post_item_purchase",
    "requestBody": {
     "required": true,
     "description": "{purchase: hex, signature: hex}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{id, kept: new|held}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not a purchase record.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "This seat hosts no such game or item.",
      "content": {
       "text/plain": {}
      }
     },
     "422": {
      "description": "The record does not check.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/items": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Items a player owns",
    "description": "The in-game items a player bought (e.g. the larger truck), from the purchase records this seat keeps.\n\nAccess: none\n\nReturns: 200 JSON {node, items[]}; 400\n\nSource: `packages/arena-node/src/server.js` line 5296.",
    "operationId": "get_items",
    "parameters": [
     {
      "name": "player",
      "in": "query",
      "required": true,
      "description": "The buyer's 32-byte items key, 64 hex.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "game",
      "in": "query",
      "required": false,
      "description": "The game name.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "dev",
      "in": "query",
      "required": false,
      "description": "The game developer's key, 64 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{node, items: [{itemId, gameName, txid, ...}]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "No valid player key.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/late-first-mark": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Player's late first mark",
    "description": "Serves the player's late first mark this node keeps.\n\nAccess: none\n\nReturns: 200 octet-stream mark; 204 none\n\nSource: `packages/arena-node/src/server.js` line 4768.",
    "operationId": "get_late_first_mark",
    "parameters": [
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The signed mark.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "204": {
      "description": "None kept.",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/liquidations": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Liquidation schedules",
    "description": "Halted federations' liquidation schedules and where claims go.\n\nAccess: none\n\nReturns: 200 JSON {node, liquidations:[{federation, haltHeight, haltProof, claims, liquidatesAt, claim windows, spentSet}]}\n\nSource: `packages/arena-node/src/server.js` line 6107.",
    "operationId": "get_liquidations",
    "responses": {
     "200": {
      "description": "{node, liquidations[]}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/liquidations/spent-set": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Hand over a spent-nonce set",
    "description": "A guardian's signed spent-nonce set for a halted federation.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: signed by a guardian of the halted federation's record\n\nReturns: 201 (kept) / 200 JSON {ok, kept, session}; 400/422; 503\n\nSource: `packages/arena-node/src/server.js` line 6112.",
    "operationId": "post_liquidations_spent_set",
    "requestBody": {
     "required": true,
     "description": "{spentSet, signature} hex.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "{ok, kept, session}.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Held already.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "422": {
      "description": "Does not stand.",
      "content": {
       "text/plain": {}
      }
     },
     "503": {
      "description": "No federation records yet.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/liquidity-claim": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "This node's liquidity provider claim",
    "description": "This node's liquidity provider claim (2026.0.16, the fourth service, spec \u00a723A.10), signed by its provider service. It names its Lightning node, the free coins it holds with one signed proof per coin (at most 50), and the channels it gave. Each proof is the address key's signature over the claim message: BIP-322-style compact ECDSA, P2TR by the BIP-86 tweak. Guardians count the provider only while free + channels given >= 5 x L on testnet4 (10 x L on mainnet), where L is the 100,000 sat channel; that amount is its weight. Measured on guardian-1 (22:20Z): 200, freeSats 538022, 1 channel of 100,000, funds with signatures; on guardian-3: 404.\n\nAccess: none (the claim and each coin proof are signed)\n\nReturns: 200 JSON signed liquidity claim {node, lightningPubkey, lightningAddr, freeSats, atMs, depositAddress, channels[{peer, capacitySats}], funds[{txid, vout, address, sats, signature}], signature}; 404 JSON {ok:false, why}\n\nSource: `packages/arena-node/src/server.js` line 4311.",
    "operationId": "get_liquidity_claim",
    "responses": {
     "200": {
      "description": "The signed claim, e.g. {\"node\":\"2fca1090\u2026\",\"lightningPubkey\":\"02bf8349\u2026\",\"lightningAddr\":\"boxy5rnx\u2026.onion:9735\",\"freeSats\":\"538022\",\"atMs\":\"1792362197408\",\"depositAddress\":\"tb1pytcj\u2026\",\"channels\":[{\"peer\":\"0274e261\u2026\",\"capacitySats\":\"100000\"}],\"funds\":[{\"txid\":\"2ff934cf\u2026\",\"vout\":1,\"address\":\"tb1pqszc\u2026\",\"sats\":\"198137\",\"signature\":\"IMADMYz4\u2026\"}],\"signature\":\"\u2026\"}.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "{ok:false, why:\"this node is no liquidity provider\"}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/liquidity-seating": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "A guardian's signed liquidity seating",
    "description": "The liquidity providers this guardian signed for a federation and epoch (2026.0.16): every provider whose proven coins meet the minimum, with its weight. A new node's inbound channels are drawn from them (at most 2 providers per node, each once); the liquidity pool (1 % of each round) is split by weight. Measured on guardian-1, federation 337ae01a, epoch 1089: providers 2fca1090 (600000) and f4bfe620 (800000).\n\nAccess: none (signed by the guardian)\n\nReturns: 200 JSON {federationId, epoch, providers[{node, weight}], guardian, signature}; 404 JSON {ok:false, why}\n\nSource: `packages/arena-node/src/server.js` line 4316.",
    "operationId": "get_liquidity_seating",
    "parameters": [
     {
      "name": "federation",
      "in": "query",
      "required": true,
      "description": "Federation id, 64 hex.",
      "schema": {
       "type": "string"
      },
      "example": "337ae01ad1e9bb35b5628faad3457e62d69d036efe8a34bcfc20cb31b42bb75e"
     },
     {
      "name": "epoch",
      "in": "query",
      "required": true,
      "description": "Gateway epoch: block height / 144 (2026.0.15).",
      "schema": {
       "type": "integer"
      },
      "example": 1089
     }
    ],
    "responses": {
     "200": {
      "description": "{\"federationId\":\"337ae01a\u2026\",\"epoch\":1089,\"providers\":[{\"node\":\"2fca1090\u2026\",\"weight\":\"600000\"},{\"node\":\"f4bfe620\u2026\",\"weight\":\"800000\"}],\"guardian\":\"2fca1090\u2026\",\"signature\":\"0138fd89\u2026\"}.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "This guardian signed none for that federation and epoch.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/lock": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "Hand over a stake lock",
    "description": "Hands over a player's federation stake lock for verification.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; verified against the federation and the entry\n\nReturns: 201 text \"stake lock verified ...\"; 400/404/409\n\nSource: `packages/arena-node/src/server.js` line 5286.",
    "operationId": "post_lock",
    "parameters": [
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Stake-lock contract fields.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "\"stake lock verified ...\"",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "Bad entry or not a lock.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such entry.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Lock refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/lock-settlement": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Losers' lock settlement state",
    "description": "Where the round's settlement of losers' locks stands. `moved` is what the settlement paid: `moved.payouts[]`, each {kind, pk, sats}. These are the winners (kind qualifier) and, from 2026.0.16, the four 1 % node pools: game/verify, settlement, custody (guardians \u2154, gateways \u2153) and liquidity providers (by weight).\n\nAccess: none\n\nReturns: 200 JSON {state, txid, why, signature, message, madeMs, moved} or {state:NONE}; for a round that takes any federation {state ACCEPTED|REFUSED|SUBMITTING, federations[]}\n\nSource: `packages/arena-node/src/server.js` line 5728.",
    "operationId": "get_lock_settlement",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{state, txid, why, signature, message, madeMs, moved} or {state:NONE}; any-federation: {state, federations[]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/market-rounds": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Rounds that took orders",
    "description": "The market rounds that took orders on this seat since a time, so a page reads a player's own orders back from the nodes after a reload, closed ones too.\n\nAccess: none\n\nReturns: 200 JSON {rounds[]}; 400\n\nSource: `packages/arena-node/src/server.js` line 6176.",
    "operationId": "get_market_rounds",
    "parameters": [
     {
      "name": "since",
      "in": "query",
      "required": false,
      "description": "Unix ms; rounds since then.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{rounds}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Bad since.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/name": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "[signed] Store a player's display name",
    "description": "Stores a joined player's signed display name for a round.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: Schnorr signature by the player key in the record; player must be joined at this node\n\nReturns: 201 {kept:true}; 200 {kept:false, why}; 400/404/409 {why}\n\nSource: `packages/arena-node/src/server.js` line 4061.",
    "operationId": "post_name",
    "requestBody": {
     "required": true,
     "description": "{record: hex lobby name record, sig: hex Schnorr signature by the record's player key}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "{kept:true}.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "{kept:false, why}: a newer name is held.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "{why}: bad record or signature.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "{why}: no such round.",
      "content": {
       "application/json": {}
      }
     },
     "409": {
      "description": "{why}: player not joined here.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/names": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Signed player names of a round",
    "description": "Lists the signed player names held for a round.\n\nAccess: none\n\nReturns: 200 JSON {round, names}\n\nSource: `packages/arena-node/src/server.js` line 4085.",
    "operationId": "get_names",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{round, names}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/network": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "This seat's network package",
    "description": "This seat's network as a package for another seat's network store.\n\nAccess: none\n\nReturns: 200 JSON network package; 404/409/500\n\nSource: `packages/arena-node/src/server.js` line 4148.",
    "operationId": "get_network",
    "parameters": [
     {
      "name": "network",
      "in": "query",
      "required": false,
      "description": "Network id, 64 hex; default this seat's own.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Network package.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "No such network.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "No federation invite named.",
      "content": {
       "text/plain": {}
      }
     },
     "500": {
      "description": "Could not be packaged.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/network-games": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Games found on the network",
    "description": "Games and markets this seat found on the network.\n\nAccess: none\n\nReturns: 200 JSON {node, atMs, seats, games:[{..., hostedHere, updateOf}]}\n\nSource: `packages/arena-node/src/server.js` line 4165.",
    "operationId": "get_network_games",
    "parameters": [
     {
      "name": "fresh",
      "in": "query",
      "required": false,
      "description": "\"1\" reads the network again now.",
      "schema": {
       "type": "string"
      },
      "example": "1"
     }
    ],
    "responses": {
     "200": {
      "description": "{node, atMs, seats, games:[{..., hostedHere, updateOf}]}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/nostr-results": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Signed Nostr event of a round result",
    "description": "The node's signed Nostr event for a round's result, so a client checks its id and signature itself.\n\nAccess: none\n\nReturns: 200 JSON signed kind-30762 Nostr event, header x-nostr-published (ISO time or \"no\"); 400; 404 round not held or game not hosted; 409 settlement not ACCEPTED yet\n\nHeaders: `x-nostr-published`\n\nSource: `packages/arena-node/src/server.js` line 4350.",
    "operationId": "get_nostr_results",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The signed kind-30762 Nostr event (NIP-01).",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not a 64-hex round id.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "Round not held, or of a game not hosted here.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Settlement not ACCEPTED here yet.",
      "content": {
       "text/plain": {}
      }
     },
     "500": {
      "description": "Result could not be read.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/objection": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "Object to a run result",
    "description": "Files an objection against a run result; a holding one suspends it and triggers a re-run.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; bundle replayed and checked\n\nReturns: 201/200/400/404/422 text\n\nSource: `packages/arena-node/src/server.js` line 6210.",
    "operationId": "post_objection",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "block",
      "in": "query",
      "required": false,
      "description": "Block hash, 64 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Objection bundle: transcript + receipts.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Taken.",
      "content": {
       "text/plain": {}
      }
     },
     "200": {
      "description": "\"already objected\"",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "Empty body.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round or entry.",
      "content": {
       "text/plain": {}
      }
     },
     "422": {
      "description": "Bundle does not hold, or the entry forfeited by proof.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/objection-bundle": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Objection that held against a run",
    "description": "The objection that held against a run, as checked here, for the arbiter to replay.\n\nAccess: none\n\nReturns: 200 octet-stream objection bundle; 404\n\nSource: `packages/arena-node/src/server.js` line 5993.",
    "operationId": "get_objection_bundle",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Objection bundle.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "404": {
      "description": "None held.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/operator/config": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Config token edits (not built)",
    "description": "Placeholder for config-token edits; always answers 501.\n\n**Needs an operator token: Authorization: Bearer <token>, minted in the owner area.**\n\nAccess: operator token with scope config\n\nReturns: 501 JSON {ok:false, scope, why} (not built yet); 401/403\n\nSource: `packages/arena-node/src/server.js` line 3507.",
    "operationId": "get_operator_config",
    "responses": {
     "501": {
      "description": "{ok:false, scope, why}: not built yet.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Missing or unknown Bearer token.",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Token lacks the needed scope.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without operator tokens.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "security": [
     {
      "operatorToken": []
     }
    ]
   }
  },
  "/operator/status": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Operator status read",
    "description": "Status read for the operator UI.\n\n**Needs an operator token: Authorization: Bearer <token>, minted in the owner area.**\n\nAccess: operator token with scope read (any method)\n\nReturns: 200 JSON {ok, node, owner, roundsHeld, federations:[{federation, status, load}]}; 401/403; 404 without operator tokens\n\nSource: `packages/arena-node/src/server.js` line 3483.",
    "operationId": "get_operator_status",
    "responses": {
     "200": {
      "description": "{ok, node, owner, roundsHeld, federations:[{federation, status, load}]}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Missing or unknown Bearer token.",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Token lacks the needed scope.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without operator tokens.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "security": [
     {
      "operatorToken": []
     }
    ]
   }
  },
  "/operator/vote": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Sign a ballot vote",
    "description": "Signs a ballot vote with the node bond key and returns the OP_RETURN payload; broadcasts nothing.\n\n**Needs an operator token: Authorization: Bearer <token>, minted in the owner area.**\n\nAccess: operator token with scope vote\n\nReturns: 200 JSON {ok, node, proposalId, choice, opReturn hex, broadcast}; 400/401/403/405\n\nSource: `packages/arena-node/src/server.js` line 3491.",
    "operationId": "post_operator_vote",
    "requestBody": {
     "required": true,
     "description": "{proposalId: 64 hex, choice: YES|NO|ABSTAIN}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, node, proposalId, choice, opReturn (hex), broadcast}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not JSON, bad proposal id or choice.",
      "content": {
       "application/json": {}
      }
     },
     "405": {
      "description": "Not a POST.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Missing or unknown Bearer token.",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Token lacks the needed scope.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without operator tokens.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "security": [
     {
      "operatorToken": []
     }
    ]
   }
  },
  "/order-locks": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "An order's verified locks",
    "description": "An order's stake lock and fee lock as this seat verified them, for a seat that holds the order's certified batch but never received its locks (kanban #620).\n\nAccess: none\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 8017.",
    "operationId": "get_order_locks",
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/outcome": {
   "post": {
    "tags": [
     "Builders"
    ],
    "summary": "[signed] Submit an outcome attestation",
    "description": "Submits the attested outcome of an oracle or market round, or a scalar market's observed value. A conflicting one marks the round DISPUTED.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: attestation must carry the game manifest's threshold of distinct Ed25519 attestor signatures and be after entry close (and the market's resolution time); a scalar market takes only a value attestation, every other market only an outcome attestation\n\nReturns: 201/200 JSON {held, fresh, why, state, ...}; 400/404/409\n\nSource: `packages/arena-node/src/server.js` line 5223.",
    "operationId": "post_outcome",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Encoded outcome attestation (type 0x1d), or value attestation (type 0x2a, a scalar market's value).",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "{held, fresh, why, state, ...}: taken.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Held already.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "No round named, or not an outcome or value attestation.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not an attested round, the wrong kind of attestation for its market, does not stand, or too early.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   },
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Outcome of an attested round",
    "description": "The current outcome of an attested round, with the round's own question and labels if it has one. For a market on a game: the held source result (gameOutcome: RoundResult, signatures, source contract) instead of an attestation, and VOID at once on a refund. For a scalar market: its bounds, the attested value, where it pays (clamped) and the scalar table.\n\nAccess: none\n\nReturns: 200 JSON {round, state OPEN|ATTESTED|DISPUTED|VOID, outcomes (the round's own labels for a template round), question?, resolveAtMs?, scalar? {low, high, unit}, outcome?, label?, value?, clamped?, valuesNamed?, attestation? | gameOutcome?, table?, ...}; 400/404/409\n\nSource: `packages/arena-node/src/server.js` line 5278.",
    "operationId": "get_outcome",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{round, state OPEN|ATTESTED|DISPUTED|VOID, outcomes, question?, resolveAtMs?, scalar?, outcome?, label?, value?, clamped?, attestation? | gameOutcome?, table?, ...}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not an attested round.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/owner": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Owner state",
    "description": "Says whether the node has an owner and whether it is leaving.\n\nAccess: none\n\nReturns: 200 JSON {node, claimed, owner, claimedAtMs, leavingAtMs}; 404 without owner area\n\nSource: `packages/arena-node/src/server.js` line 3512.",
    "operationId": "get_owner",
    "responses": {
     "200": {
      "description": "{node, claimed, owner, claimedAtMs, leavingAtMs}.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/owner/add-bond": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Add to the bond (a second output)",
    "description": "Adds to this node's bond: a second bond output next to the first, with the node's newest advertisement as its body. From protocol 19 both outputs count together (kanban #544). Without post: the plan (amount, new total, fees, maturity, about when), checked with testmempoolaccept. With post: true, the funding and bond transactions are broadcast. Paid from the installer's wallet or, on a seat set up by hand, from the bond wallet it names (kanban #553).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, plan: {addSats, bondSats, totalSats, fees, maturity, lock, countsAfter}, bond: {txid} or null}; 400 with why; 401/403 when not the owner; 501 without an installer home or a bond wallet (ARENA_BOND_CLI)\n\nSource: `packages/arena-node/src/server.js` line 4744.",
    "operationId": "post_owner_add_bond",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"liquidity/new-address\", args {}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok:true, address:\"tb1p\u2026\"}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "This node runs no liquidity provider service.",
      "content": {
       "application/json": {}
      }
     },
     "502": {
      "description": "The provider service did not answer or failed.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/app-devs": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Game developers overview",
    "description": "For each developer key the node holds: its apps, donations and proposals (kanban #582).\n\nAccess: none\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 5897.",
    "operationId": "get_owner_app_devs",
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/owner/apps/dev-key": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Install or remove a developer key",
    "description": "Installs or removes a game developer's key; answers its public key and the apps it signs, never the key (kanban #582).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner-style signed request (the owner key)\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 6081.",
    "operationId": "post_owner_apps_dev_key",
    "requestBody": {
     "required": true,
     "description": "Signed request with the developer key to install, or the key to remove.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/apps/split": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Set an app's split",
    "description": "Sets how an app's developer share is split between keys (kanban #582).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner-style signed request (the owner key)\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 6069.",
    "operationId": "post_owner_apps_split",
    "requestBody": {
     "required": true,
     "description": "Signed request with the split.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/bond": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "This node's bond and its lock",
    "description": "This node's bond as the newest census this seat holds names it (outpoint, amount, confirmation height, maturity, template) and its lock at the tip: the maturity block, the blocks to it, an estimated date and whether it can be withdrawn now. Public, as /owner/standing.\n\nAccess: none\n\nReturns: 200 JSON {node, bond, network, tip, lock, says}\n\nSource: `packages/arena-node/src/server.js` line 4246.",
    "operationId": "get_owner_bond",
    "responses": {
     "200": {
      "description": "{node, bond: {txid, vout, sats, height, maturity, template} or null, network, tip, lock: {maturity, tip, blocksLeft, estimatedMs, withdrawable}, says}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/owner/bond-wallet/address": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] A top-up address for the bond wallet",
    "description": "A new top-up address of the bond wallet a seat set up by hand names (ARENA_BOND_CLI), for the owner page's \"Top-up address\" button beside Add to bond (kanban #553).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, address}; 401/403 when not the owner; 501 without a bond wallet (ARENA_BOND_CLI); 500 when the wallet does not answer\n\nSource: `packages/arena-node/src/server.js` line 4775.",
    "operationId": "post_owner_bond_wallet_address",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"liquidity/new-address\", args {}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok:true, address:\"tb1p\u2026\"}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "This node runs no liquidity provider service.",
      "content": {
       "application/json": {}
      }
     },
     "502": {
      "description": "The provider service did not answer or failed.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/bond-withdraw": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Withdraw the bond after its lock",
    "description": "From the bond's maturity block on, sends the whole bond to the owner's address through its template-2 recovery leaf: signed with this node's key, checked with testmempoolaccept, then broadcast. Before maturity it refuses and names the height, the blocks left and the date. The node leaves the census from the next census height.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner\n\nReturns: 200 JSON {ok, txid, value, fee}; 400; 401/403; 409; 503\n\nSource: `packages/arena-node/src/server.js` line 4524.",
    "operationId": "post_owner_bond_withdraw",
    "requestBody": {
     "required": true,
     "description": "An owner request (signOwnerRequest or a NIP-98 event) for action bond-withdraw with args {address: a segwit address of the bond's network, feeRate: sat/vB, 2 by default}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok: true, txid, value, fee}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not an address of that network, or the spend failed.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not a valid owner signature.",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Not this node's owner.",
      "content": {
       "application/json": {}
      }
     },
     "409": {
      "description": "No bond of this node in the census, or still locked (the height, blocks left and date are named).",
      "content": {
       "application/json": {}
      }
     },
     "503": {
      "description": "This seat reads no chain to send to.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/claim": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Claim the node",
    "description": "Binds the first owner key to the node.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner-style signed request (action claim) plus the claim code from the node's log\n\nReturns: 200 {ok, owner}; 401/403/409 {ok:false, why}\n\nSource: `packages/arena-node/src/server.js` line 3619.",
    "operationId": "post_owner_claim",
    "requestBody": {
     "required": true,
     "description": "Signed request, action \"claim\", args {code}: the claim code from the node's log.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, owner}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature does not verify.",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Wrong claim code.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Node already has an owner.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/client.js": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Owner page script",
    "description": "Serves the owner page script that signs owner requests.\n\nAccess: none\n\nReturns: 200 text/javascript\n\nSource: `packages/arena-node/src/server.js` line 3471.",
    "operationId": "get_owner_client_js",
    "responses": {
     "200": {
      "description": "The owner page script (no-store).",
      "content": {
       "text/javascript": {}
      }
     }
    }
   }
  },
  "/owner/custody/add": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Become custody from the owner page: plan, start, progress",
    "description": "Makes an installed node a custody node from the owner page (kanban #563). The node runs the installer's own custody steps itself (Lightning, the gateway, the guardian, the advertisement update); the owner does not run \"arena-install --add-custody\". Without post: the plan. With progress: the runner's progress. With post and the typed I UNDERSTAND: starts it.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, plan} (Lightning, gateway, bond against the guardian floor, what the wallet must hold, part by part, its address) or {ok, progress}; 200 {ok} once started; 400 with why (e.g. \"type I UNDERSTAND\", a short wallet); 401/403 when not the owner; 501 on a node the installer did not set up; 500 with why\n\nSource: `packages/arena-node/src/server.js` line 5340.",
    "operationId": "post_owner_custody_add",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"liquidity/new-address\", args {}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok:true, address:\"tb1p\u2026\"}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "This node runs no liquidity provider service.",
      "content": {
       "application/json": {}
      }
     },
     "502": {
      "description": "The provider service did not answer or failed.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/dev": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Owner dev clients",
    "description": "The owner's dev clients: what each was given (protocol and per-game split), its wallets and what withdrawals answered.\n\nAccess: none\n\nReturns: 200 JSON {managed, clients:[{slug, ...snapshot, imported, running, pid, waiting, requests[], split}], beside}; 404 without owner area\n\nSource: `packages/arena-node/src/server.js` line 3605.",
    "operationId": "get_owner_dev",
    "responses": {
     "200": {
      "description": "{managed, clients[], beside}.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/owner/dev/donations": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "One client's donations",
    "description": "One dev client's donations, newest first, each with its app, filterable by app and protocol, paged (kanban #578).\n\nAccess: none\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 5958.",
    "operationId": "get_owner_dev_donations",
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/owner/dev/fee-answer": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] A developer's answer to a fee proposal",
    "description": "From the owner page: a dev client of this node approves or denies a fee proposal, signed with that client's key, kept and handed on.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: node owner\n\nReturns: 200 JSON {ok, ...}; 400/401/404/501\n\nSource: `packages/arena-node/src/server.js` line 4460.",
    "operationId": "post_owner_dev_fee_answer",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request (BIP-340 JSON or NIP-98 kind 27235) with args {slug, proposalId (64 hex), approve: bool}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok: true, id, fresh}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "No such dev client or fee proposal.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "No dev clients or no fee proposals on this node.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/dev/propose": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Propose a developers' set",
    "description": "From the owner page: a dev client of this node proposes a new split of the protocol developers' donation set (with optional vesting), signed with its recipient key, kept and handed on (\u00a727A.4.1).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: node owner\n\nReturns: 200 JSON {ok, ...}; 401/404/409/501\n\nSource: `packages/arena-node/src/server.js` line 4419.",
    "operationId": "post_owner_dev_propose",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request (BIP-340 JSON or NIP-98 kind 27235) with args {slug, recipients}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok: true, id}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "409": {
      "description": "This dev key is not a recipient of the set in force.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "No dev clients or no ballots.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/dev/remove": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Remove a dev client",
    "description": "Stops a dev client; its directory and key are kept, renamed.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, kept}; 401/403/404; 501 without dev clients\n\nSource: `packages/arena-node/src/server.js` line 3714.",
    "operationId": "post_owner_dev_remove",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"dev/remove\", args {slug}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, kept}: stopped, directory and key kept.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "No such dev client.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "409": {
      "description": "Node has no owner yet.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "Node runs no dev clients (ARENA_DEV_WASM_PKG unset).",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/dev/setup": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Set up a dev client",
    "description": "Sets up a dev client (new or imported key) and starts it.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, slug, recipientPk, imported}; 400/401/403/409; 501 without dev clients\n\nSource: `packages/arena-node/src/server.js` line 3714.",
    "operationId": "post_owner_dev_setup",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"dev/setup\", args {label, secretHex?, minWithdrawMsat?}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, slug, recipientPk, imported}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Bad label or key.",
      "content": {
       "application/json": {}
      }
     },
     "409": {
      "description": "A client of that label or key exists.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "501": {
      "description": "Node runs no dev clients (ARENA_DEV_WASM_PKG unset).",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/dev/vote": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Vote on a developers' set",
    "description": "From the owner page: a dev client of this node accepts or denies a proposed developers' set, signed with its recipient key, kept and handed on.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: node owner\n\nReturns: 200 JSON {ok, ...}; 401/404/501\n\nSource: `packages/arena-node/src/server.js` line 4419.",
    "operationId": "post_owner_dev_vote",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request (BIP-340 JSON or NIP-98 kind 27235) with args {slug, proposalId, accept: bool}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok: true, id}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "No such dev client.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "No dev clients or no ballots.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/dev/withdraw": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Withdraw from a dev client",
    "description": "Leaves a withdrawal request for a dev client to pay out to an invoice or Lightning address.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, id}; 400/401/403/404/409; 501 without dev clients\n\nSource: `packages/arena-node/src/server.js` line 3714.",
    "operationId": "post_owner_dev_withdraw",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"dev/withdraw\", args {slug, invoice | lnAddress, msat?, federation?}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, id}: the request left for the client.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Bad invoice, address or amount.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "No such dev client.",
      "content": {
       "application/json": {}
      }
     },
     "409": {
      "description": "A withdrawal is still waiting.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "Node runs no dev clients (ARENA_DEV_WASM_PKG unset).",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/donations": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Donation sets verified here",
    "description": "What this seat verified for the protocol and game donation sets.\n\nAccess: none\n\nReturns: 200 JSON donation report (protocol sets and each hosted game's set, with rows held)\n\nSource: `packages/arena-node/src/server.js` line 3609.",
    "operationId": "get_owner_donations",
    "responses": {
     "200": {
      "description": "Donation report: protocol sets and each hosted game's set, with rows held.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/owner/federation/retire": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Retire an empty federation this node guards: plan, consent",
    "description": "Retires a federation that holds nothing (kanban #577): the owner of one of its guardians consents. A seat builds that federation's record as CLOSED, with no successor, only when its own owner consented, so the record stands once a threshold of the guardians' owners consented. Every seat then reads it as CLOSED, and its guardians are free for the next founding. Once the record stands, the node sets its guardian of that federation aside (kept) and starts a guardian in setup.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, plan} (the federation this node guards, its record status and reserve, the guardian's audit by module, holdsNothing, consented); 200 {ok, consented} once kept; 200 {retired: true} when the record is already CLOSED; 400 with why (no guardian, another federation, \"type RETIRE\"); 409 when it still holds something; 401/403 when not the owner\n\nSource: `packages/arena-node/src/server.js` line 5364.",
    "operationId": "post_owner_federation_retire",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"liquidity/new-address\", args {}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok:true, address:\"tb1p\u2026\"}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "This node runs no liquidity provider service.",
      "content": {
       "application/json": {}
      }
     },
     "502": {
      "description": "The provider service did not answer or failed.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/first-bond": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Post the first bond",
    "description": "The first bond from the owner area: the plan (the node wallet's address, what to send, what arrived), and with post: true the bond posted (kanban #728).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner-style signed request (the owner key)\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 6306.",
    "operationId": "post_owner_first_bond",
    "requestBody": {
     "required": true,
     "description": "Signed request, args {post}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/funding-comment": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Owner: comment (funding)",
    "description": "From the owner page: a comment by this node on a funding proposal, written and signed with the node's own key, kept and handed on (\u00a727A.9.3).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: node owner\n\nReturns: 200 JSON {ok, id, ...}; 401/404/503\n\nSource: `packages/arena-node/src/server.js` line 4296.",
    "operationId": "post_owner_funding_comment",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request (BIP-340 JSON or NIP-98 kind 27235) with args {proposal, parent?, text}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok: true, id, fresh}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "This node keeps no funding proposals.",
      "content": {
       "application/json": {}
      }
     },
     "503": {
      "description": "This node reads no chain height or network.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/funding-propose": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Owner: propose (funding)",
    "description": "From the owner page: a funding proposal authored by this node (amount, LNURL, purpose), written and signed with the node's own key, kept and handed on (\u00a727A.9.3).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: node owner\n\nReturns: 200 JSON {ok, id, ...}; 401/404/503\n\nSource: `packages/arena-node/src/server.js` line 4296.",
    "operationId": "post_owner_funding_propose",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request (BIP-340 JSON or NIP-98 kind 27235) with args {amountSats, lnurl, purpose}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok: true, id, fresh}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "This node keeps no funding proposals.",
      "content": {
       "application/json": {}
      }
     },
     "503": {
      "description": "This node reads no chain height or network.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/funding-signal": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Owner: signal (funding)",
    "description": "From the owner page: this node's signal for a funding proposal, written and signed with the node's own key, kept and handed on (\u00a727A.9.3).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: node owner\n\nReturns: 200 JSON {ok, id, ...}; 401/404/503\n\nSource: `packages/arena-node/src/server.js` line 4296.",
    "operationId": "post_owner_funding_signal",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request (BIP-340 JSON or NIP-98 kind 27235) with args {proposal}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok: true, id, fresh}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "This node keeps no funding proposals.",
      "content": {
       "application/json": {}
      }
     },
     "503": {
      "description": "This node reads no chain height or network.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/gateway/setup": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Set up the gateway",
    "description": "For a custody node whose setup left Lightning or the gateway for later: starts the setup, or with {progress: true} reads how far it is (kanban #711).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner-style signed request (the owner key)\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 6445.",
    "operationId": "post_owner_gateway_setup",
    "requestBody": {
     "required": true,
     "description": "Signed request, args {progress}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/key-from-words": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Move to the key of the 24 words",
    "description": "An installed node moves to the key its 24 words give: a new bond under it, then the old one taken back at its maturity (kanban #650).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner-style signed request (the owner key)\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 6325.",
    "operationId": "post_owner_key_from_words",
    "requestBody": {
     "required": true,
     "description": "Signed request.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/leave": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "What a leaving seat still owes",
    "description": "What a leaving seat still owes: held rounds and its guardian custody.\n\nAccess: none\n\nReturns: 200 JSON leave status (rounds still held, custody check, leavingAtMs)\n\nSource: `packages/arena-node/src/server.js` line 3517.",
    "operationId": "get_owner_leave",
    "responses": {
     "200": {
      "description": "Leave status: rounds still held, custody check, leavingAtMs.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     }
    }
   },
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Leave: stop taking new rounds",
    "description": "Seat stops taking new rounds; a guardian node also signs and posts a departure notice to every seat.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, leavingAtMs, already?, departure?}; 401/403/409\n\nSource: `packages/arena-node/src/server.js` line 3633.",
    "operationId": "post_owner_leave",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"leave\", args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, leavingAtMs, already?, departure?}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Node has no owner yet.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/liquidity/become": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Become a liquidity provider (installed node)",
    "description": "Makes an installed node a liquidity provider from its owner page (\"Set up\", then \"Become a liquidity provider\"). Without post: the plan (LND tested, the deposit against the node's wallet, a custody node's peg-in kept aside). With post: sets up the provider service on its LND, the agent that sends the deposit, the role and its settings.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, plan} (without post) or {ok, plan, done}; 400 {ok:false, why} (no Bitcoin Core, no LND, LND not answering, a provider already); 401/403 when not the owner; 501 on a node not set up by the installer\n\nSource: `packages/arena-node/src/server.js` line 5277.",
    "operationId": "post_owner_liquidity_become",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"liquidity/become\", args {post}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok:true, plan:{lightningPubkey, depositSats, walletSats, reservedSats, shortSats, address, channelSats}, done?}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "{ok:false, why}: not possible on this node yet.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "Not a node set up by the installer.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/liquidity/new-address": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] New top-up address for the liquidity wallet",
    "description": "A new top-up address for the liquidity provider's LND wallet (the owner page's \"New address\" button). The node asks its provider service on the same machine, which owns the LND and re-signs its claim once coins arrive.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, address}; 401/403 when not the owner; 501 without a provider service (ARENA_LIQUIDITY_PROVIDER_URL); 502 when the provider service fails\n\nSource: `packages/arena-node/src/server.js` line 4644.",
    "operationId": "post_owner_liquidity_new_address",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"liquidity/new-address\", args {}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok:true, address:\"tb1p\u2026\"}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "This node runs no liquidity provider service.",
      "content": {
       "application/json": {}
      }
     },
     "502": {
      "description": "The provider service did not answer or failed.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/login": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Owner login check",
    "description": "Checks an owner signature and returns the node summary for the owner page.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, node, guardian, games[]}; 401/403/409\n\nSource: `packages/arena-node/src/server.js` line 3728.",
    "operationId": "post_owner_login",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"login\", args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, node, guardian, games[]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Node has no owner yet.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/owner/musig/nonce": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] MuSig2 nonce for a bond spend",
    "description": "Node draws its MuSig2 nonce for a cooperative key-path spend of its bond.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, node, pubnonce}; 400/401/403/409\n\nSource: `packages/arena-node/src/server.js` line 3694.",
    "operationId": "post_owner_musig_nonce",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"musig\", args {sessionId, msg 64 hex, tweak 64 hex}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, node, pubnonce}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Missing session id, tweak or message.",
      "content": {
       "application/json": {}
      }
     },
     "409": {
      "description": "Session already open.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/musig/partial": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] MuSig2 partial signature of the bond",
    "description": "Node signs its MuSig2 partial signature once for that session.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, psig}; 404 no session; 409 no chain named (regtest/testnet4 only); 422\n\nSource: `packages/arena-node/src/server.js` line 3702.",
    "operationId": "post_owner_musig_partial",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"musig\", args {sessionId, aggnonce}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, psig}.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "No such session.",
      "content": {
       "application/json": {}
      }
     },
     "409": {
      "description": "Node names no chain (regtest/testnet4 only).",
      "content": {
       "application/json": {}
      }
     },
     "422": {
      "description": "Signing failed.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/network": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Network store view of this seat",
    "description": "The chain this seat reads, its own network package and installed network packages.\n\nAccess: none\n\nReturns: 200 JSON {chain, networkId, own, draining[], installed[]}\n\nSource: `packages/arena-node/src/server.js` line 3592.",
    "operationId": "get_owner_network",
    "responses": {
     "200": {
      "description": "{chain, networkId, own, draining[], installed[]}.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/owner/network/install": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Install a network package",
    "description": "Installs a network package from another seat after checks.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 or status JSON result; 422 when refused\n\nSource: `packages/arena-node/src/server.js` line 3672.",
    "operationId": "post_owner_network_install",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"network-install\", args {network, from}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "Install result.",
      "content": {
       "application/json": {}
      }
     },
     "422": {
      "description": "Refused by the checks.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Node has no owner yet.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/network/remove": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Remove a network package",
    "description": "Removes an installed network package.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 or status JSON result; 409 when refused\n\nSource: `packages/arena-node/src/server.js` line 3680.",
    "operationId": "post_owner_network_remove",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"network-remove\", args {network}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "Remove result.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Node has no owner yet.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/network/update": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Update a network package",
    "description": "Updates an installed network package.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 or status JSON result; 422 when refused\n\nSource: `packages/arena-node/src/server.js` line 3672.",
    "operationId": "post_owner_network_update",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"network-update\", args {network, from}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "Update result.",
      "content": {
       "application/json": {}
      }
     },
     "422": {
      "description": "Refused by the checks.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Node has no owner yet.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/old-bond-withdraw": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Take an old bond back",
    "description": "Spends an old bond with the old key at its maturity, signed by the owner like the bond's own withdrawal (kanban #650).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner-style signed request (the owner key)\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 6590.",
    "operationId": "post_owner_old_bond_withdraw",
    "requestBody": {
     "required": true,
     "description": "Signed request.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/operator/list": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] List operator tokens",
    "description": "Lists operator tokens.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, tokens[]}; 401/403/404/409\n\nSource: `packages/arena-node/src/server.js` line 3621.",
    "operationId": "post_owner_operator_list",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"operator-list\", args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, tokens[]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Node has no owner yet.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/owner/operator/mint": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Mint an operator token",
    "description": "Mints a scoped operator token.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, id, scopes, uri (arena-operator: pairing URI; an old blwp-operator: URI still pairs)}; 400/401/403/404/409\n\nSource: `packages/arena-node/src/server.js` line 3621.",
    "operationId": "post_owner_operator_mint",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"operator-mint\", args {scopes[]}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, id, scopes, uri (arena-operator: pairing URI; an old blwp-operator: URI still pairs)}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Node has no owner yet.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/operator/revoke": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Revoke an operator token",
    "description": "Revokes an operator token.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok}; 401/403/404/409\n\nSource: `packages/arena-node/src/server.js` line 3621.",
    "operationId": "post_owner_operator_revoke",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"operator-revoke\", args {id}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Node has no owner yet.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/plugins": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Hosted and installed games",
    "description": "Games hosted and installed on this seat, and the store settings.\n\nAccess: none\n\nReturns: 200 JSON {hosted[], installed[], settings}\n\nSource: `packages/arena-node/src/server.js` line 3580.",
    "operationId": "get_owner_plugins",
    "responses": {
     "200": {
      "description": "{hosted[], installed[], settings}.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/owner/plugins/install": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Install a game",
    "description": "Fetches a game from another seat, checks it and activates it at once.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 or status JSON result; 422 when refused\n\nSource: `packages/arena-node/src/server.js` line 3656.",
    "operationId": "post_owner_plugins_install",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"install\", args {game, from}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "Install result.",
      "content": {
       "application/json": {}
      }
     },
     "422": {
      "description": "Refused by the checks.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Node has no owner yet.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/plugins/remove": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Remove a hosted game",
    "description": "Removes a hosted game.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 or status JSON result; 409 when refused\n\nSource: `packages/arena-node/src/server.js` line 3664.",
    "operationId": "post_owner_plugins_remove",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"remove\", args {game}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "Remove result.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Node has no owner yet.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/plugins/update": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Update a hosted game",
    "description": "Installs a newer version of a hosted game in place of the one it replaces.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 or status JSON result; 422 when refused\n\nSource: `packages/arena-node/src/server.js` line 3656.",
    "operationId": "post_owner_plugins_update",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"update\", args {game, from, replaces}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "Update result.",
      "content": {
       "application/json": {}
      }
     },
     "422": {
      "description": "Refused by the checks.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Node has no owner yet.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/reach": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Read or switch how the node is reached",
    "description": "Reads or switches how this installed node is reached, from the owner page: quick, workers, direct, tailscale or permanent. A switch runs the installer's own reach and service steps in the background, since they restart the seat.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, mode, url, stable, serving, progress, modes} (and the switch started when args.mode names one); 401/403 when not the owner; 501 on a node the installer did not set up\n\nSource: `packages/arena-node/src/server.js` line 5106.",
    "operationId": "post_owner_reach",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"reach\", args, atMs, sig}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok:true, mode, url, stable, serving, progress, modes}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "Not a node set up by the installer.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/react.css": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "The owner page's React stylesheet",
    "description": "The stylesheet of the owner page's React screens (packages/arena-web/dist/arena.css).\n\nAccess: none\n\nReturns: 200 stylesheet; 404 when this release carries no React screens\n\nSource: `packages/arena-node/src/server.js` line 4762.",
    "operationId": "get_owner_react_css",
    "responses": {
     "200": {
      "description": "The stylesheet.",
      "content": {
       "text/css": {}
      }
     },
     "404": {
      "description": "This release carries no React screens.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/owner/react.js": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "The owner page's React screens",
    "description": "The owner page's React screens (packages/arena-web/dist/owner.js). Where a screen exists, the page mounts it in place of its own panel.\n\nAccess: none\n\nReturns: 200 JavaScript module; 404 when this release carries no React screens\n\nSource: `packages/arena-node/src/server.js` line 4762.",
    "operationId": "get_owner_react_js",
    "responses": {
     "200": {
      "description": "The bundle.",
      "content": {
       "text/javascript": {}
      }
     },
     "404": {
      "description": "This release carries no React screens.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/owner/referrer/name": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Name a referral program",
    "description": "Names a referral program: the name signed by the program's key and sent to the seats, so the explorer and Health show it (kanban #675).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner-style signed request (the owner key)\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 6470.",
    "operationId": "post_owner_referrer_name",
    "requestBody": {
     "required": true,
     "description": "Signed request, args {slug, name}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/referrer/setup": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Create a referral program",
    "description": "A referral program: a client of kind referrer with a new key, earning the website fees of the entries its link brings (kanban #675).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner-style signed request (the owner key)\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 6470.",
    "operationId": "post_owner_referrer_setup",
    "requestBody": {
     "required": true,
     "description": "Signed request, args {name}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/roles": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Change the node's advertised roles",
    "description": "Changes the roles the node advertises (owner-signed, {action: 'roles', args: {roles, custody, post}}): any of game, verify, settlement and relay, plus custody (guardian_capable). It does this with an advertisement update of its bond, paid from the bond wallet. Without post: the plan (fee), checked with testmempoolaccept. With post: true, both transactions are sent. The census reads the new roles 6 blocks later.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 JSON {ok, plan{before{roles, custody}, after{roles, custody}, bond, feeSats, countsAfter}, update{txid}|null}; 400 {ok:false, why} (no bond, no change, an unknown role, the wallet too small, the mempool refuses); 401 not the owner; 501 no bond wallet named (ARENA_BOND_CLI), or an installed node\n\nSource: `packages/arena-node/src/server.js` line 4744.",
    "operationId": "post_owner_roles",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"liquidity/new-address\", args {}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok:true, address:\"tb1p\u2026\"}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "This node runs no liquidity provider service.",
      "content": {
       "application/json": {}
      }
     },
     "502": {
      "description": "The provider service did not answer or failed.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/rounds": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Rounds this node is drawn for",
    "description": "Each round of the last day and the coming ones this node is drawn for, what it does in it, and the first reason when there is none (kanban #715).\n\nAccess: none\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 5760.",
    "operationId": "get_owner_rounds",
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/owner/seatings": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Missed seatings",
    "description": "Seatings this node was drawn for and missed, with a warning from three in a row.\n\nAccess: none\n\nReturns: 200 JSON {missedInARow, warning, rounds[up to 20]}\n\nSource: `packages/arena-node/src/server.js` line 3537.",
    "operationId": "get_owner_seatings",
    "responses": {
     "200": {
      "description": "{missedInARow, warning, rounds[up to 20]}.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/owner/services": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] The node's services and their state",
    "description": "The owner page's Services card. It lists every service of the installed node (Bitcoin Core or the chain bridge, Tor, LND, the gateway, the guardian inside the seat, the seat, its tunnel, the liquidity provider), whether it runs, and what it answers (LND synced, the gateway's federations, the public address reaching this node). It is the same view as `arenanode status` on the node's machine.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, version, instance, port, publicUrl, roles, settings, command, services:[{id, title, running, pid, detail, inside, probe:{ok, says}}]}; 401/403 when not the owner; 501 for a node not started from the installer's arena.conf\n\nSource: `packages/arena-node/src/server.js` line 4649.",
    "operationId": "post_owner_services",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"services\", args {}, atMs, sig} (BIP-340 over [node, action, args, atMs]), or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok:true, version, instance, port, publicUrl, roles, settings:\"arena.conf\", command:\"arenanode\", services:[{id:\"lnd\", title:\"Lightning (LND)\", running:true, pid, detail, probe:{ok:true, says:\"synced at block \u2026\"}}]}.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Not signed by the owner.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "This node was not started from the installer's arena.conf.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/owner/settings": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Set store settings",
    "description": "Sets the store settings (automatic updates, source seats).\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, settings}; 401/403/409\n\nSource: `packages/arena-node/src/server.js` line 3726.",
    "operationId": "post_owner_settings",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"settings\", args {autoUpdate, sources[]}, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, settings}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Node has no owner yet.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/standing": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Node standing and bond_min",
    "description": "This node's standing in recent censuses and the bond_min floor and rises.\n\nAccess: none\n\nReturns: 200 JSON node standing (own weight, brackets, headroom) + bondMin {inForce, noticeBlocks, censuses, pending} + warnings[]\n\nSource: `packages/arena-node/src/server.js` line 3553.",
    "operationId": "get_owner_standing",
    "responses": {
     "200": {
      "description": "Standing + bondMin {inForce, noticeBlocks, censuses, pending} + warnings[].",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/owner/stay": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "[signed] Take back a leave",
    "description": "Takes back a leave; new rounds are taken again.\n\n**Needs the node owner: a request signed by the claimed owner key (BIP-340 JSON or a NIP-98 kind 27235 event).**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: owner's signed JSON request {pubkey, action, args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event; key must be the claimed owner\n\nReturns: 200 {ok, leavingAtMs:null}; 401/403/409\n\nSource: `packages/arena-node/src/server.js` line 3727.",
    "operationId": "post_owner_stay",
    "requestBody": {
     "required": true,
     "description": "Owner-signed request {pubkey, action:\"stay\", args, atMs, sig} (BIP-340 over [node, action, args, atMs], within 2 min, once) or a Nostr kind 27235 event.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, leavingAtMs:null}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Body is not JSON.",
      "content": {
       "application/json": {}
      }
     },
     "401": {
      "description": "Signature or request does not verify (stale, replayed or malformed).",
      "content": {
       "application/json": {}
      }
     },
     "403": {
      "description": "Key is not the claimed owner.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "Node runs without an owner area.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Node has no owner yet.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/owner/version": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "The release this node runs",
    "description": "The release this node runs: its VERSION and COMMIT (the release root's files, null when run from a source checkout), the protocol versions it speaks, and how it is updated. Public, as /owner/standing.\n\nAccess: none\n\nReturns: 200 JSON {node, version, commit, latest, protocols, update}\n\nSource: `packages/arena-node/src/server.js` line 4248.",
    "operationId": "get_owner_version",
    "responses": {
     "200": {
      "description": "{node, version (e.g. 0.1.0-rc.17) or null, commit or null, latest {latest, why, checkedMs, newer} from the signed release/latest.json, protocols: [1..16], update: how to update}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/payments": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Gifts, zaps and items bought since a time",
    "description": "Every donation, zap and item purchase this seat kept after a time, oldest first - what the explorer reads besides /txs. Each seat keeps every one of its network.\n\nAccess: none\n\nReturns: 200 JSON {seat, gifts[], items[]}\n\nSource: `packages/arena-node/src/server.js` line 7531.",
    "operationId": "get_payments",
    "parameters": [
     {
      "name": "since",
      "in": "query",
      "required": false,
      "description": "Kept after this time, ms since 1970. Default 0.",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "At most this many of each list, 1 to 500. Default 200.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{seat, gifts: [{id, kind, item, donor, gameName, federation, txid, totalMsat, outputs, atMs, keptMs}], items: [{id, kind, item, player, gameName, itemId, priceSat, federation, txid, totalMsat, outputs, atMs, keptMs}]}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/payout-address": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "[signed] Name where winnings are sent",
    "description": "Names where a player's winnings are sent.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: Ed25519 signature by the entry's session key; first address stands\n\nReturns: 201 JSON {entry, address, state:NAMED, why}; 400/403/404/409\n\nSource: `packages/arena-node/src/server.js` line 5482.",
    "operationId": "post_payout_address",
    "parameters": [
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Lightning address (UTF-8) followed by a 64-byte Ed25519 signature of the entry's session key.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "{entry, address, state:NAMED, why}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Bad entry, too short, or not a Lightning address.",
      "content": {
       "text/plain": {}
      }
     },
     "403": {
      "description": "Not signed by the session key.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such entry.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Another address already stands.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/pending": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Grids waiting for their beacon, peg-ins confirming",
    "description": "What the network is waiting for, as this node reads its own chain. Every grid published but not yet posted: its publication (found in the node's last 300 blocks), its beacon block (read from its own headers) and how deep it is. Every peg-in that the gateway claims name as confirming, counted against the federation's finality. The health page and the mining dashboard merge this across nodes. The chain part names this node's tip and the other tips it knows within 12 blocks. A rival with the same work is a split that the next block decides; everything else in the answer counts on this node's own branch.\n\nAccess: none\n\nReturns: 200 JSON {ok, node, tip, tipHash, nowMs, chain{hash, height, rivals[{hash, height, status, forkHeight, work: same|more|less}]}, grids[{game, firstWindowMs, firstCloseMs, lastCloseMs, slots, committeeTimeMs, federation, publication{txid, height, confirmations, inMempool}, beacon{height, depth, needed, medianTimeMs}, stage}], pegIns[{federation, node, txid, vout, sats, confirmations, finality, onChain}]}; 503 when the node reads no chain\n\nSource: `packages/arena-node/src/server.js` line 4324.",
    "operationId": "get_pending",
    "responses": {
     "200": {
      "description": "The ranking; amounts are decimal strings.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "{ok:false, why:\"this node runs no guardian, so it ranks no gateways\"}.",
      "content": {
       "application/json": {}
      }
     },
     "503": {
      "description": "The view could not be read now.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/plugin": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Hosted game as a package",
    "description": "A hosted game as a package for another seat's plugin store.\n\nAccess: none\n\nReturns: 200 JSON game package (manifest, donation set, adapters, clients) (cache 60 s); 404/409/500\n\nSource: `packages/arena-node/src/server.js` line 4156.",
    "operationId": "get_plugin",
    "parameters": [
     {
      "name": "game",
      "in": "query",
      "required": true,
      "description": "Game id, 64 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Game package: manifest, donation set, adapters, clients (cache 60 s).",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "No such game.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Cores are not files it can hand out.",
      "content": {
       "text/plain": {}
      }
     },
     "500": {
      "description": "Files unreadable.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/postings": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Signed transcript postings",
    "description": "Each signer node's signed word that it posted the run's transcript.\n\nAccess: none\n\nReturns: 200 octet-stream fixed-size signed postings, header x-postings\n\nHeaders: `x-postings`\n\nSource: `packages/arena-node/src/server.js` line 4969.",
    "operationId": "get_postings",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Fixed-size signed postings.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     }
    }
   }
  },
  "/present": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Say present for a seating",
    "description": "A drawn node says it is present for a round's seating.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: signature by a node drawn for that round and role; only when seating is on (ARENA_SEATING=1)\n\nReturns: 201 \"present kept\"; 409\n\nSource: `packages/arena-node/src/server.js` line 6057.",
    "operationId": "post_present",
    "requestBody": {
     "required": true,
     "description": "PRESENT message.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "\"present kept\"",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such door: seating is off (ARENA_SEATING unset).",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   },
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "PRESENTs held for a round",
    "description": "PRESENTs held for a round.\n\nAccess: none; only when seating is on (ARENA_SEATING=1)\n\nReturns: 200 JSON {presents:[{role, node, present}]}; 400\n\nSource: `packages/arena-node/src/server.js` line 6076.",
    "operationId": "get_present",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{presents[]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such door: seating is off (ARENA_SEATING unset).",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/presents": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Many PRESENTs in one post",
    "description": "Many PRESENTs in one post.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: each checked as /present; only when seating is on (ARENA_SEATING=1)\n\nReturns: 201 JSON {ok, taken, refused[]}; 400\n\nSource: `packages/arena-node/src/server.js` line 6063.",
    "operationId": "post_presents",
    "requestBody": {
     "required": true,
     "description": "PRESENT messages back to back.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "{ok, taken, refused[]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such door: seating is off (ARENA_SEATING unset).",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/price-attested": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Hand over an attested price",
    "description": "Hands over an attested price sample or tape to keep.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; must carry the round committee's threshold of signatures\n\nReturns: 200 JSON {ok}; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5147.",
    "operationId": "post_price_attested",
    "requestBody": {
     "required": true,
     "description": "{round, kind: \"sample\"|\"tape\", k?, priceCents?, prices?, sigs[]}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not a price round, or the committee threshold does not stand.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/price-reading": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] A committee seat's price reading",
    "description": "A committee seat's own signed price reading for a price round; a sample is the median of the readings, nobody proposes a price (protocol 5).\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: the committee seat's signature\n\nReturns: 200 JSON; 400/409\n\nSource: `packages/arena-node/src/server.js` line 6167.",
    "operationId": "post_price_reading",
    "requestBody": {
     "required": true,
     "description": "The signed reading.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "The reading kept.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not JSON.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "The reading does not check.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/price-samples": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Attested price samples of a round",
    "description": "Attested price samples and tape this seat holds for a price round.\n\nAccess: none\n\nReturns: 200 JSON {round, samples[], tape, feed}; 400\n\nSource: `packages/arena-node/src/server.js` line 5132.",
    "operationId": "get_price_samples",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "since",
      "in": "query",
      "required": false,
      "description": "Only samples from this tick on.",
      "schema": {
       "type": "integer"
      },
      "example": 0
     },
     {
      "name": "ks",
      "in": "query",
      "required": false,
      "description": "Comma list of up to 4 sample numbers k.",
      "schema": {
       "type": "string"
      },
      "example": "0,1"
     }
    ],
    "responses": {
     "200": {
      "description": "{round, samples[], tape, feed}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/price-sign": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Ask this seat to sign a price",
    "description": "Asks this seat to sign a price sample or opening tape it read too.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; signed only if within 0.05 % of this seat's own reading for that moment, a reading no older than 5 s\n\nReturns: 200 JSON {ok, key, signature}; 400/404/409\n\nSource: `packages/arena-node/src/server.js` line 5147.",
    "operationId": "post_price_sign",
    "requestBody": {
     "required": true,
     "description": "{round, kind:\"sample\", k, priceCents} or {round, kind:\"tape\", prices[]}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, key, signature}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not within 0.05 % of a fresh (5 s) own reading, wrong time, or another price signed.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/proof-pull": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Pull a two-first-marks proof now",
    "description": "Asks this node to pull and verify a two-first-marks proof now.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none (proof is checked here, not taken on the asker's word)\n\nReturns: 200 text \"proven\" | \"no proof\"; 400/404\n\nSource: `packages/arena-node/src/server.js` line 4759.",
    "operationId": "post_proof_pull",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "\"proven\" or \"no proof\".",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such entry.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/proposal": {
   "post": {
    "tags": [
     "Operators"
    ],
    "summary": "Submit a config proposal",
    "description": "Submits a config proposal for the ballot.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; proposal signature and its deposit on this seat's chain are checked\n\nReturns: 201 or 200 (already) JSON kept proposal; 400/422 {ok:false, why}\n\nSource: `packages/arena-node/src/server.js` line 3785.",
    "operationId": "post_proposal",
    "requestBody": {
     "required": true,
     "description": "{proposal: hex of body + 64-byte signature, blockHash: 64 hex}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "Proposal kept.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Held already.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed proposal or block hash.",
      "content": {
       "application/json": {}
      }
     },
     "422": {
      "description": "Deposit or signature does not stand.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "No such door: the feature is off on this node.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/proposals": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Ballot proposals held",
    "description": "Lists the ballot config proposals this seat holds.\n\nAccess: none (only when the node keeps a ballot)\n\nReturns: 200 JSON {proposals[]}\n\nSource: `packages/arena-node/src/server.js` line 3781.",
    "operationId": "get_proposals",
    "responses": {
     "200": {
      "description": "{proposals[]}.",
      "content": {
       "application/json": {}
      }
     },
     "404": {
      "description": "No such door: the feature is off on this node.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/randomness": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Round randomness beacon",
    "description": "The round's randomness beacon so the client seeds the same world.\n\nAccess: none\n\nReturns: 200 octet-stream 32-byte beacon block hash, header x-height; 404/409\n\nHeaders: `x-height`\n\nSource: `packages/arena-node/src/server.js` line 6328.",
    "operationId": "get_randomness",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "32-byte beacon block hash.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "No beacon yet, or none read here.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/reach-check": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Connect back to the asker (installer reach test)",
    "description": "Checks whether the internet can reach a new node. The seat connects back only to the asking address (it must be public), on the named port, asks GET /reach-nonce and says only whether the nonce came back. It does not say what it read, or whether the port refused or did not answer. Limit: 6 checks a minute per address, 60 in all. The node installer's direct-connection test uses it (ruling 7).\n\nAccess: none\n\nReturns: 200 JSON {ok, reached, address, port, ms?}; 400; 429\n\nSource: `packages/arena-node/src/server.js` line 5317.",
    "operationId": "post_reach_check",
    "requestBody": {
     "required": true,
     "description": "{port: 1-65535, nonce: 16-64 characters of [A-Za-z0-9_-]}",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok: true, reached, address (the asker's public address as this seat saw it), port, ms (when reached)}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Bad port or nonce, or the asker's address is not public (the address is named).",
      "content": {
       "application/json": {}
      }
     },
     "429": {
      "description": "More than 6 checks a minute from this address, or 60 in all.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/reach-nonce": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Direct-check nonce for the installer",
    "description": "Lets the installer's direct check reach an installed node on its own port: the seats ask this address, and the node answers with the installer's nonce (kanban #734).\n\nAccess: none\n\nReturns: 200 text: the nonce the installer wrote into this node's home, while it is under 5 minutes old; else 404\n\nSource: `packages/arena-node/src/server.js` line 7543.",
    "operationId": "get_reach_nonce",
    "responses": {
     "200": {
      "description": "The nonce from <ARENA_HOME>/reach-nonce, written by the installer less than 5 minutes ago.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No nonce, or one older than 5 minutes.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/receipts": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Receipts of a run's marks",
    "description": "Receipts for a run's marks, so a reconnecting client can recover them.\n\nAccess: none\n\nReturns: 200 octet-stream receipts, header x-receipts\n\nHeaders: `x-receipts`\n\nSource: `packages/arena-node/src/server.js` line 6295.",
    "operationId": "get_receipts",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Receipts back to back.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     }
    }
   }
  },
  "/referral-fees": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "What each website earned",
    "description": "The website payouts of the settlements this seat indexed, per website payout key: their sum and count, and the total (kanban #676).\n\nAccess: none\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 9278.",
    "operationId": "get_referral_fees",
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/referral-name": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Keep a referral program's name",
    "description": "Keeps a referral program's name when its site key signed it, and hands it on to every seat once (kanban #675).\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 9291.",
    "operationId": "post_referral_name",
    "requestBody": {
     "required": true,
     "description": "The name, the site key and its signature.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/refused-first-mark": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "First mark this node refused",
    "description": "Serves an on-time first mark this node refused, for peers closing the round.\n\nAccess: none\n\nReturns: 200 JSON {mark, why}; 404\n\nSource: `packages/arena-node/src/server.js` line 4097.",
    "operationId": "get_refused_first_mark",
    "parameters": [
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{mark, why}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "None refused.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/refused-lock": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "Register a lock for a refused round",
    "description": "Registers a stake locked for a round this node refuses so it can be returned at once.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; checked against held handout, claim key and federation\n\nReturns: 201 text with forfeit link; 400/404/409\n\nSource: `packages/arena-node/src/server.js` line 5342.",
    "operationId": "post_refused_lock",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "{fields, outpoint \"txid:index\", federation? (64 hex, any-federation rounds)}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "Kept for its return, with the forfeit link.",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not refused here, or the lock does not check.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/replay": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Game replay page",
    "description": "Serves the round's game replay page.\n\nAccess: none\n\nReturns: 200 text/html game replay page; 400/404\n\nSource: `packages/arena-node/src/server.js` line 4805.",
    "operationId": "get_replay",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": false,
      "description": "Entry id, 64 hex; read by the page, not by the node.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The game's replay page.",
      "content": {
       "text/html": {}
      }
     },
     "400": {
      "description": "No round named.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round, game not hosted, or no replay page.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/replay-budget": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Measured replay speed and capacity",
    "description": "This seat's measured replay speed and how many players a round can hold in the result window. Also its storage cleanup: transcripts are deleted when the claim window ends (lastPrune), and unused rounds are deleted with their committee and seating records after their windows (unusedRounds).\n\nAccess: none\n\nReturns: 200 JSON {speedX, samples, runMs, maxPlayersPerRound, retention, lastPrune{atMs, pruned, kept, rows}, unusedRounds{deleted, rows, passes, lastAtMs, caughtUpAtMs}}\n\nSource: `packages/arena-node/src/server.js` line 5670.",
    "operationId": "get_replay_budget",
    "parameters": [
     {
      "name": "runMs",
      "in": "query",
      "required": false,
      "description": "Run length in ms; default 82000.",
      "schema": {
       "type": "integer"
      },
      "example": 82000
     }
    ],
    "responses": {
     "200": {
      "description": "{speedX, samples, runMs, maxPlayersPerRound, retention, lastPrune, unusedRounds}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/replay/client.js": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Client bundle for the replay page",
    "description": "Serves the protocol decoders/client bundle for the replay page.\n\nAccess: none\n\nReturns: 200 text/javascript arena-client bundle\n\nSource: `packages/arena-node/src/server.js` line 4842.",
    "operationId": "get_replay_client_js",
    "responses": {
     "200": {
      "description": "arena-client bundle.",
      "content": {
       "text/javascript": {}
      }
     }
    }
   }
  },
  "/replay/core.js": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Game core for a replay",
    "description": "Serves the game rules (core) the round names, for replay.\n\nAccess: none\n\nReturns: 200 text/javascript core bundle the round names; 404/409\n\nSource: `packages/arena-node/src/server.js` line 4819.",
    "operationId": "get_replay_core_js",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Core bundle the round names.",
      "content": {
       "text/javascript": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round, attested game, or no replay bundle.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Core not run here.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/replay/nodes": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Other endpoints holding the run",
    "description": "Other committee endpoints that may hold the run.\n\nAccess: none\n\nReturns: 200 JSON {stable, endpoints[] https}\n\nSource: `packages/arena-node/src/server.js` line 4865.",
    "operationId": "get_replay_nodes",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{stable, endpoints[] https}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/replay/transcript": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Run as JSON for replay",
    "description": "The run as this node replays it, as JSON.\n\nAccess: none\n\nReturns: 200 JSON transcript (ticks, ...) + clock {firstTick, firstMs, lastTick, lastMs}; 400/404\n\nSource: `packages/arena-node/src/server.js` line 4848.",
    "operationId": "get_replay_transcript",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Transcript (ticks, ...) + clock {firstTick, firstMs, lastTick, lastMs}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No transcript held.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/reruns": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Signed re-runs of a result",
    "description": "Signer nodes' re-runs of a suspended result (own one re-signed now).\n\nAccess: none\n\nReturns: 200 octet-stream fixed-size signed re-run results, header x-reruns\n\nHeaders: `x-reruns`\n\nSource: `packages/arena-node/src/server.js` line 5885.",
    "operationId": "get_reruns",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Signed re-run results back to back.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     }
    }
   }
  },
  "/resend-sends": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Propose a winnings re-send",
    "description": "Proposes a re-send of an expired winnings payment.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; checked\n\nReturns: 201 \"re-send checked and kept\"; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5605.",
    "operationId": "post_resend_sends",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "late",
      "in": "query",
      "required": false,
      "description": "Entry id (64 hex) of a late loser's second settlement; omit for the round's own settlement.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Re-send proposal.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "\"re-send checked and kept\"",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/reserve-payout/commit": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Reserve payout: commit",
    "description": "The reserve payout ceremony between guardian seats: a guardian seat's FROST commitment for a payout plan it rebuilt itself.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; every seat rebuilds and checks the plan itself\n\nReturns: 200 JSON {ok, ...}; 400; 501\n\nSource: `packages/arena-node/src/server.js` line 6929.",
    "operationId": "post_reserve_payout_commit",
    "requestBody": {
     "required": true,
     "description": "The plan or plan id, kind, and commitments as the step needs.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok: true, commitment | share | record kept}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not JSON or the plan does not check.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "This node pays no reserves.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/reserve-payout/record": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Reserve payout: record",
    "description": "The reserve payout ceremony between guardian seats: a payout record any seat keeps (a PAID one only with the invoice's preimage).\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; every seat rebuilds and checks the plan itself\n\nReturns: 200 JSON {ok, ...}; 400; 501\n\nSource: `packages/arena-node/src/server.js` line 6929.",
    "operationId": "post_reserve_payout_record",
    "requestBody": {
     "required": true,
     "description": "The plan or plan id, kind, and commitments as the step needs.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok: true, commitment | share | record kept}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not JSON or the plan does not check.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "This node pays no reserves.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/reserve-payout/share": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Reserve payout: share",
    "description": "The reserve payout ceremony between guardian seats: a guardian seat's FROST signature share for that plan, given the commitments.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; every seat rebuilds and checks the plan itself\n\nReturns: 200 JSON {ok, ...}; 400; 501\n\nSource: `packages/arena-node/src/server.js` line 6929.",
    "operationId": "post_reserve_payout_share",
    "requestBody": {
     "required": true,
     "description": "The plan or plan id, kind, and commitments as the step needs.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok: true, commitment | share | record kept}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not JSON or the plan does not check.",
      "content": {
       "application/json": {}
      }
     },
     "501": {
      "description": "This node pays no reserves.",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/reserve-payouts": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Reserve payouts",
    "description": "Every payout from the protocol reserves this seat knows: funding proposals and leaderboard payouts, with plan, state and txid.\n\nAccess: none\n\nReturns: 200 JSON {payouts[]}\n\nSource: `packages/arena-node/src/server.js` line 6942.",
    "operationId": "get_reserve_payouts",
    "responses": {
     "200": {
      "description": "{payouts: [{proposal, kind, state, federation, plan, txid, preimage, ...}]}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/reserves": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Protocol reserves per federation",
    "description": "Per federation this node knows guardians of: its reserve key (guardian seats, threshold, group key, public shares), what the reserves hold and what came in, and the reserve payouts (\u00a727A.9.2).\n\nAccess: none\n\nReturns: 200 JSON {node, totalMsat, entries, federations[{federationId, members, needed, key, heldMsat, paidIn, ...}], paidIn[], payouts[]}\n\nSource: `packages/arena-node/src/server.js` line 6875.",
    "operationId": "get_reserves",
    "parameters": [
     {
      "name": "all",
      "in": "query",
      "required": false,
      "description": "1: list every payment in, not only the newest.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{node, totalMsat, entries, federations, paidIn, payouts}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/results": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Signed player results of a run",
    "description": "Signed player results held for a run.\n\nAccess: none\n\nReturns: 200 octet-stream fixed-size signed results, headers x-results, x-no-quorum?\n\nHeaders: `x-results`, `x-no-quorum`\n\nSource: `packages/arena-node/src/server.js` line 4951.",
    "operationId": "get_results",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Signed results back to back.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     }
    }
   }
  },
  "/reveal": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "Reveal a head-to-head move",
    "description": "A head-to-head player reveals its hidden move (e.g. Rock Paper Scissors).\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none - the reveal must hash to the commitment that entry named, after the round's entry close and before its end, for a move the game offers\n\nReturns: 201 (taken) / 200 (held already) JSON {held, fresh}; 400/403 (identity proof does not verify)/404/409 with the reason\n\nSource: `packages/arena-node/src/server.js` line 5078.",
    "operationId": "post_reveal",
    "parameters": [
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "{move: integer, salt: 64 hex, identity?: {key, sig}}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "{held, fresh}: taken.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Held already.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Bad entry or body.",
      "content": {
       "text/plain": {}
      }
     },
     "403": {
      "description": "Identity proof does not verify.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such entry or round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not head-to-head, or does not match the commitment or window.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/reveals": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Reveals held for a head-to-head round",
    "description": "Every reveal this node holds for a head-to-head round; the other nodes pull these at the round's close so all decide from the same moves.\n\nAccess: none\n\nReturns: 200 JSON {round, reveals:[{entry, move, salt, identity?:{key, sig}}]}; 400/404\n\nSource: `packages/arena-node/src/server.js` line 5235.",
    "operationId": "get_reveals",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{round, reveals:[{entry, move, salt, identity?}]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/roles": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Roles of each census node",
    "description": "Each census node's advertised roles and the federations it guards, for the lobby node list.\n\nAccess: none\n\nReturns: 200 JSON {node, censusHeight, nodes:[{node, endpoint, roles, guardianCapable, serving, custody[], guardianOf[]}]} (cache 60 s); 503\n\nSource: `packages/arena-node/src/server.js` line 3794.",
    "operationId": "get_roles",
    "responses": {
     "200": {
      "description": "{node, censusHeight, nodes[]} (cache 60 s).",
      "content": {
       "application/json": {}
      }
     },
     "503": {
      "description": "Seat reads no census.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/round": {
   "post": {
    "tags": [
     "Builders"
    ],
    "summary": "[signed] Open a round contract",
    "description": "Opens (stores) a round contract on this node after creator, rules, committee, bond-min, game (a template round must carry its question, any other must not), series, federation, gateway, fee and bond checks.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: creator signature over the round id when the contract names a creator (403 otherwise); paying round must be funded (operator list) or of a series this node holds, else 402\n\nReturns: 201 round id bytes; 202 id (stored, beacon not yet); 400/402/403/409/503 text reason\n\nSource: `packages/arena-node/src/server.js` line 3828.",
    "operationId": "post_round",
    "parameters": [
     {
      "name": "creator",
      "in": "query",
      "required": false,
      "description": "BIP-340 signature (128 hex) of the creator over the round id; required when the contract names a creator.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Encoded round contract.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Round id (32 bytes); signer nodes assigned.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "202": {
      "description": "Round id; stored, beacon not yet on chain.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Not a round contract.",
      "content": {
       "text/plain": {}
      }
     },
     "402": {
      "description": "Nobody funded the round.",
      "content": {
       "text/plain": {}
      }
     },
     "403": {
      "description": "Creator signature missing or wrong.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused by a rule (game, series, federation, gateways, fees, bonds, donation set, template event, ...).",
      "content": {
       "text/plain": {}
      }
     },
     "503": {
      "description": "Federation fee rule unreadable.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   },
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Round contract by id",
    "description": "Returns a stored round contract by id.\n\nAccess: none\n\nReturns: 200 octet-stream round contract, header x-state; a template round also x-question, x-outcomes (URI-encoded JSON list), x-resolve-at-ms; 404\n\nHeaders: `x-state`, `x-question`, `x-outcomes`, `x-resolve-at-ms`\n\nSource: `packages/arena-node/src/server.js` line 4373.",
    "operationId": "get_round",
    "parameters": [
     {
      "name": "id",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Encoded round contract.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/round-creator": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Creator signature of a round",
    "description": "The creator signature kept beside a round contract that names its creator.\n\nAccess: none\n\nReturns: 200 text: creator signature hex; 400/404\n\nSource: `packages/arena-node/src/server.js` line 5720.",
    "operationId": "get_round_creator",
    "parameters": [
     {
      "name": "id",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Creator signature, hex.",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "None held.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/round-result": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Signed result of a price round",
    "description": "This seat's signed result of a price round, once the round has ended.\n\nAccess: none\n\nReturns: 200 JSON {ok, round, openCents, closeCents, front, samples, openTick, closeTick, committee, needed, key, signature}; 400/404/409\n\nSource: `packages/arena-node/src/server.js` line 5141.",
    "operationId": "get_round_result",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{ok, round, openCents, closeCents, front, samples, openTick, closeTick, committee, needed, key, signature}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not ended, or no attested ends.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/rounds": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Lobby listing of announced rounds",
    "description": "Lobby listing of announced rounds this node holds, each row signed by the node.\n\nAccess: none\n\nReturns: 200 JSON {node, nowMs, rounds:[{id, phase, entryOpen, game, event? {question, outcomes, resolveAtMs}, outcome, startTime, endTime, committee, stakeMsat, free (development rounds only), wallet, joined, playing, watching, names, needed, signerNodes, sig, ...}], games}\n\nSource: `packages/arena-node/src/server.js` line 4188.",
    "operationId": "get_rounds",
    "parameters": [
     {
      "name": "ahead",
      "in": "query",
      "required": false,
      "description": "Only rounds starting within this many ms, or hours with an h suffix (e.g. 72h).",
      "schema": {
       "type": "string"
      },
      "example": "72h"
     },
     {
      "name": "next",
      "in": "query",
      "required": false,
      "description": "At most this many upcoming rounds per series. With neither next nor ahead the node lists the next 8 of each series (kanban #742).",
      "schema": {
       "type": "integer"
      },
      "example": 8
     },
     {
      "name": "all",
      "in": "query",
      "required": false,
      "description": "1: every announced round this node holds, unbounded (slow at grid density: tens of thousands of rows). Without it, a bare /rounds is next=8.",
      "schema": {
       "type": "integer"
      },
      "example": 1
     }
    ],
    "responses": {
     "200": {
      "description": "{node, nowMs, rounds[] (each signed; event for a template round), games}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/rounds/react.js": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "The rounds page's React bundle",
    "description": "The rounds page's React bundle (packages/arena-web/dist/rounds.js). /rounds draws its stat and round cards with it; without it, the page uses its own drawing.\n\nAccess: none\n\nReturns: 200 JavaScript module; 404 when this release carries no React rounds page\n\nSource: `packages/arena-node/src/server.js` line 4752.",
    "operationId": "get_rounds_react_js",
    "responses": {
     "200": {
      "description": "The bundle.",
      "content": {
       "text/javascript": {}
      }
     },
     "404": {
      "description": "This release carries no React rounds page.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/season": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Leaderboard of a game",
    "description": "One game's leaderboard per player over its FINAL rounds in a time window. It is for display, not an authority. By default it uses this node's own rounds; with scope=network it uses every seat's rounds, and a round counts only when 3 seats hand in byte-identical accounts of it.\n\nAccess: none\n\nReturns: 200 JSON {node, game {name, ids}, days, from, to, rows:[{rank, player, name, rounds, wins, netMsat, stakedMsat, paidMsat, bestScore, lastPlayed}], rounds, leftOut, unchecked} (cache 30 s); with scope=network also {scope, agree, seats {asked, answered}}; 400/404/500\n\nSource: `packages/arena-node/src/server.js` line 4412.",
    "operationId": "get_season",
    "parameters": [
     {
      "name": "game",
      "in": "query",
      "required": true,
      "description": "A hosted game's name (every version under it) or one game id in hex.",
      "schema": {
       "type": "string"
      },
      "example": "nextblock"
     },
     {
      "name": "days",
      "in": "query",
      "required": false,
      "description": "Window in whole days, 1 to 90; default 7.",
      "schema": {
       "type": "integer"
      },
      "example": 7
     },
     {
      "name": "scope",
      "in": "query",
      "required": false,
      "description": "network: ask every seat this node knows for its rounds (GET /season-rounds) and merge them with its own. A round counts only when 3 distinct seats hand in byte-identical accounts of it, so no single seat can forge a row. Omitted: this node's own rounds.",
      "schema": {
       "type": "string"
      },
      "example": "network"
     }
    ],
    "responses": {
     "200": {
      "description": "{node, game:{name, ids}, days, from, to, fromMs, toMs, rows:[{rank, player, name, rounds, wins, netMsat, stakedMsat, paidMsat, bestScore, lastPlayed}], rounds, leftOut, unchecked} (cache 30 s). With scope=network also scope: 'network', agree: 3, seats: {asked, answered}; leftOut includes the rounds without agreement.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "No game named, days out of range, or a scope other than network.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No hosted game by that name.",
      "content": {
       "text/plain": {}
      }
     },
     "500": {
      "description": "Leaderboard could not be built.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/season-rounds": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Leaderboard rounds held by this node",
    "description": "The rounds this node's own leaderboard is built from: FINAL results and the amounts its ACCEPTED settlements paid. Another node merges them into its network leaderboard. The weekly top-3 badge merges on the round keys too.\n\nAccess: none\n\nReturns: 200 JSON {node, game {ids}, days, fromMs, toMs, roundKeys: true, rounds:[{roundId, gameId, startMs, void, entries:[{player, name, stakeMsat, payoutMsat, outcome, score, roundKey}]}]} - msat and startMs as decimal strings, payoutMsat null while not settled here, roundKey the key the entry joined under (cache 30 s); 400/404\n\nSource: `packages/arena-node/src/server.js` line 4440.",
    "operationId": "get_season_rounds",
    "parameters": [
     {
      "name": "game",
      "in": "query",
      "required": true,
      "description": "A hosted game's name, one game id in hex, or a comma list of game ids in hex (how a network leaderboard asks).",
      "schema": {
       "type": "string"
      },
      "example": "nextblock"
     },
     {
      "name": "days",
      "in": "query",
      "required": false,
      "description": "Window in whole days, 1 to 90; default 7.",
      "schema": {
       "type": "integer"
      },
      "example": 7
     }
    ],
    "responses": {
     "200": {
      "description": "{node, game:{ids}, days, fromMs, toMs, roundKeys: true, rounds:[{roundId, gameId, startMs, void, entries:[{player, name, stakeMsat, payoutMsat, outcome, score, roundKey}]}]} (cache 30 s).",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "No game named, or days out of range.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No hosted game by that name.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/seating": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Hand over a seating certificate",
    "description": "Hands over a seating certificate; a differing one is kept as proof of equivocation.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: certificate checked against this node's draw; only when seating is on (ARENA_SEATING=1)\n\nReturns: 201 JSON (kept) / 200 (equivocation proof); 400/409\n\nSource: `packages/arena-node/src/server.js` line 6050.",
    "operationId": "post_seating",
    "requestBody": {
     "required": true,
     "description": "Seating certificate.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Kept.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Differs from the held one: kept as equivocation proof.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such door: seating is off (ARENA_SEATING unset).",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   },
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Seating certificate of a round",
    "description": "The seating certificate held for a round and role.\n\nAccess: none; only when seating is on (ARENA_SEATING=1)\n\nReturns: 200 JSON {cert}; 400/404\n\nSource: `packages/arena-node/src/server.js` line 6080.",
    "operationId": "get_seating",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "role",
      "in": "query",
      "required": true,
      "description": "\"game\" or \"settlement\".",
      "schema": {
       "type": "string"
      },
      "example": "game"
     }
    ],
    "responses": {
     "200": {
      "description": "{cert}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "None held, or seating off.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/seating-batch": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Seating state of many rounds",
    "description": "Seating state of many rounds in one read.\n\nAccess: none; only when seating is on (ARENA_SEATING=1)\n\nReturns: 200 JSON {rounds:{id:{presents, sig, cert}}}; 400\n\nSource: `packages/arena-node/src/server.js` line 6067.",
    "operationId": "get_seating_batch",
    "parameters": [
     {
      "name": "rounds",
      "in": "query",
      "required": true,
      "description": "1 to 64 round ids (64 hex), comma-separated.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{rounds:{id:{presents, sig, cert}}}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such door: seating is off (ARENA_SEATING unset).",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/seating-equivocation": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Seating equivocation proofs",
    "description": "Proofs of two seatings for one round.\n\nAccess: none; only when seating is on (ARENA_SEATING=1)\n\nReturns: 200 JSON {equivocations[]}; 400\n\nSource: `packages/arena-node/src/server.js` line 6077.",
    "operationId": "get_seating_equivocation",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{equivocations[]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such door: seating is off (ARENA_SEATING unset).",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/seating-sig": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "This node's seating signature",
    "description": "This node's signature over a round's seating.\n\nAccess: none; only when seating is on (ARENA_SEATING=1)\n\nReturns: 200 JSON this node's seating signature; 400/404\n\nSource: `packages/arena-node/src/server.js` line 6079.",
    "operationId": "get_seating_sig",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "role",
      "in": "query",
      "required": true,
      "description": "\"game\" or \"settlement\".",
      "schema": {
       "type": "string"
      },
      "example": "game"
     }
    ],
    "responses": {
     "200": {
      "description": "Seating signature.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "None signed, or seating off.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/sell": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "[signed] Sell shares an entry holds",
    "description": "A market player sells shares its entry holds; matched in a batch, paid at settlement.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: Ed25519 signature by the entry's session key over the sell id\n\nReturns: 201 JSON {ok, id, fresh}; 200 held already; 400/403/409 (after market close)\n\nSource: `packages/arena-node/src/server.js` line 5178.",
    "operationId": "post_sell",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "{entry, outcome, price, sharesMsat, nonce, signature}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "{ok, id, fresh}.",
      "content": {
       "application/json": {}
      }
     },
     "200": {
      "description": "Held already.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "403": {
      "description": "Not signed by the entry's session key.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "After market close or refused.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/send-commit": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Winnings send auth, round one",
    "description": "Round one of authorising a winnings send.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; node answers only for the message it rebuilt\n\nReturns: 200 octet-stream nonce commitment; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5589.",
    "operationId": "post_send_commit",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "late",
      "in": "query",
      "required": false,
      "description": "Entry id (64 hex) of a late loser's second settlement; omit for the round's own settlement.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "kind",
      "in": "query",
      "required": false,
      "description": "\"auth\" (default) or \"resend\".",
      "schema": {
       "type": "string"
      },
      "example": "auth"
     },
     {
      "name": "attempt",
      "in": "query",
      "required": false,
      "description": "Re-send attempt number.",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "hash",
      "in": "query",
      "required": false,
      "description": "Invoice hash the asker rebuilt.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Nonce commitment.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/send-share": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Winnings send auth, round two",
    "description": "Round two of authorising a winnings send.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; same rule\n\nReturns: 200 octet-stream signature share; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5595.",
    "operationId": "post_send_share",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "late",
      "in": "query",
      "required": false,
      "description": "Entry id (64 hex) of a late loser's second settlement; omit for the round's own settlement.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "kind",
      "in": "query",
      "required": false,
      "description": "\"auth\" (default) or \"resend\".",
      "schema": {
       "type": "string"
      },
      "example": "auth"
     },
     {
      "name": "attempt",
      "in": "query",
      "required": false,
      "description": "Re-send attempt number.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Encoded commitment list.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Signature share.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/series": {
   "post": {
    "tags": [
     "Builders"
    ],
    "summary": "[signed] Take a grid series",
    "description": "Takes a grid series (one post per table) whose rounds this node then writes.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: creator signature in the line when the series names a creator (403); must be funded (402)\n\nReturns: 200 JSON {ok, series, rounds, held}; 400/402/403/409 text\n\nSource: `packages/arena-node/src/server.js` line 4358.",
    "operationId": "post_series",
    "requestBody": {
     "required": true,
     "description": "Series line (a grid series).",
     "content": {
      "text/plain": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ok, series, rounds, held}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Not a grid series line.",
      "content": {
       "text/plain": {}
      }
     },
     "402": {
      "description": "Series not funded.",
      "content": {
       "text/plain": {}
      }
     },
     "403": {
      "description": "Creator signature missing or wrong.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   },
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Series this node writes",
    "description": "Lists the round series this node writes and how far ahead.\n\nAccess: none\n\nReturns: 200 JSON {node, nowMs, series:[summary]}\n\nSource: `packages/arena-node/src/server.js` line 4367.",
    "operationId": "get_series",
    "responses": {
     "200": {
      "description": "{node, nowMs, series:[summary]}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/series-publication": {
   "post": {
    "tags": [
     "Builders"
    ],
    "summary": "Prove a series publication",
    "description": "Proves a series' on-chain publication and its fee, for the publisher payout.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; tx must be the series' first confirmed publication on this seat's chain and parents must prove its fee\n\nReturns: 200 JSON {txid, feeSats, payoutSats}; 400/404/409/422/503\n\nSource: `packages/arena-node/src/server.js` line 5698.",
    "operationId": "post_series_publication",
    "requestBody": {
     "required": true,
     "description": "{series: 64 hex, tx: hex, parents: [hex]}.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "{txid, feeSats, payoutSats}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such series.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Not the first confirmed publication.",
      "content": {
       "text/plain": {}
      }
     },
     "422": {
      "description": "Parents do not prove the fee.",
      "content": {
       "text/plain": {}
      }
     },
     "503": {
      "description": "Seat cannot read its chain.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/series-template": {
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "A series template",
    "description": "A series' template as its text line, for a page checking a series round it was given. The reader trusts it only if it hashes to the id it asked for.\n\nAccess: none\n\nReturns: 200 text/plain the template line (cache 1 h); 400; 404\n\nSource: `packages/arena-node/src/server.js` line 5335.",
    "operationId": "get_series_template",
    "parameters": [
     {
      "name": "id",
      "in": "query",
      "required": true,
      "description": "The series id, 64 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The template line.",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "No valid id.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such series here.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/served": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Who served rounds in a window",
    "description": "The nodes that served rounds in a time window, from the FINAL signatures this seat holds, each checked against its committee; the root lets seats compare.\n\nAccess: none\n\nReturns: 200 JSON {node, fromMs, toMs, rounds, root, nodes, refused, held?}; 400\n\nSource: `packages/arena-node/src/server.js` line 5302.",
    "operationId": "get_served",
    "parameters": [
     {
      "name": "to",
      "in": "query",
      "required": true,
      "description": "Window end, unix ms.",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "from",
      "in": "query",
      "required": false,
      "description": "Window start, unix ms; at most 7 days before to.",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "finals",
      "in": "query",
      "required": false,
      "description": "1: also hand over the rounds with committees and FINALs read.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{node, fromMs, toMs, rounds, root, nodes, refused, held?}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Bad window.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/settle-commit": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Settlement signing, round one",
    "description": "Round one of signing the round's settlement of losers' locks.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; node answers only for the txid it rebuilt\n\nReturns: 200 octet-stream nonce commitment; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5459.",
    "operationId": "post_settle_commit",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "txid",
      "in": "query",
      "required": true,
      "description": "Settlement txid the asker rebuilt.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": false,
      "description": "Entry id (64 hex) of a late loser's second settlement.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "federation",
      "in": "query",
      "required": false,
      "description": "Federation id (64 hex) for one federation's settlement of an any-federation round.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Nonce commitment.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/settle-sends": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Kept winnings send plan",
    "description": "The winnings send plan this node keeps for a round.\n\nAccess: none\n\nReturns: 200 JSON kept send plan; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5510.",
    "operationId": "get_settle_sends",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "late",
      "in": "query",
      "required": false,
      "description": "Entry id (64 hex) of a late loser's second settlement; omit for the round's own settlement.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Kept send plan.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    }
   },
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Propose winnings send plans",
    "description": "Coordinator proposes winnings send plans; seat signs if they stand.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; plans checked here\n\nReturns: 201 octet-stream this seat's signature over the plan id; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5523.",
    "operationId": "post_settle_sends",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "late",
      "in": "query",
      "required": false,
      "description": "Entry id (64 hex) of a late loser's second settlement; omit for the round's own settlement.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Array of send plans.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "201": {
      "description": "This seat's signature over the plan id.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/settle-share": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Settlement signing, round two",
    "description": "Round two of the settlement signing.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; same rule\n\nReturns: 200 octet-stream signature share; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5465.",
    "operationId": "post_settle_share",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": false,
      "description": "Entry id (64 hex) of a late loser's second settlement.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "federation",
      "in": "query",
      "required": false,
      "description": "Federation id (64 hex) for one federation's settlement of an any-federation round.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Encoded commitment list.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Signature share.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/settle-signature": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Hand over the settlement signature",
    "description": "Hands over the combined settlement signature.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; checked\n\nReturns: 201 \"settlement signature kept\"; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5473.",
    "operationId": "post_settle_signature",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": false,
      "description": "Entry id (64 hex) of a late loser's second settlement.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "federation",
      "in": "query",
      "required": false,
      "description": "Federation id (64 hex) for one federation's settlement of an any-federation round.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "64-byte combined signature.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "\"settlement signature kept\"",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/settle-taken": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "[signed] Hand in signed plan agreement",
    "description": "Hands in the seats' signed agreement on a send plan.\n\n**Needs a signature: the body or record must be signed by the key named below.**\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; checked against kept plan\n\nReturns: 201 text \"N of M seats' signed agreement kept\"; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5544.",
    "operationId": "post_settle_taken",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "late",
      "in": "query",
      "required": false,
      "description": "Entry id (64 hex) of a late loser's second settlement; omit for the round's own settlement.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Certificate: 128-byte signed acceptances back to back.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "\"N of M seats' signed agreement kept\"",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   },
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Signed agreement of a send plan",
    "description": "Serves the signed agreement a settlement plan was taken by.\n\nAccess: none\n\nReturns: 200 JSON {planId, certificate}; 404\n\nSource: `packages/arena-node/src/server.js` line 5554.",
    "operationId": "get_settle_taken",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "late",
      "in": "query",
      "required": false,
      "description": "Entry id (64 hex) of a late loser's second settlement; omit for the round's own settlement.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{planId, certificate}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "None held.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/settled": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Rounds settled since a time",
    "description": "Rounds settled since a time, for seed-only recovery on another device.\n\nAccess: none\n\nReturns: 200 JSON {node, nowMs, since, rounds:[{id, state, madeMs, payouts[], refunds}]}\n\nSource: `packages/arena-node/src/server.js` line 5753.",
    "operationId": "get_settled",
    "parameters": [
     {
      "name": "since",
      "in": "query",
      "required": true,
      "description": "Time in ms (capped to 7 days back).",
      "schema": {
       "type": "integer"
      },
      "example": 0
     }
    ],
    "responses": {
     "200": {
      "description": "{node, nowMs, since, rounds:[{id, state, madeMs, payouts[], refunds}]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/settlement": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Stake and finality of an entry",
    "description": "Where an entry's stake and result finality stand.\n\nAccess: none\n\nReturns: 200 JSON {entry, stake FREE (development rounds only)|SEEN|UNSEEN, finality, finalityWhy, windowClosesAtMs}; 404\n\nSource: `packages/arena-node/src/server.js` line 4625.",
    "operationId": "get_settlement",
    "parameters": [
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{entry, stake FREE|SEEN|UNSEEN, finality, finalityWhy, windowClosesAtMs}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such entry.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/setup-status": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Setup progress",
    "description": "The setup's progress for the dashboards: Core's background sync, the bond's and the peg-in's confirmations (kanban #635).\n\nAccess: none\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 6620.",
    "operationId": "get_setup_status",
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/share": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Sealed stake share for a signer node",
    "description": "Hands one signer node's share of a stake preimage to another signer node.\n\nAccess: no request signature; answer sealed to the asker; refused unless asker is a signer node and run is final with a claimable outcome\n\nReturns: 200 octet-stream sealed share answer, header x-signer-node; 400/409\n\nHeaders: `x-signer-node`\n\nSource: `packages/arena-node/src/server.js` line 4910.",
    "operationId": "get_share",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "signer node",
      "in": "query",
      "required": true,
      "description": "Asking signer node's public key, hex (the parameter name contains a space).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "proof",
      "in": "query",
      "required": false,
      "description": "\"1\" when the asker holds a two-first-marks proof.",
      "schema": {
       "type": "string"
      },
      "example": "1"
     }
    ],
    "responses": {
     "200": {
      "description": "Share answer sealed to the asker.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/slash-owing": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "What filed slash proofs owe",
    "description": "What filed slash proofs owe and to whom at a given height; records nothing.\n\nAccess: none\n\nReturns: 200 JSON {slashHeight, tipHeight, owing:[{node, bond, offence, bondSats, toPlayers, toNodes, toDevelopers, players[], nodes[], ...}]}; 400/404/409\n\nSource: `packages/arena-node/src/server.js` line 5916.",
    "operationId": "get_slash_owing",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "height",
      "in": "query",
      "required": true,
      "description": "Slashing height named by the arbitration set.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{slashHeight, tipHeight, owing[]}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such round or no slash proof.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Height out of range or census unreadable.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/slash-proofs": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Slash proofs filed for a run",
    "description": "Slash proofs this node filed for a run.\n\nAccess: none\n\nReturns: 200 octet-stream fixed-size slash evidence, header x-slash-proofs\n\nHeaders: `x-slash-proofs`\n\nSource: `packages/arena-node/src/server.js` line 6118.",
    "operationId": "get_slash_proofs",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Slash evidence back to back.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     }
    }
   }
  },
  "/slash/{id}": {
   "put": {
    "tags": [
     "Nodes"
    ],
    "summary": "Relay stores a slash proof",
    "description": "Relay stores a slash proof under its own id.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; proof id and evidence checked\n\nReturns: 201 \"kept\"; 400/409\n\nSource: `packages/arena-node/src/server.js` line 6131.",
    "operationId": "put_slash_id",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Slash proof id, 64 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Slash proof + signed result, or + signed re-run.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "\"kept\"",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Evidence is not what the id names.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   },
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Relay serves a slash proof",
    "description": "Relay serves a stored slash proof.\n\nAccess: none\n\nReturns: 200 octet-stream evidence; 404\n\nSource: `packages/arena-node/src/server.js` line 6155.",
    "operationId": "get_slash_id",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Slash proof id, 64 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Evidence bytes.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "404": {
      "description": "None under that id.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/slashes": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Slash proofs this node filed",
    "description": "Every slash proof this node filed, for the arbitration set to fetch.\n\nAccess: none\n\nReturns: 200 JSON {node, slashes:[{round, entry, node, proof, seenMs, objection}]}\n\nSource: `packages/arena-node/src/server.js` line 5986.",
    "operationId": "get_slashes",
    "responses": {
     "200": {
      "description": "{node, slashes:[{round, entry, node, proof, seenMs, objection}]}.",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/stake": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Whether the entry's stake is seen",
    "description": "Says whether this node has seen the entry's stake.\n\nAccess: none\n\nReturns: 200 JSON {entry, state, paidMsat}; 404/409\n\nSource: `packages/arena-node/src/server.js` line 4598.",
    "operationId": "get_stake",
    "parameters": [
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{entry, state, paidMsat}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such entry.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Stake not seen, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/stake-lock": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Find stake locks by refund key",
    "description": "Finds a player's stake locks by refund key (seed recovery).\n\nAccess: none\n\nReturns: 200 JSON array of verified (and refused-round) locks\n\nSource: `packages/arena-node/src/server.js` line 5400.",
    "operationId": "get_stake_lock",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "refund",
      "in": "query",
      "required": true,
      "description": "33-byte refund key, 66 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Array of verified (and refused-round) locks.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/standing": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Pending-line standing of an entry",
    "description": "Pending-line figure: entry state and payout row so far.\n\nAccess: none\n\nReturns: 200 JSON {entry, round, nowMs, ...standing (state, payout row, window open/close)}; 404\n\nSource: `packages/arena-node/src/server.js` line 5626.",
    "operationId": "get_standing",
    "parameters": [
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{entry, round, nowMs, state, payout row, window open/close}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such entry or round.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/start-forfeit": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "FORFEIT record for a late start",
    "description": "Serves the FORFEIT record for a late first mark of an entry.\n\nAccess: none\n\nReturns: 200 JSON {outcome:FORFEIT, markTick, lastTick, why, mark, forwarded}; 404\n\nSource: `packages/arena-node/src/server.js` line 4116.",
    "operationId": "get_start_forfeit",
    "parameters": [
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{outcome:FORFEIT, markTick, lastTick, why, mark, forwarded}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No FORFEIT held.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/transcript": {
   "get": {
    "tags": [
     "Nodes"
    ],
    "summary": "Input transcript of a run",
    "description": "Everything this node received for a run (input transcript).\n\nAccess: none\n\nReturns: 200 octet-stream transcript, headers x-transcript-hash, x-ticks\n\nHeaders: `x-transcript-hash`, `x-ticks`\n\nSource: `packages/arena-node/src/server.js` line 4879.",
    "operationId": "get_transcript",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Transcript bytes.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     }
    }
   }
  },
  "/transcript/{hash}": {
   "put": {
    "tags": [
     "Nodes"
    ],
    "summary": "Relay stores a transcript",
    "description": "Publication relay stores a transcript under its hash.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; bytes must hash to the path\n\nReturns: 201 \"kept\"; 409\n\nSource: `packages/arena-node/src/server.js` line 6166.",
    "operationId": "put_transcript_hash",
    "parameters": [
     {
      "name": "hash",
      "in": "path",
      "required": true,
      "description": "Transcript hash, 64 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "Transcript bytes.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "\"kept\"",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Bytes do not hash to the path.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   },
   "get": {
    "tags": [
     "Builders"
    ],
    "summary": "Relay serves a transcript",
    "description": "Publication relay serves a transcript by hash.\n\nAccess: none\n\nReturns: 200 octet-stream transcript; 404\n\nSource: `packages/arena-node/src/server.js` line 6173.",
    "operationId": "get_transcript_hash",
    "parameters": [
     {
      "name": "hash",
      "in": "path",
      "required": true,
      "description": "Transcript hash, 64 hex.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Transcript bytes.",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "404": {
      "description": "None under that hash.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/tx": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "One transaction",
    "description": "One order or payment this seat stored, with its timing when the page sent one (kanban #624).\n\nAccess: none\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 7964.",
    "operationId": "get_tx",
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/tx-timing": {
   "post": {
    "tags": [
     "Players"
    ],
    "summary": "A page's timing of its order",
    "description": "The page's own timing of its order, signed by the order's session key; kept for GET /tx (kanban #624).\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 8003.",
    "operationId": "post_tx_timing",
    "requestBody": {
     "required": true,
     "description": "{timing, sig}: the session key's Ed25519 signature over the timing.",
     "content": {
      "application/json": {
       "schema": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    },
    "x-changes-state": true
   }
  },
  "/txs": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Newest transactions",
    "description": "The ids of the transactions stored here since `since` (ms), oldest first, at most 500 - what explorer.bitcoinarena.io polls (kanban #624).\n\nAccess: none\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 7971.",
    "operationId": "get_txs",
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/uptime": {
   "get": {
    "tags": [
     "Operators"
    ],
    "summary": "Node uptime",
    "description": "The node's uptime figures (24 h, 7 days, 30 days, all time) from its own record, kept 30 s (kanban #756).\n\nAccess: none\n\nReturns: 200 application/json\n\nSource: `packages/arena-node/src/server.js` line 6640.",
    "operationId": "get_uptime",
    "responses": {
     "200": {
      "description": "200 application/json",
      "content": {
       "application/json": {}
      }
     }
    }
   }
  },
  "/winnings": {
   "get": {
    "tags": [
     "Players"
    ],
    "summary": "Where an entry's winnings stand",
    "description": "Where an entry's winnings stand.\n\nAccess: none\n\nReturns: 200 JSON {entry, send, winnings {state, owedMsat, request, paidMs}}; 404\n\nSource: `packages/arena-node/src/server.js` line 5640.",
    "operationId": "get_winnings",
    "parameters": [
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "{entry, send, winnings {state, owedMsat, request, paidMs}}.",
      "content": {
       "application/json": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "404": {
      "description": "No such entry.",
      "content": {
       "text/plain": {}
      }
     }
    }
   }
  },
  "/winnings-paid": {
   "post": {
    "tags": [
     "Nodes"
    ],
    "summary": "Report a winnings preimage",
    "description": "Reports a winnings payment preimage.\n\n**Changes state on the node:** this page does not send it.\n\nAccess: none; preimage must match the invoice\n\nReturns: 201 \"the winning is kept as paid\"; 400/409\n\nSource: `packages/arena-node/src/server.js` line 5579.",
    "operationId": "post_winnings_paid",
    "parameters": [
     {
      "name": "round",
      "in": "query",
      "required": true,
      "description": "Round id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entry",
      "in": "query",
      "required": true,
      "description": "Entry id, 64 hex (32 bytes).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "late",
      "in": "query",
      "required": false,
      "description": "Entry id (64 hex) of a late loser's second settlement; omit for the round's own settlement.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "32-byte payment preimage.",
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "format": "binary"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "\"the winning is kept as paid\"",
      "content": {
       "text/plain": {}
      }
     },
     "400": {
      "description": "Malformed id or request.",
      "content": {
       "text/plain": {}
      }
     },
     "409": {
      "description": "Refused, with the reason.",
      "content": {
       "text/plain": {}
      }
     }
    },
    "x-changes-state": true
   }
  }
 }
}