{
  "openapi": "3.1.0",
  "info": {
    "title": "Bitbank Launchpad API",
    "version": "0.1.0",
    "description": "Noncustodial launchpad API. Proposed pool fee: 100bp total = 10bp protocol + 90bp collaborators. Authentication and pinning require operator configuration. Unsigned transaction endpoints require a pinned deployment manifest and successful onchain simulation. Existing Pons token retains its original fee policy."
  },
  "servers": [
    {
      "url": "https://bitbank.nz/api/v1/launchpad"
    },
    {
      "url": "http://127.0.0.1:8748/api/v1/launchpad",
      "description": "Disposable local preview"
    }
  ],
  "paths": {
    "/config": {
      "get": {
        "operationId": "get_config",
        "summary": "Protocol fee policy, provider availability and configured capabilities. Configuration does not imply successful chain verification.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "eth_usd": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "eth_usd_source_pool": {
                      "type": "string"
                    },
                    "eth_usd_as_of": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "quote": {
                      "enum": [
                        "usd",
                        "eth"
                      ]
                    },
                    "oracle": {
                      "$ref": "#/components/schemas/OracleObservation"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/tokens": {
      "get": {
        "operationId": "get_tokens",
        "summary": "Historical Pons launches plus cached manifest Bitbank discovery. Featured token sorts first.",
        "security": [],
        "parameters": [
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "volume",
                "market_cap",
                "new",
                "gainers"
              ],
              "default": "volume"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 300,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stored index data; unknown metrics are null. Cache-Control: public, max-age=10.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IndexedTokens"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Token not indexed"
          },
          "503": {
            "description": "Index storage unavailable"
          }
        }
      }
    },
    "/analytics": {
      "get": {
        "operationId": "get_analytics",
        "summary": "Indexed launch and covered trade totals with explicit coverage message.",
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Stored index data; unknown metrics are null. Cache-Control: public, max-age=10.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IndexAnalytics"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Token not indexed"
          },
          "503": {
            "description": "Index storage unavailable"
          }
        }
      }
    },
    "/intents": {
      "post": {
        "operationId": "post_intents",
        "summary": "Validate and persist a private draft; does not launch a token",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Draft"
                }
              }
            }
          },
          "400": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "201": {
            "description": "Draft created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Draft"
                }
              }
            }
          },
          "409": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Intent"
              }
            }
          }
        },
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128
            }
          }
        ]
      },
      "get": {
        "operationId": "get_intents",
        "summary": "Latest 50 private launch drafts",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Draft"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/images": {
      "post": {
        "operationId": "post_images",
        "summary": "Upload a <=4MiB PNG/JPEG/GIF/WebP to configured Pinata IPFS",
        "responses": {
          "200": {
            "description": "Stored image",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "uri": {
                      "type": "string"
                    },
                    "ipfs": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "ipfs_error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "uri"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "description": "Multipart image upload. Stored on the Bitbank static bucket when R2 is configured and pinned to IPFS when PINATA_JWT is set. Returns uri (preferred, ipfs:// when pinned), plus optional ipfs and url."
      }
    },
    "/connections": {
      "get": {
        "operationId": "get_connections",
        "summary": "Your linked GitHub/X provider IDs and current handles",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/splits/transactions": {
      "post": {
        "operationId": "post_splits_transactions",
        "summary": "Prepare unsigned immutable collaborator splitter deployment",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnsignedResult"
                }
              }
            }
          },
          "400": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SplitRequest"
              }
            }
          }
        }
      }
    },
    "/launch/transactions": {
      "post": {
        "operationId": "post_launch_transactions",
        "summary": "Prepare unsigned V3 launch from a private intent",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnsignedResult"
                }
              }
            }
          },
          "400": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LaunchRequest"
              }
            }
          }
        }
      }
    },
    "/trade/quote": {
      "post": {
        "operationId": "post_trade_quote",
        "summary": "Quote a supported Bitbank pool at an explicit block",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                }
              }
            }
          },
          "400": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TradeRequest"
              }
            }
          }
        }
      }
    },
    "/trade/transactions": {
      "post": {
        "operationId": "post_trade_transactions",
        "summary": "Prepare exact approval or deadline-protected swap; request again after approval receipt",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnsignedResult"
                }
              }
            }
          },
          "400": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TradeRequest"
              }
            }
          }
        }
      }
    },
    "/fees/claim-transactions": {
      "post": {
        "operationId": "post_fees_claim_transactions",
        "summary": "Prepare one stage of fee collection, settlement, or release",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnsignedResult"
                }
              }
            }
          },
          "400": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClaimRequest"
              }
            }
          }
        }
      }
    },
    "/fees/positions": {
      "get": {
        "operationId": "get_fees_positions",
        "summary": "Read credited and splitter-claimable balances; uncollected LP fees are not estimated",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Request failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "token",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^0x[0-9a-fA-F]{40}$",
              "description": "Nonzero EVM address."
            }
          },
          {
            "in": "query",
            "name": "wallet",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^0x[0-9a-fA-F]{40}$",
              "description": "Nonzero EVM address."
            }
          }
        ]
      }
    },
    "/gas/quote": {
      "post": {
        "summary": "Quote a network-fee top-up paid in USDC/USDT",
        "description": "FlexGas-style: prices the ETH the wallet is short for gas_limit at the current gas price in an accepted token (V3 quoter price plus markup_bps). Returns EIP-712 typed data for the user to sign, plus ERC-2612 permit typed data when the token supports permit and allowance is insufficient. Quotes expire after 3 minutes.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "wallet",
                  "token",
                  "gas_limit"
                ],
                "properties": {
                  "wallet": {
                    "type": "string"
                  },
                  "token": {
                    "type": "string",
                    "description": "Accepted token address or symbol from /config gas_station.tokens"
                  },
                  "gas_limit": {
                    "type": "integer",
                    "minimum": 21000,
                    "maximum": 30000000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Quote",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "quote_id": {
                      "type": "string"
                    },
                    "token_amount": {
                      "type": "string"
                    },
                    "eth_amount": {
                      "type": "string"
                    },
                    "eth_needed": {
                      "type": "string"
                    },
                    "eth_balance": {
                      "type": "string"
                    },
                    "gas_price": {
                      "type": "string"
                    },
                    "eth_usd": {
                      "type": "string"
                    },
                    "deadline": {
                      "type": "integer"
                    },
                    "needs_top_up": {
                      "type": "boolean"
                    },
                    "needs_permit": {
                      "type": "boolean"
                    },
                    "typed_data": {
                      "type": "object"
                    },
                    "permit_typed_data": {
                      "type": "object"
                    },
                    "station": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/gas/topup": {
      "post": {
        "summary": "Submit a signed top-up through the Bitbank relayer",
        "description": "The relayer calls BitbankGasStation.topUp with the user's EIP-712 signature (and permit). The contract atomically pulls the quoted token amount and sends the quoted ETH; a quote id is consumed once. Wait for the returned hash before sending the user's own transaction.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "quote_id",
                  "wallet",
                  "signature"
                ],
                "properties": {
                  "quote_id": {
                    "type": "string"
                  },
                  "wallet": {
                    "type": "string"
                  },
                  "signature": {
                    "type": "string",
                    "description": "65-byte hex eth_signTypedData_v4 signature over typed_data"
                  },
                  "permit_signature": {
                    "type": "string",
                    "description": "65-byte hex signature over permit_typed_data when needs_permit"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Submitted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "hash": {
                      "type": "string"
                    },
                    "next": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/qr.png": {
      "get": {
        "summary": "Receive QR code",
        "parameters": [
          {
            "name": "text",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^(ethereum:)?0x[0-9a-fA-F]{40}(@[0-9]{1,8})?$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "PNG image"
          },
          "400": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/tokens/{address}": {
      "get": {
        "operationId": "get_indexed_token",
        "summary": "Token metadata and latest 50 trades.",
        "security": [],
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^0x[0-9a-fA-F]{40}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stored index data; unknown metrics are null. Cache-Control: public, max-age=10.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenDetail"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Token not indexed"
          },
          "503": {
            "description": "Index storage unavailable"
          }
        }
      }
    },
    "/tokens/{address}/trades": {
      "get": {
        "operationId": "get_indexed_trades",
        "summary": "Latest trades in descending chain order.",
        "security": [],
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^0x[0-9a-fA-F]{40}$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 300,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stored index data; unknown metrics are null. Cache-Control: public, max-age=10.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/IndexedTrade"
                      }
                    }
                  },
                  "required": [
                    "items"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Token not indexed"
          },
          "503": {
            "description": "Index storage unavailable"
          }
        }
      }
    },
    "/tokens/{address}/candles": {
      "get": {
        "operationId": "get_indexed_candles",
        "summary": "Ascending OHLC buckets. Missing intervals are omitted; v is USD volume or null. ETH fallback avoids mixing quote currencies.",
        "security": [],
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^0x[0-9a-fA-F]{40}$"
            }
          },
          {
            "name": "interval",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1m",
                "5m",
                "1h",
                "1d"
              ],
              "default": "1h"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 300,
              "default": 300
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stored index data; unknown metrics are null. Cache-Control: public, max-age=10.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "interval": {
                      "type": "string"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/IndexedCandle"
                      }
                    },
                    "price_usd_available": {
                      "type": "boolean"
                    },
                    "quote": {
                      "type": "string",
                      "enum": [
                        "usd",
                        "eth"
                      ]
                    }
                  },
                  "required": [
                    "interval",
                    "items",
                    "price_usd_available",
                    "quote"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Token not indexed"
          },
          "503": {
            "description": "Index storage unavailable"
          }
        }
      }
    },
    "/businesses": {
      "get": {
        "operationId": "list_businesses",
        "summary": "Discover published businesses and source-attributed external listings. This does not enable trading.",
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "in": "query",
            "name": "source",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "bitbank",
                "orynth",
                "bags",
                "pumpfun"
              ]
            }
          },
          {
            "in": "query",
            "name": "kind",
            "schema": {
              "type": "string",
              "enum": [
                "business",
                "token"
              ]
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "default": 24,
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Directory listings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Business"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid filter"
          },
          "503": {
            "description": "Storage unavailable"
          }
        }
      },
      "post": {
        "operationId": "publish_business",
        "summary": "Publish a business without a token, wallet, launch draft, or market.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BusinessInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Business published",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Business"
                }
              }
            }
          },
          "200": {
            "description": "Existing listing for identical retry",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Business"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body or missing idempotency key"
          },
          "401": {
            "description": "Authentication required"
          },
          "403": {
            "description": "Invalid origin"
          },
          "409": {
            "description": "Idempotency key was used with different content"
          },
          "422": {
            "description": "Invalid business fields"
          },
          "503": {
            "description": "Storage unavailable"
          }
        }
      }
    },
    "/businesses/{id}": {
      "get": {
        "operationId": "get_business",
        "summary": "Read a directory profile; percent-encode its ID.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Business profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Business"
                }
              }
            }
          },
          "400": {
            "description": "Invalid ID"
          },
          "404": {
            "description": "Listing not found"
          },
          "503": {
            "description": "Storage unavailable"
          }
        }
      }
    },
    "/gallery": {
      "get": {
        "summary": "Browse processed token images",
        "security": [],
        "description": "Public database-only response. Cache-Control: public, max-age=10.",
        "parameters": [
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "new",
                "volume",
                "market_cap",
                "random"
              ],
              "default": "new"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 60
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Indexed records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Gallery"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query"
          },
          "503": {
            "description": "Storage unavailable"
          }
        }
      }
    },
    "/directory": {
      "get": {
        "summary": "Read the business directory and source counts",
        "security": [],
        "description": "Public database-only response. Cache-Control: public, max-age=10.",
        "parameters": [
          {
            "name": "source",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "bitbank",
                "orynth",
                "pumpfun",
                "bags",
                "pons"
              ]
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 24
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Indexed records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Directory"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query"
          },
          "503": {
            "description": "Storage unavailable"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Existing Bitbank API token. Same-origin browser session cookies also work; mutating cookie requests require matching Origin. URL credentials are forbidden."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "Recipient": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "provider",
          "wallet",
          "share_bps"
        ],
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "wallet",
              "github",
              "x"
            ]
          },
          "handle": {
            "type": "string",
            "maxLength": 39,
            "description": "Unverified social label; required for GitHub/X. Does not authorize a payout."
          },
          "wallet": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$",
            "description": "Nonzero EVM address."
          },
          "share_bps": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10000,
            "description": "Share of the 90bp collaborator portion. All recipients sum to 10000."
          }
        }
      },
      "Intent": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "symbol",
          "image_uri",
          "chain_id"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "symbol": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9]{1,12}$"
          },
          "description": {
            "type": "string",
            "maxLength": 1000
          },
          "image_uri": {
            "type": "string",
            "pattern": "^(ipfs|https)://",
            "maxLength": 256,
            "description": "ipfs:// URI from POST /images, or an https:// CDN URL."
          },
          "website": {
            "type": "string",
            "maxLength": 256,
            "description": "Optional HTTPS URL."
          },
          "chain_id": {
            "type": "integer",
            "enum": [
              4663,
              46630
            ]
          },
          "recipients": {
            "type": "array",
            "minItems": 0,
            "maxItems": 20,
            "items": {
              "$ref": "#/components/schemas/Recipient"
            }
          },
          "fee_bps": {
            "type": "integer",
            "enum": [
              100,
              50,
              30,
              10
            ],
            "default": 100,
            "description": "Total pool fee in basis points. Bitbank keeps 10bp at every tier; the remainder is the collaborator share. Only 100 is launchable on the current contracts. 10 needs no recipients."
          }
        }
      },
      "Draft": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft"
            ]
          },
          "intent": {
            "$ref": "#/components/schemas/Intent"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "transaction": {
            "type": "null"
          }
        }
      },
      "Transaction": {
        "type": "object",
        "required": [
          "chainId",
          "from",
          "data",
          "value",
          "gas"
        ],
        "properties": {
          "chainId": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$"
          },
          "data": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$"
          },
          "value": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$"
          },
          "gas": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$"
          },
          "from": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$",
            "description": "Nonzero EVM address."
          },
          "to": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$",
            "description": "Omitted for contract creation. All values and gas are hex quantities. Sign locally; the server never submits."
          }
        }
      },
      "TradeRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "token",
          "wallet",
          "side",
          "amount_in",
          "slippage_bps"
        ],
        "properties": {
          "token": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$",
            "description": "Nonzero EVM address."
          },
          "wallet": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$",
            "description": "Nonzero EVM address."
          },
          "side": {
            "type": "string",
            "enum": [
              "buy",
              "sell"
            ]
          },
          "amount_in": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Positive uint256 in ERC20 base units. Buy spends WETH; sell receives WETH."
          },
          "slippage_bps": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500
          }
        }
      },
      "Quote": {
        "type": "object",
        "properties": {
          "token_in": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$",
            "description": "Nonzero EVM address."
          },
          "token_out": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$",
            "description": "Nonzero EVM address."
          },
          "amount_in": {
            "type": "string"
          },
          "amount_out": {
            "type": "string"
          },
          "minimum_out": {
            "type": "string"
          },
          "block_number": {
            "type": "string"
          },
          "settlement": {
            "type": "string"
          },
          "expires_at": {
            "type": "integer",
            "description": "Unix seconds; quote validity 60 seconds."
          },
          "slippage_bps": {
            "type": "integer"
          }
        }
      },
      "LaunchRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "intent_id",
          "wallet",
          "splitter",
          "salt"
        ],
        "properties": {
          "intent_id": {
            "type": "string",
            "format": "uuid"
          },
          "wallet": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$",
            "description": "Nonzero EVM address."
          },
          "splitter": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$",
            "description": "Deployed BitbankFeeSplitter with exact draft allocations; verified onchain."
          },
          "salt": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{64}$"
          }
        }
      },
      "SplitRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "intent_id",
          "wallet"
        ],
        "properties": {
          "intent_id": {
            "type": "string",
            "format": "uuid"
          },
          "wallet": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$",
            "description": "Nonzero EVM address."
          }
        }
      },
      "ClaimRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "token",
          "asset",
          "wallet",
          "action"
        ],
        "properties": {
          "token": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$",
            "description": "Nonzero EVM address."
          },
          "asset": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$",
            "description": "Nonzero EVM address."
          },
          "wallet": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$",
            "description": "Nonzero EVM address."
          },
          "action": {
            "type": "string",
            "enum": [
              "collect",
              "claim"
            ],
            "description": "Collect LP fees first. Then claim to settle locker credit and call again to release the splitter share. Wait for each receipt."
          }
        }
      },
      "UnsignedResult": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "unsigned"
            ]
          },
          "transaction": {
            "$ref": "#/components/schemas/Transaction"
          },
          "next": {
            "type": "string"
          },
          "step": {
            "type": "string"
          },
          "quote": {
            "$ref": "#/components/schemas/Quote"
          }
        }
      },
      "TokenSummary": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "image": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "twitter": {
            "type": "string"
          },
          "telegram": {
            "type": "string"
          },
          "deployer": {
            "type": "string"
          },
          "pool": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "price_eth": {
            "type": [
              "number",
              "null"
            ]
          },
          "price_usd": {
            "type": [
              "number",
              "null"
            ]
          },
          "market_cap_usd": {
            "type": [
              "number",
              "null"
            ]
          },
          "liquidity_usd": {
            "type": [
              "number",
              "null"
            ],
            "description": "Current principal value in the canonical pool. V4 replays position ranges; excludes uncollected fees, never uses singleton manager balances."
          },
          "volume_24h_usd": {
            "type": [
              "number",
              "null"
            ]
          },
          "change_24h_pct": {
            "type": [
              "number",
              "null"
            ]
          },
          "venue": {
            "type": "string",
            "enum": [
              "pons",
              "bitbank",
              "external"
            ]
          },
          "chain_id": {
            "type": "integer"
          },
          "launched_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "block": {
            "type": "integer"
          },
          "trades_24h": {
            "type": [
              "integer",
              "null"
            ]
          },
          "holders": {
            "type": [
              "integer",
              "null"
            ]
          },
          "featured": {
            "type": "boolean"
          },
          "image_thumb": {
            "type": "string"
          },
          "image_full": {
            "type": "string"
          },
          "metadata_source": {
            "type": "string"
          },
          "holders_source": {
            "type": "string"
          }
        },
        "required": [
          "address",
          "name",
          "symbol",
          "image",
          "description",
          "website",
          "twitter",
          "telegram",
          "deployer",
          "pool",
          "url",
          "price_eth",
          "price_usd",
          "market_cap_usd",
          "liquidity_usd",
          "volume_24h_usd",
          "change_24h_pct",
          "venue",
          "chain_id",
          "launched_at",
          "block",
          "trades_24h",
          "holders",
          "featured"
        ]
      },
      "IndexedTrade": {
        "type": "object",
        "properties": {
          "tx": {
            "type": "string"
          },
          "block": {
            "type": "integer"
          },
          "t": {
            "type": "integer"
          },
          "side": {
            "type": "string",
            "enum": [
              "buy",
              "sell"
            ]
          },
          "wallet": {
            "type": "string",
            "description": "V3 event recipient, possibly a router; V2 buyer/seller. Not inferred transaction origin."
          },
          "amount_token": {
            "type": [
              "number",
              "null"
            ]
          },
          "amount_eth": {
            "type": [
              "number",
              "null"
            ]
          },
          "amount_usd": {
            "type": [
              "number",
              "null"
            ],
            "description": "USDG quote amount, or ETH notional converted using historical canonical WETH/USDG Swap slot0 with three-pool agreement. Historical source selected by current WETH balance. Null without verified historical quote."
          },
          "price_usd": {
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "tx",
          "block",
          "t",
          "side",
          "wallet",
          "amount_token",
          "amount_eth",
          "amount_usd",
          "price_usd"
        ]
      },
      "IndexedCandle": {
        "type": "object",
        "properties": {
          "t": {
            "type": "integer"
          },
          "o": {
            "type": "number"
          },
          "h": {
            "type": "number"
          },
          "l": {
            "type": "number"
          },
          "c": {
            "type": "number"
          },
          "v": {
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "t",
          "o",
          "h",
          "l",
          "c",
          "v"
        ]
      },
      "IndexedTokens": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TokenSummary"
            }
          },
          "as_of": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "indexed": {
            "type": "boolean"
          },
          "from_block": {
            "type": "integer"
          },
          "to_block": {
            "type": "integer"
          },
          "complete": {
            "type": "boolean"
          }
        },
        "required": [
          "items",
          "as_of",
          "indexed",
          "from_block",
          "to_block",
          "complete"
        ]
      },
      "TokenDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/TokenSummary"
          },
          {
            "type": "object",
            "properties": {
              "trades": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/IndexedTrade"
                }
              },
              "supply": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Integer base units, null while token metadata is not indexed."
              },
              "decimals": {
                "type": "integer"
              }
            },
            "required": [
              "trades",
              "supply",
              "decimals"
            ]
          }
        ],
        "properties": {
          "market_as_of": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "IndexAnalytics": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "indexed",
              "not_indexed"
            ]
          },
          "as_of": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "tokens": {
            "type": [
              "integer",
              "null"
            ]
          },
          "launches_24h": {
            "type": [
              "integer",
              "null"
            ]
          },
          "launches_7d": {
            "type": [
              "integer",
              "null"
            ]
          },
          "trades_24h": {
            "type": [
              "integer",
              "null"
            ]
          },
          "volume_24h_usd": {
            "type": [
              "number",
              "null"
            ]
          },
          "volume_7d_usd": {
            "type": [
              "number",
              "null"
            ]
          },
          "top_gainers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TokenSummary"
            }
          },
          "top_volume": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TokenSummary"
            }
          },
          "message": {
            "type": "string"
          },
          "eth_usd": {
            "type": [
              "number",
              "null"
            ]
          },
          "eth_usd_source_pool": {
            "type": "string"
          },
          "eth_usd_as_of": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "quote": {
            "enum": [
              "usd",
              "eth"
            ]
          },
          "oracle": {
            "$ref": "#/components/schemas/OracleObservation"
          },
          "market_as_of": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "market_tokens": {
            "type": "integer"
          },
          "indexed_volume_24h_usd": {
            "type": [
              "number",
              "null"
            ]
          },
          "indexed_volume_7d_usd": {
            "type": [
              "number",
              "null"
            ]
          },
          "launches_per_day_as_of": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "launches_per_day": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "t": {
                  "type": "integer",
                  "description": "UTC midnight, Unix seconds"
                },
                "launches": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "required": [
          "status",
          "as_of",
          "tokens",
          "launches_24h",
          "launches_7d",
          "trades_24h",
          "volume_24h_usd",
          "volume_7d_usd",
          "top_gainers",
          "top_volume",
          "message"
        ],
        "description": "Factory census and separately measured market coverage. Indexed volume sums priced trades only; market-wide volume remains null until covered. Rankings cover enriched tokens only. Final launch day is partial."
      },
      "OracleObservation": {
        "type": "object",
        "properties": {
          "eth_usd": {
            "type": [
              "number",
              "null"
            ]
          },
          "source_pool": {
            "type": "string"
          },
          "as_of": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "block": {
            "type": "integer"
          },
          "quote": {
            "enum": [
              "usd",
              "eth"
            ]
          }
        },
        "description": "Canonical WETH/USDG V3 slot0. All three pools must agree within 5%, price 300\u201350000; source has greatest WETH balance. USDG is treated as USD. Observation is stored, cached 30 seconds, and never fetched on request paths."
      },
      "BusinessInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "website"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "maxLength": 1000
          },
          "website": {
            "type": "string",
            "format": "uri",
            "pattern": "^https://",
            "maxLength": 2048
          },
          "image": {
            "type": "string",
            "maxLength": 2048,
            "description": "Optional HTTPS image URL; empty string is allowed."
          }
        }
      },
      "Business": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "image": {
            "type": "string"
          },
          "source_url": {
            "type": "string"
          },
          "chain": {
            "type": "string"
          },
          "token_address": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "bitbank",
              "orynth",
              "bags",
              "pumpfun"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "business",
              "token"
            ]
          },
          "market_status": {
            "type": "string",
            "enum": [
              "no_market",
              "not_available_on_bitbank"
            ]
          },
          "indexed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "GalleryItem": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "venue": {
            "type": "string"
          },
          "image_thumb": {
            "type": "string"
          },
          "image_full": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "price_usd": {
            "type": "number",
            "nullable": true
          },
          "market_cap_usd": {
            "type": "number",
            "nullable": true
          },
          "volume_24h_usd": {
            "type": "number",
            "nullable": true
          },
          "width": {
            "type": "integer"
          },
          "height": {
            "type": "integer"
          },
          "launched_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "links": {
            "type": "object",
            "properties": {
              "pons": {
                "type": "string"
              },
              "explorer": {
                "type": "string"
              },
              "website": {
                "type": "string"
              },
              "twitter": {
                "type": "string"
              },
              "telegram": {
                "type": "string"
              }
            },
            "required": [
              "pons",
              "explorer",
              "website",
              "twitter",
              "telegram"
            ]
          }
        },
        "required": [
          "address",
          "name",
          "symbol",
          "venue",
          "image_thumb",
          "image_full",
          "url",
          "price_usd",
          "market_cap_usd",
          "volume_24h_usd",
          "width",
          "height",
          "launched_at",
          "links"
        ]
      },
      "Gallery": {
        "type": "object",
        "required": [
          "items",
          "next_cursor",
          "total",
          "as_of"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GalleryItem"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true
          },
          "total": {
            "type": "integer",
            "description": "Count of all tokens with successfully processed images, independent of q."
          },
          "as_of": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Directory": {
        "type": "object",
        "required": [
          "items",
          "sources"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Business"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "source",
                "count",
                "label",
                "url"
              ],
              "properties": {
                "source": {
                  "type": "string"
                },
                "count": {
                  "type": "integer"
                },
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}
