{
  "openapi": "3.1.0",
  "info": {
    "title": "Nodely x402 APIs",
    "version": "1",
    "description": "Pay-per-call APIs for agents, paid with x402 (USDC on Algorand). Each paid route answers 402 with a PAYMENT-REQUIRED header until it gets a PAYMENT-SIGNATURE; /.well-known/x402 lists them.\n\n## Nodely Search and Scrape (x402)\n\nPay-per-request web search and page scraping for agents, paid in USDC on Algorand mainnet (ASA 31566704) with the x402 v2 `exact` scheme: an unpaid request gets 402 with a PAYMENT-REQUIRED header listing the price of that resource; retry with PAYMENT-SIGNATURE carrying one signed USDC asset transfer of exactly that amount. A search costs 0.01 USDC, a scrape 0.01 USDC (each resource is priced on its own: read the 402 or the pricing routes). The payer must hold at least 10x the price of the request in USDC on top of its unsettled payments. Search results come from Brave Search API, Google (via Serper), Bing, Marginalia and Wikipedia, merged and re-ranked; they can be streamed per engine as NDJSON or SSE. Request/response follow Tavily-style names; Exa, You.com, Perplexity, Brave, Serper and Linkup field names are accepted as aliases. Scrapes run on Firecrawl (headless browser) and return its page data. Searches that return nothing and scrapes that fail are not charged.\n\n## Nodely DEX Prices (x402)\n\nAlgorand DEX prices, paid per call with x402 (exact scheme, USDC ASA 31566704 on Algorand, 0.001 USDC per call, payTo URTHOQHNY5B4ZZSOBFVAZXOYCHC7EHGYOGCIEJVHKVEPTWXVT7SAZDRIVE). An unpaid call answers 402 with the PAYMENT-REQUIRED offer; a bad request answers 400 and is never charged, nor is a call that returns no data. The same data is free and rate-limited at https://algoprices.api.nodely.io. Historical and live prices of Algorand ASAs, computed from on-chain DEX pool state (Tinyman V2, Pact, Pact StableSwap, Pact weighted, Humble, Algofi, LiquiHog, Biatec) since round 19,247,000. Prices are exact to the round: the state of every pool is replayed from its eval deltas. A USD price is a liquidity-weighted route search to USDC over the pools; a price in another quote is the ratio of both USD prices.\n\nEvery price carries three units: `price` (in the requested quote), `usdc` and `algo` (null if the asset cannot be routed).\n\nRate limit: 10 requests/s per client IP (burst 20); excess requests get HTTP 429. Checkout <a href=\"/v1/api-docs/swagger.json\">swagger.json</a>."
  },
  "servers": [
    {
      "url": "https://x402.api.nodely.io"
    }
  ],
  "paths": {
    "/v1/search": {
      "post": {
        "operationId": "search",
        "summary": "Web search (paid, 0.01 USDC per query)",
        "parameters": [
          {
            "$ref": "#/components/parameters/SearchPaymentSignature"
          },
          {
            "$ref": "#/components/parameters/SearchAccept"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchSearchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/SearchSearchOK"
          },
          "400": {
            "$ref": "#/components/responses/SearchError"
          },
          "402": {
            "$ref": "#/components/responses/SearchPaymentRequired"
          },
          "429": {
            "$ref": "#/components/responses/SearchError"
          },
          "502": {
            "$ref": "#/components/responses/SearchError"
          },
          "503": {
            "$ref": "#/components/responses/SearchError"
          }
        },
        "tags": [
          "search"
        ]
      },
      "get": {
        "operationId": "searchGet",
        "summary": "Web search via query parameters (paid, same fields; lists comma-separated)",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 400
            },
            "description": "Alias: q"
          },
          {
            "name": "max_results",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 10
            }
          },
          {
            "name": "time_range",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "day",
                "week",
                "month",
                "year"
              ]
            }
          },
          {
            "name": "include_domains",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated"
          },
          {
            "name": "stream",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "$ref": "#/components/parameters/SearchPaymentSignature"
          },
          {
            "$ref": "#/components/parameters/SearchAccept"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/SearchSearchOK"
          },
          "400": {
            "$ref": "#/components/responses/SearchError"
          },
          "402": {
            "$ref": "#/components/responses/SearchPaymentRequired"
          },
          "429": {
            "$ref": "#/components/responses/SearchError"
          },
          "502": {
            "$ref": "#/components/responses/SearchError"
          },
          "503": {
            "$ref": "#/components/responses/SearchError"
          }
        },
        "tags": [
          "search"
        ]
      }
    },
    "/v1/search/pricing": {
      "get": {
        "operationId": "searchPricing",
        "summary": "Price, asset, networks and receiving address (free)",
        "responses": {
          "200": {
            "description": "Pricing",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "tags": [
          "search"
        ]
      }
    },
    "/v1/search/health": {
      "get": {
        "operationId": "searchHealth",
        "summary": "Service health (free)",
        "responses": {
          "200": {
            "description": "Healthy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "503": {
            "description": "Unhealthy (algod or SearXNG unreachable)"
          }
        },
        "tags": [
          "search"
        ]
      }
    },
    "/v1/scrape": {
      "post": {
        "operationId": "scrape",
        "summary": "Scrape one web page (paid, 0.01 USDC per page)",
        "description": "Fetches and renders one public http(s) URL with Firecrawl and returns its data (markdown, html, rawHtml, links). Charged only when the page was delivered: Firecrawl succeeded and the target answered with a status below 400. A failed scrape (502 scrape_failed) or a timeout (504 scrape_timeout) is not charged and the same payment may be retried (a bounded number of times). The scrape must finish while the payment can still be committed: its deadline is what the payment's validity window leaves (at most 20 s); a window leaving less than 3 s is refused with 402 invalid_exact_avm_validity_window before anything is fetched. URLs with credentials, IP-literal hosts and private names (localhost, *.local, *.internal, *.lan, single-label hosts) are refused with 400 before payment.",
        "parameters": [
          {
            "$ref": "#/components/parameters/SearchPaymentSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchScrapeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/SearchScrapeOK"
          },
          "400": {
            "$ref": "#/components/responses/SearchError"
          },
          "402": {
            "$ref": "#/components/responses/SearchPaymentRequired"
          },
          "429": {
            "$ref": "#/components/responses/SearchError"
          },
          "502": {
            "$ref": "#/components/responses/SearchError"
          },
          "503": {
            "$ref": "#/components/responses/SearchError"
          },
          "504": {
            "$ref": "#/components/responses/SearchError"
          }
        },
        "tags": [
          "scrape"
        ]
      },
      "get": {
        "operationId": "scrapeGet",
        "summary": "Scrape one web page via query parameters (paid, same fields; lists comma-separated)",
        "description": "Same as POST /v1/scrape. Charged only when the page was delivered: Firecrawl succeeded and the target answered with a status below 400. A failed scrape (502 scrape_failed) or a timeout (504 scrape_timeout) is not charged and the same payment may be retried (a bounded number of times). The scrape must finish while the payment can still be committed: its deadline is what the payment's validity window leaves (at most 20 s); a window leaving less than 3 s is refused with 402 invalid_exact_avm_validity_window before anything is fetched.",
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri",
              "maxLength": 2048
            }
          },
          {
            "name": "formats",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated: markdown (default), html, rawHtml, links"
          },
          {
            "name": "only_main_content",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": true
            },
            "description": "Alias: onlyMainContent"
          },
          {
            "name": "wait_for",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000
            },
            "description": "ms; alias: waitFor"
          },
          {
            "name": "mobile",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "timeout",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "ms; clamped to what the payment's validity window leaves"
          },
          {
            "$ref": "#/components/parameters/SearchPaymentSignature"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/SearchScrapeOK"
          },
          "400": {
            "$ref": "#/components/responses/SearchError"
          },
          "402": {
            "$ref": "#/components/responses/SearchPaymentRequired"
          },
          "429": {
            "$ref": "#/components/responses/SearchError"
          },
          "502": {
            "$ref": "#/components/responses/SearchError"
          },
          "503": {
            "$ref": "#/components/responses/SearchError"
          },
          "504": {
            "$ref": "#/components/responses/SearchError"
          }
        },
        "tags": [
          "scrape"
        ]
      }
    },
    "/v1/scrape/pricing": {
      "get": {
        "operationId": "scrapePricing",
        "summary": "Scrape price, asset, networks and receiving address (free)",
        "responses": {
          "200": {
            "description": "Pricing",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "tags": [
          "scrape"
        ]
      }
    },
    "/v1/prices/health": {
      "get": {
        "operationId": "pricesHealth",
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "summary": "Service and algod health (free)",
        "tags": [
          "status"
        ]
      }
    },
    "/v1/prices/history": {
      "get": {
        "description": "`bins` bins of equal width ending at `to` (clamped to the indexed tip). Each point is the price at the end of its bin. Bins under 1 h are computed from raw pool events, 1 h to 1 d from hourly bars, 1 d or more from daily bars.",
        "operationId": "pricesHistory",
        "parameters": [
          {
            "description": "ASA id, `algo` (= 0) or `usdc` (= 31566704).",
            "example": "386192725",
            "in": "query",
            "name": "asset",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Quote asset (ASA id, `algo` or `usdc`). Default USDC.",
            "in": "query",
            "name": "quote",
            "schema": {
              "default": "usdc",
              "type": "string"
            }
          },
          {
            "description": "Unix seconds, RFC 3339, or YYYY-MM-DD (UTC).",
            "example": "2026-10-01",
            "in": "query",
            "name": "from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Unix seconds, RFC 3339, or YYYY-MM-DD (UTC).",
            "example": "2026-10-23",
            "in": "query",
            "name": "to",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Number of bins (max 2000).",
            "in": "query",
            "name": "bins",
            "schema": {
              "default": 100,
              "maximum": 2000,
              "type": "integer"
            }
          },
          {
            "description": "Minimum pool liquidity in USD for a pool to be used in routing.",
            "in": "query",
            "name": "min_liq",
            "schema": {
              "default": 50,
              "type": "number"
            }
          },
          {
            "description": "Maximum route length from the asset to USDC.",
            "in": "query",
            "name": "max_hops",
            "schema": {
              "default": 4,
              "type": "integer"
            }
          },
          {
            "description": "Ignore pools with no event for this many days.",
            "in": "query",
            "name": "stale_days",
            "schema": {
              "default": 30,
              "type": "integer"
            }
          },
          {
            "description": "Drop pool quotes deviating more than this fraction from the liquidity-weighted median.",
            "in": "query",
            "name": "max_dev",
            "schema": {
              "default": 0.2,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricesHistory"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricesError"
                }
              }
            },
            "description": "Bad parameter or unknown asset"
          },
          "402": {
            "description": "Payment required: x402 offer in the PAYMENT-REQUIRED header (base64 JSON; the same JSON is the body). Retry with PAYMENT-SIGNATURE."
          },
          "429": {
            "description": "Rate limit exceeded (10 requests/s per client IP, burst 20)"
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricesError"
                }
              }
            },
            "description": "Internal error"
          }
        },
        "summary": "Price history in equal-width bins",
        "tags": [
          "prices"
        ]
      }
    },
    "/v1/prices/pairs": {
      "get": {
        "description": "Every pair with a live pool that day, sorted by TVL: venues, pool counts, swaps, close price (asset B per asset A, deepest pool), reserves, volumes, TVL and volume in USD. The default day is the last finalized one; `final` is false for the still-open day.",
        "operationId": "pricesPairs",
        "parameters": [
          {
            "description": "YYYY-MM-DD (UTC). Default: last finalized day.",
            "in": "query",
            "name": "date",
            "schema": {
              "format": "date",
              "type": "string"
            }
          },
          {
            "description": "`1`: only pairs with at least one swap that day.",
            "in": "query",
            "name": "active",
            "schema": {
              "enum": [
                "0",
                "1"
              ],
              "type": "string"
            }
          },
          {
            "description": "Minimum TVL in USD.",
            "in": "query",
            "name": "min_tvl",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricesPairs"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricesError"
                }
              }
            },
            "description": "Bad parameter or unknown asset"
          },
          "402": {
            "description": "Payment required: x402 offer in the PAYMENT-REQUIRED header (base64 JSON; the same JSON is the body). Retry with PAYMENT-SIGNATURE."
          },
          "429": {
            "description": "Rate limit exceeded (10 requests/s per client IP, burst 20)"
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricesError"
                }
              }
            },
            "description": "Internal error"
          }
        },
        "summary": "All pairs with a live pool on a day",
        "tags": [
          "markets"
        ]
      }
    },
    "/v1/prices/pools": {
      "get": {
        "operationId": "pricesPools",
        "parameters": [
          {
            "description": "ASA id, `algo` (= 0) or `usdc` (= 31566704).",
            "example": "386192725",
            "in": "query",
            "name": "asset",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricesPools"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricesError"
                }
              }
            },
            "description": "Bad parameter or unknown asset"
          },
          "402": {
            "description": "Payment required: x402 offer in the PAYMENT-REQUIRED header (base64 JSON; the same JSON is the body). Retry with PAYMENT-SIGNATURE."
          },
          "429": {
            "description": "Rate limit exceeded (10 requests/s per client IP, burst 20)"
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricesError"
                }
              }
            },
            "description": "Internal error"
          }
        },
        "summary": "Pools holding an asset",
        "tags": [
          "markets"
        ]
      }
    },
    "/v1/prices/price": {
      "get": {
        "description": "The price after round `round`, or after the last block at or before `ts`. With neither, the price at the indexed tip (seconds behind the chain). A `ts` at or after the tip is answered at the tip and echoed as `requested_ts`.",
        "operationId": "pricesPrice",
        "parameters": [
          {
            "description": "ASA id, `algo` (= 0) or `usdc` (= 31566704).",
            "example": "386192725",
            "in": "query",
            "name": "asset",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Quote asset (ASA id, `algo` or `usdc`). Default USDC.",
            "in": "query",
            "name": "quote",
            "schema": {
              "default": "usdc",
              "type": "string"
            }
          },
          {
            "description": "Round (exclusive of `ts`).",
            "example": 65000000,
            "in": "query",
            "name": "round",
            "schema": {
              "format": "int64",
              "type": "integer"
            }
          },
          {
            "description": "Time (exclusive of `round`). Unix seconds, RFC 3339, or YYYY-MM-DD (UTC).",
            "example": "2026-09-13T09:16:17Z",
            "in": "query",
            "name": "ts",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "`1` lists every pool quote used: venue, pool, via-asset, implied USD price, weight, kept.",
            "in": "query",
            "name": "details",
            "schema": {
              "enum": [
                "0",
                "1"
              ],
              "type": "string"
            }
          },
          {
            "description": "Minimum pool liquidity in USD for a pool to be used in routing.",
            "in": "query",
            "name": "min_liq",
            "schema": {
              "default": 50,
              "type": "number"
            }
          },
          {
            "description": "Maximum route length from the asset to USDC.",
            "in": "query",
            "name": "max_hops",
            "schema": {
              "default": 4,
              "type": "integer"
            }
          },
          {
            "description": "Ignore pools with no event for this many days.",
            "in": "query",
            "name": "stale_days",
            "schema": {
              "default": 30,
              "type": "integer"
            }
          },
          {
            "description": "Drop pool quotes deviating more than this fraction from the liquidity-weighted median.",
            "in": "query",
            "name": "max_dev",
            "schema": {
              "default": 0.2,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricesPrice"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricesError"
                }
              }
            },
            "description": "Bad parameter or unknown asset"
          },
          "402": {
            "description": "Payment required: x402 offer in the PAYMENT-REQUIRED header (base64 JSON; the same JSON is the body). Retry with PAYMENT-SIGNATURE."
          },
          "429": {
            "description": "Rate limit exceeded (10 requests/s per client IP, burst 20)"
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricesError"
                }
              }
            },
            "description": "Internal error"
          }
        },
        "summary": "Price of an asset at a round or time",
        "tags": [
          "prices"
        ]
      }
    },
    "/v1/prices/pricing": {
      "get": {
        "operationId": "pricesPricing",
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "summary": "Paid resources and their prices (free)",
        "tags": [
          "status"
        ]
      }
    },
    "/v1/prices/status": {
      "get": {
        "operationId": "pricesStatus",
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "summary": "How far the dataset is built (free)",
        "tags": [
          "status"
        ]
      }
    }
  },
  "components": {
    "parameters": {
      "SearchPaymentSignature": {
        "name": "PAYMENT-SIGNATURE",
        "in": "header",
        "required": false,
        "description": "x402 v2 PaymentPayload, base64 JSON: {x402Version:2, accepted:<one of the 402's accepts>, payload:{paymentGroup:[<base64 msgpack signed axfer>], paymentIndex:0}}. X-PAYMENT is accepted as an alias.",
        "schema": {
          "type": "string"
        }
      },
      "SearchAccept": {
        "name": "Accept",
        "in": "header",
        "required": false,
        "description": "application/json (default, buffered), application/x-ndjson or text/event-stream (stream events per engine)",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "SearchError": {
        "description": "Error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/SearchError"
            }
          }
        }
      },
      "SearchSearchOK": {
        "description": "Results. PAYMENT-RESPONSE (base64 JSON SettlementResponse) carries the payment transaction id; settlement is deferred (accepted into algod's pool, not awaited).",
        "headers": {
          "PAYMENT-RESPONSE": {
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/SearchSearchResponse"
            }
          },
          "application/x-ndjson": {
            "schema": {
              "$ref": "#/components/schemas/SearchStreamEvent"
            }
          },
          "text/event-stream": {
            "schema": {
              "$ref": "#/components/schemas/SearchStreamEvent"
            }
          }
        }
      },
      "SearchPaymentRequired": {
        "description": "Payment required or rejected. PAYMENT-REQUIRED (base64 JSON PaymentRequired) lists the accepted payments: scheme exact, network algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73k (or the full-genesis-hash form), asset 31566704, amount = the price of the requested resource (10000 = 0.01 USDC for search and for scrape).",
        "headers": {
          "PAYMENT-REQUIRED": {
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "type": "object"
            }
          }
        }
      },
      "SearchScrapeOK": {
        "description": "The page. PAYMENT-RESPONSE (base64 JSON SettlementResponse) carries the payment transaction id; settlement is deferred (accepted into algod's pool before the page is sent, not awaited).",
        "headers": {
          "PAYMENT-RESPONSE": {
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/SearchScrapeResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "SearchSearchRequest": {
        "type": "object",
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "string",
            "minLength": 1,
            "maxLength": 400,
            "description": "Alias: q"
          },
          "max_results": {
            "type": "integer",
            "minimum": 1,
            "maximum": 50,
            "default": 10,
            "description": "Aliases: count, num_results, numResults, maxResults, limit, num"
          },
          "page": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "default": 1
          },
          "time_range": {
            "type": "string",
            "enum": [
              "day",
              "week",
              "month",
              "year"
            ],
            "description": "Aliases: freshness, search_recency_filter"
          },
          "start_date": {
            "type": "string",
            "format": "date"
          },
          "end_date": {
            "type": "string",
            "format": "date"
          },
          "include_domains": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "exclude_domains": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "language": {
            "type": "string",
            "examples": [
              "en",
              "en-US"
            ]
          },
          "country": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2"
          },
          "safesearch": {
            "description": "off/moderate/strict or 0/1/2"
          },
          "topic": {
            "type": "string",
            "enum": [
              "general",
              "news"
            ],
            "default": "general"
          },
          "engines": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "braveapi",
                "bing",
                "serper",
                "marginalia",
                "wikipedia"
              ]
            }
          },
          "include_answer": {
            "type": "boolean",
            "default": false
          },
          "stream": {
            "type": "boolean",
            "default": false
          }
        },
        "additionalProperties": true
      },
      "SearchResult": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "content": {
            "type": "string"
          },
          "snippet": {
            "type": "string"
          },
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "published_date": {
            "type": [
              "string",
              "null"
            ]
          },
          "engines": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "position": {
            "type": "integer"
          },
          "thumbnail": {
            "type": "string"
          }
        }
      },
      "SearchSearchResponse": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchResult"
            }
          },
          "answer": {
            "type": [
              "string",
              "null"
            ]
          },
          "suggestions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "engines": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "results": {
                  "type": "integer"
                },
                "error": {
                  "type": "string"
                },
                "elapsed_s": {
                  "type": "number"
                }
              }
            }
          },
          "response_time": {
            "type": "number"
          },
          "request_id": {
            "type": "string"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "SearchStreamEvent": {
        "type": "object",
        "description": "One event per NDJSON line / SSE message, in order: meta, results (per engine, new results only), engine_error, then done (the SearchResponse, authoritative: charged) or error (not charged).",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "meta",
              "results",
              "engine_error",
              "done",
              "error"
            ]
          }
        }
      },
      "SearchError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          },
          "request_id": {
            "type": "string"
          }
        }
      },
      "SearchScrapeRequest": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "http or https, public DNS name (no IP literals, credentials or private names)"
          },
          "formats": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "markdown",
                "html",
                "rawHtml",
                "links"
              ]
            },
            "default": [
              "markdown"
            ]
          },
          "only_main_content": {
            "type": "boolean",
            "default": true,
            "description": "Alias: onlyMainContent"
          },
          "include_tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 50,
            "description": "Alias: includeTags"
          },
          "exclude_tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 50,
            "description": "Alias: excludeTags"
          },
          "wait_for": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000,
            "description": "ms to wait after load; alias: waitFor; at most half the timeout"
          },
          "mobile": {
            "type": "boolean",
            "default": false
          },
          "timeout": {
            "type": "integer",
            "minimum": 1,
            "description": "ms; clamped to what the payment's validity window leaves (at most 20 s)"
          }
        },
        "additionalProperties": true
      },
      "SearchScrapeResponse": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "data": {
            "type": "object",
            "description": "Firecrawl v2 scrape data, passed through as-is",
            "properties": {
              "markdown": {
                "type": "string"
              },
              "html": {
                "type": "string"
              },
              "rawHtml": {
                "type": "string"
              },
              "links": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "metadata": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "sourceURL": {
                    "type": "string"
                  },
                  "url": {
                    "type": "string"
                  },
                  "statusCode": {
                    "type": "integer"
                  },
                  "contentType": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "request_id": {
            "type": "string"
          },
          "response_time": {
            "type": "number"
          }
        }
      },
      "PricesAsset": {
        "properties": {
          "decimals": {
            "type": "integer"
          },
          "id": {
            "description": "ASA id, 0 = ALGO",
            "format": "int64",
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "unit": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "PricesAssetUSD": {
        "properties": {
          "hops": {
            "type": "integer"
          },
          "liquidity_usd": {
            "type": "number"
          },
          "routes": {
            "description": "With details=1",
            "items": {
              "$ref": "#/components/schemas/PricesRoute"
            },
            "type": "array"
          },
          "usd": {
            "description": "USD per whole unit; null if not routable",
            "nullable": true,
            "type": "number"
          }
        },
        "type": "object"
      },
      "PricesError": {
        "properties": {
          "error": {
            "example": "unknown asset 1",
            "type": "string"
          }
        },
        "type": "object"
      },
      "PricesHistory": {
        "properties": {
          "asset": {
            "$ref": "#/components/schemas/PricesAsset"
          },
          "bin_seconds": {
            "type": "integer"
          },
          "from": {
            "format": "date-time",
            "type": "string"
          },
          "points": {
            "items": {
              "$ref": "#/components/schemas/PricesPoint"
            },
            "type": "array"
          },
          "pools": {
            "type": "integer"
          },
          "quote": {
            "$ref": "#/components/schemas/PricesAsset"
          },
          "source": {
            "enum": [
              "events",
              "bars_1h",
              "daily"
            ],
            "type": "string"
          },
          "to": {
            "format": "date-time",
            "type": "string"
          }
        },
        "type": "object"
      },
      "PricesPair": {
        "properties": {
          "active_pools": {
            "type": "integer"
          },
          "asset_a": {
            "$ref": "#/components/schemas/PricesAsset"
          },
          "asset_b": {
            "$ref": "#/components/schemas/PricesAsset"
          },
          "pools": {
            "type": "integer"
          },
          "price": {
            "description": "Close: asset B per asset A (whole units), deepest pool",
            "type": "number"
          },
          "reserve_a": {
            "type": "number"
          },
          "reserve_b": {
            "type": "number"
          },
          "swaps": {
            "type": "integer"
          },
          "tvl_usd": {
            "type": "number"
          },
          "venues": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "volume_a": {
            "type": "number"
          },
          "volume_b": {
            "type": "number"
          },
          "volume_usd": {
            "type": "number"
          }
        },
        "type": "object"
      },
      "PricesPairs": {
        "properties": {
          "count": {
            "type": "integer"
          },
          "date": {
            "format": "date",
            "type": "string"
          },
          "final": {
            "type": "boolean"
          },
          "pairs": {
            "items": {
              "$ref": "#/components/schemas/PricesPair"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "PricesPoint": {
        "properties": {
          "algo": {
            "nullable": true,
            "type": "number"
          },
          "liquidity_usd": {
            "type": "number"
          },
          "price": {
            "nullable": true,
            "type": "number"
          },
          "ts": {
            "format": "date-time",
            "type": "string"
          },
          "usdc": {
            "nullable": true,
            "type": "number"
          }
        },
        "type": "object"
      },
      "PricesPool": {
        "properties": {
          "address": {
            "type": "string"
          },
          "app_id": {
            "format": "int64",
            "type": "integer"
          },
          "asa_a": {
            "format": "int64",
            "type": "integer"
          },
          "asa_b": {
            "format": "int64",
            "type": "integer"
          },
          "fee_bps": {
            "type": "number"
          },
          "first_round": {
            "format": "int64",
            "type": "integer"
          },
          "lp_asa": {
            "format": "int64",
            "type": "integer"
          },
          "pool_id": {
            "description": "App id, or the LP-token ASA id for Tinyman V2",
            "format": "int64",
            "type": "integer"
          },
          "venue": {
            "enum": [
              "tinyman2",
              "pact",
              "pactstable",
              "pactw",
              "biatec",
              "humble",
              "algofi",
              "liquihog",
              "nanoswap",
              "talgo",
              "xalgo",
              "folks"
            ],
            "type": "string"
          }
        },
        "type": "object"
      },
      "PricesPools": {
        "properties": {
          "asset": {
            "format": "int64",
            "type": "integer"
          },
          "count": {
            "type": "integer"
          },
          "pools": {
            "items": {
              "$ref": "#/components/schemas/PricesPool"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "PricesPrice": {
        "example": {
          "algo": 806462.88,
          "asset": {
            "decimals": 8,
            "id": 386192725,
            "name": "goBTC",
            "unit": "goBTC"
          },
          "asset_usd": {
            "hops": 1,
            "liquidity_usd": 122543.4,
            "usd": 74302.41
          },
          "price": 74302.41,
          "quote": {
            "decimals": 6,
            "id": 31566704,
            "name": "USDC",
            "unit": "USDC"
          },
          "quote_usd": {
            "usd": 1
          },
          "round": 65000000,
          "ts": "2026-09-13T09:16:17Z",
          "usdc": 74302.41
        },
        "properties": {
          "algo": {
            "nullable": true,
            "type": "number"
          },
          "asset": {
            "$ref": "#/components/schemas/PricesAsset"
          },
          "asset_usd": {
            "$ref": "#/components/schemas/PricesAssetUSD"
          },
          "price": {
            "description": "Whole quote units per whole asset unit",
            "nullable": true,
            "type": "number"
          },
          "quote": {
            "$ref": "#/components/schemas/PricesAsset"
          },
          "quote_usd": {
            "$ref": "#/components/schemas/PricesAssetUSD"
          },
          "requested_ts": {
            "description": "Present when ts was at or after the indexed tip",
            "format": "date-time",
            "type": "string"
          },
          "round": {
            "format": "int64",
            "type": "integer"
          },
          "ts": {
            "format": "date-time",
            "type": "string"
          },
          "usdc": {
            "nullable": true,
            "type": "number"
          }
        },
        "type": "object"
      },
      "PricesRoute": {
        "properties": {
          "kept": {
            "type": "boolean"
          },
          "pool_id": {
            "format": "int64",
            "type": "integer"
          },
          "price_usd": {
            "type": "number"
          },
          "venue": {
            "type": "string"
          },
          "via": {
            "description": "Asset on the other side of the pool",
            "format": "int64",
            "type": "integer"
          },
          "weight_usd": {
            "type": "number"
          }
        },
        "type": "object"
      },
      "PricesStatus": {
        "properties": {
          "final_day": {
            "format": "date",
            "type": "string"
          },
          "round": {
            "format": "int64",
            "type": "integer"
          },
          "ts": {
            "format": "date-time",
            "type": "string"
          }
        },
        "type": "object"
      }
    }
  },
  "tags": [
    {
      "name": "search",
      "description": "Nodely Search and Scrape (x402)"
    },
    {
      "name": "prices",
      "description": "Nodely DEX Prices (x402)"
    }
  ]
}
