{
  "openapi": "3.1.0",
  "info": {
    "title": "listof.tools public catalogue",
    "version": "0.1.0",
    "description": "Discover and invoke approved, anonymous, read-only operations."
  },
  "servers": [
    {
      "url": "https://listof.tools"
    }
  ],
  "paths": {
    "/api/run/check-mdn-browser-support": {
      "get": {
        "operationId": "check_mdn_browser_support",
        "summary": "Check browser support",
        "description": "Search by feature name or MDN key, such as api.AbortController. Returns up to five matches with support versions, flags and notes. Results identify the versioned MDN dataset hosted by listof.tools.",
        "parameters": [
          {
            "in": "query",
            "name": "feature",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 160,
              "example": "css.properties.grid-template-columns.subgrid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Returns MDN Subgrid data with Chrome, Firefox and Safari support versions and a dataset version.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/check-caniuse-browser-support": {
      "get": {
        "operationId": "check_caniuse_browser_support",
        "summary": "Check browser support",
        "description": "Enter a feature name or Can I use ID, such as css-subgrid. Shows up to five matching features and support in the browser versions marked current in the dataset. Expand a result for the full version history. Uses a versioned copy of Can I use data hosted by listof.tools.",
        "parameters": [
          {
            "in": "query",
            "name": "feature",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 160,
              "example": "css-subgrid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Returns CSS Subgrid support tables, notes and a dataset version.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/check-web-feature-support": {
      "get": {
        "operationId": "check_web_feature_support",
        "summary": "Check browser support",
        "description": "Enter a Web Platform Status feature ID, such as subgrid. Returns its recorded implementation versions across desktop and mobile browsers. These are feature-level implementation records; consult MDN or Can I use for detailed exceptions.",
        "parameters": [
          {
            "in": "query",
            "name": "feature",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 120,
              "example": "subgrid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The response includes Subgrid with browser implementation versions and a Baseline status.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/check-feature-baseline": {
      "get": {
        "operationId": "check_feature_baseline",
        "summary": "Check a feature’s Baseline status",
        "description": "Enter a Web Platform Status feature ID, such as subgrid. Returns the recorded Baseline status and dates, where available. Baseline describes support across its core browser set; it does not establish support in every browser or older version.",
        "parameters": [
          {
            "in": "query",
            "name": "feature",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 120,
              "example": "subgrid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The response includes Subgrid with browser implementation versions and a Baseline status.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/search-web-features": {
      "get": {
        "operationId": "search_web_features",
        "summary": "Search web platform features",
        "description": "Search Web Platform Status by name or keyword. Returns up to five matching features with IDs and Baseline status. Use a feature ID for a focused support or Baseline lookup.",
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 120,
              "example": "subgrid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The response includes Subgrid with browser implementation versions and a Baseline status.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/calculate-expression": {
      "get": {
        "operationId": "calculate_expression",
        "summary": "Calculate an expression",
        "description": "Supports arithmetic, functions and unit conversions.",
        "parameters": [
          {
            "in": "query",
            "name": "expr",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 200,
              "example": "2 * (7 - 3)"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result should be 8",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/generate-qr-code": {
      "get": {
        "operationId": "generate_qr_code",
        "summary": "Generate a QR code",
        "description": "Returns a PNG QR code.",
        "parameters": [
          {
            "in": "query",
            "name": "text",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 400,
              "example": "https://listof.tools"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Response must be a PNG image",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/find-place": {
      "get": {
        "operationId": "find_place",
        "summary": "Find coordinates for a place",
        "description": "Returns matching places and their coordinates.",
        "parameters": [
          {
            "in": "query",
            "name": "name",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 100,
              "example": "Nottingham"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Response should have matching locations and coordinates",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/lookup-exchange-rate": {
      "get": {
        "operationId": "lookup_exchange_rate",
        "summary": "Look up an exchange rate",
        "description": "Reference rates, not live trading prices.",
        "parameters": [
          {
            "in": "query",
            "name": "base",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "GBP",
                "USD",
                "EUR",
                "CAD",
                "AUD",
                "JPY",
                "CHF"
              ],
              "example": "GBP"
            }
          },
          {
            "in": "query",
            "name": "symbols",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "EUR",
                "GBP",
                "USD",
                "CAD",
                "AUD",
                "JPY",
                "CHF"
              ],
              "example": "EUR"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Response should contain a numeric rate",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/search-books": {
      "get": {
        "operationId": "search_books",
        "summary": "Search books by title",
        "description": "Returns book records from Open Library.",
        "parameters": [
          {
            "in": "query",
            "name": "title",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 120,
              "example": "Aurora"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Response should include a list of matching books",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/check-package-vulnerabilities": {
      "get": {
        "operationId": "check_package_vulnerabilities",
        "summary": "Check package vulnerabilities",
        "description": "Queries published vulnerability records for a package version.",
        "parameters": [
          {
            "in": "query",
            "name": "ecosystem",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "npm",
                "PyPI",
                "Go",
                "Maven",
                "crates.io"
              ],
              "example": "npm"
            }
          },
          {
            "in": "query",
            "name": "name",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 120,
              "example": "lodash"
            }
          },
          {
            "in": "query",
            "name": "version",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 40,
              "example": "4.17.20"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Returns vulnerability records for lodash 4.17.20",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/check-food-hygiene": {
      "get": {
        "operationId": "check_food_hygiene",
        "summary": "Check food hygiene ratings",
        "description": "Search food businesses by name and town or postcode.",
        "parameters": [
          {
            "in": "query",
            "name": "name",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 100,
              "example": "pizza"
            }
          },
          {
            "in": "query",
            "name": "address",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 100,
              "example": "Nottingham"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Returns business names, ratings and inspection dates",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/search-research-papers": {
      "get": {
        "operationId": "search_research_papers",
        "summary": "Search research papers",
        "description": "Search life sciences literature, including articles and preprints.",
        "parameters": [
          {
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 200,
              "example": "CRISPR"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Returns matching papers with titles and identifiers",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/find-species-records": {
      "get": {
        "operationId": "find_species_records",
        "summary": "Find species records",
        "description": "Find records for a species in a country. Uses scientific names.",
        "parameters": [
          {
            "in": "query",
            "name": "scientificName",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 120,
              "example": "Falco peregrinus"
            }
          },
          {
            "in": "query",
            "name": "country",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 2,
              "example": "GB"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Returns dated records with coordinates",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/check-flood-warnings": {
      "get": {
        "operationId": "check_flood_warnings",
        "summary": "Check flood warnings",
        "description": "Find warnings for an English county. An empty list means no matching alerts were returned.",
        "parameters": [
          {
            "in": "query",
            "name": "county",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 100,
              "example": "Nottinghamshire"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Returns an official alerts list, which may be empty",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/lookup-uk-postcode": {
      "get": {
        "operationId": "lookup_uk_postcode",
        "summary": "Look up a UK postcode",
        "description": "Find a postcode’s council, ward, constituency, region, country and coordinates. Partial postcodes return the first five prefix matches; no match returns an empty result.",
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 10,
              "example": "NG1 2DT"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "NG1 2DT should return Nottingham, East Midlands and geographic coordinates.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/find-place-areas": {
      "get": {
        "operationId": "find_place_areas",
        "summary": "Search places",
        "description": "Returns up to five matching places, with coordinates and available country, state and county fields. Regional fields may be incomplete and do not list every area containing the place. Add a country code to narrow the search.",
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 120,
              "example": "Nottingham"
            }
          },
          {
            "in": "query",
            "name": "countrycode",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 2,
              "example": "GB"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Nottingham match should include coordinates, country and available regional address fields.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/find-place-coordinates": {
      "get": {
        "operationId": "find_place_coordinates",
        "summary": "Find coordinates for a place",
        "description": "Search for a named place and compare up to five matches with their latitude and longitude. Regional details help distinguish places with the same name. Useful for map markers or other location lookups.",
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 120,
              "example": "Nottingham"
            }
          },
          {
            "in": "query",
            "name": "countrycode",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 2,
              "example": "GB"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Nottingham match should include coordinates, country and available regional address fields.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/lookup-place-regions": {
      "get": {
        "operationId": "lookup_place_regions",
        "summary": "Look up a place’s regional details",
        "description": "Search for a named place and compare the country, state and county fields supplied for up to five matches. Fields may be missing and do not list every area containing the place.",
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 120,
              "example": "Nottingham"
            }
          },
          {
            "in": "query",
            "name": "countrycode",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 2,
              "example": "GB"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A Nottingham match should include coordinates, country and available regional address fields.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/find-parent-regions": {
      "get": {
        "operationId": "find_parent_regions",
        "summary": "Find a named area’s parent regions",
        "description": "Enter the exact English Wikipedia article title for a place or region, including any disambiguation in brackets. Returns Wikidata’s recorded administrative parent chain and country. Records can be incomplete or include historical relationships; this is not a polygon containment test.",
        "parameters": [
          {
            "in": "query",
            "name": "name",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 160,
              "example": "Nottingham"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Nottingham should include England, East Midlands and United Kingdom among its recorded parents.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/lookup-french-postcode": {
      "get": {
        "operationId": "lookup_french_postcode",
        "summary": "Look up a French postcode",
        "description": "Find the French communes using a postal code, with their department and region names and codes. A postcode can cover several communes.",
        "parameters": [
          {
            "in": "query",
            "name": "codePostal",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 5,
              "example": "44000"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "44000 should return Nantes, Loire-Atlantique and Pays de la Loire.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/find-french-town-regions": {
      "get": {
        "operationId": "find_french_town_regions",
        "summary": "Find a French town’s department and region",
        "description": "Search French communes by name and return their department and region, with official codes. The five matches are ranked with larger populations first; check the commune when names are shared.",
        "parameters": [
          {
            "in": "query",
            "name": "nom",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 100,
              "example": "Nantes"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Nantes should include its department Loire-Atlantique and region Pays de la Loire.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/inspect-link-metadata": {
      "get": {
        "operationId": "inspect_link_metadata",
        "summary": "Inspect a link’s sharing metadata",
        "description": "Returns a public page’s title, description, sharing tags, image and favicon URLs, resolved Details preview and warnings as JSON. Image availability and dimensions are not checked. URLs are not submitted to the gallery.",
        "parameters": [
          {
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri",
              "maxLength": 500,
              "example": "https://unfurls.to/"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Returns one successful metadata entry, with sharing tags and a Details preview.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/run/compare-link-previews": {
      "get": {
        "operationId": "compare_link_previews",
        "summary": "Compare links’ sharing previews",
        "description": "Compare 2–100 public URLs in a platform, All, image, icon or metadata view. Returns JSON and comparison links; duplicates are removed and normalized order is kept. Each site has a result or error. Cards are estimates. Large results may exceed our 256 KiB limit; open the comparison on unfurls.to instead.",
        "parameters": [
          {
            "in": "query",
            "name": "urls",
            "required": true,
            "schema": {
              "type": "string",
              "description": "One public HTTP(S) URL per line. Prefer POST with a JSON array for long lists.",
              "maxLength": 205000,
              "example": "https://listof.tools/\nhttps://unfurls.to/\nhttps://example.org/"
            }
          },
          {
            "in": "query",
            "name": "view",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "details",
                "images",
                "favicon",
                "imessage",
                "bluesky",
                "discord",
                "facebook",
                "linkedin",
                "slack",
                "telegram",
                "whatsapp",
                "x"
              ],
              "example": "slack"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Returns three successful entries in the requested order, each with a Slack preview and warnings array.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      },
      "post": {
        "operationId": "compare_link_previews_post",
        "summary": "Compare links’ sharing previews",
        "description": "Read-only execution with JSON inputs. Prefer this for URL lists to avoid request-URL length limits. Input body limit: 220 KiB; provider result limit: 256 KiB.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "urls",
                  "view"
                ],
                "properties": {
                  "urls": {
                    "type": "array",
                    "minItems": 2,
                    "maxItems": 100,
                    "items": {
                      "type": "string",
                      "format": "uri",
                      "maxLength": 2048
                    }
                  },
                  "view": {
                    "type": "string",
                    "enum": [
                      "all",
                      "details",
                      "images",
                      "favicon",
                      "imessage",
                      "bluesky",
                      "discord",
                      "facebook",
                      "linkedin",
                      "slack",
                      "telegram",
                      "whatsapp",
                      "x"
                    ]
                  }
                }
              },
              "example": {
                "urls": [
                  "https://listof.tools/",
                  "https://unfurls.to/",
                  "https://example.org/"
                ],
                "view": "slack"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Returns three successful entries in the requested order, each with a Slack preview and warnings array.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Invalid inputs"
          },
          "413": {
            "description": "Inputs exceed 220 KiB"
          },
          "415": {
            "description": "Use application/json"
          },
          "429": {
            "description": "Rate limited"
          },
          "502": {
            "description": "Provider failure or response exceeds 256 KiB"
          },
          "503": {
            "description": "Requests paused or accounting unavailable"
          }
        }
      }
    },
    "/api/run/find-recent-earthquakes-fae47142": {
      "get": {
        "operationId": "find_recent_earthquakes_fae47142",
        "summary": "Find recent earthquakes",
        "description": "The five most recent earthquakes above a minimum magnitude, with locations and times.",
        "parameters": [
          {
            "in": "query",
            "name": "minmagnitude",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 10,
              "example": "4.5"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The submitted example passed its response check.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Per-client or shared provider/site allowance reached; respect Retry-After.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds before retrying."
              }
            }
          },
          "502": {
            "description": "Provider failure"
          },
          "503": {
            "description": "Requests paused or usage accounting unavailable."
          },
          "504": {
            "description": "Provider timeout"
          }
        }
      }
    },
    "/api/tool-schema": {
      "get": {
        "summary": "Tool submission schema",
        "responses": {
          "200": {
            "description": "JSON Schema for a tool definition"
          }
        }
      }
    },
    "/api/feedback/{id}": {
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "summary": "Read anonymous tool feedback",
        "description": "Unverified counts of worked, useful and provider trust signals. These are opinions, not independent checks. Optionally provide X-Feedback-Client to retrieve your own selected signals.",
        "parameters": [
          {
            "in": "header",
            "name": "X-Feedback-Client",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 16,
              "maxLength": 80,
              "pattern": "^[a-zA-Z0-9_-]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Feedback counts and optional own selections",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "counts": {
                      "type": "object",
                      "properties": {
                        "worked": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "useful": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "trusted": {
                          "type": "integer",
                          "minimum": 0
                        }
                      }
                    },
                    "unverified": {
                      "const": true
                    },
                    "selected": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "worked",
                          "useful",
                          "trusted"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown or disabled tool"
          }
        }
      },
      "post": {
        "summary": "Add or undo your feedback",
        "description": "For people and AI clients. Report only your actual experience or judgement. Reuse a random clientId; do not use a personal identifier. Repeating the same signal counts once. value:false removes it.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "signal",
                  "value",
                  "clientId"
                ],
                "properties": {
                  "signal": {
                    "type": "string",
                    "enum": [
                      "worked",
                      "useful",
                      "trusted"
                    ]
                  },
                  "value": {
                    "type": "boolean"
                  },
                  "clientId": {
                    "type": "string",
                    "minLength": 16,
                    "maxLength": 80,
                    "pattern": "^[a-zA-Z0-9_-]+$"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated unverified counts"
          },
          "400": {
            "description": "Invalid feedback"
          },
          "404": {
            "description": "Unknown or disabled tool"
          },
          "429": {
            "description": "Rate limited"
          }
        }
      }
    },
    "/api/submissions": {
      "post": {
        "summary": "Submit a tool for review",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "title": "listof.tools tool definition",
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "name",
                  "provider",
                  "description",
                  "documentation",
                  "endpoint",
                  "method",
                  "output",
                  "parameters",
                  "example",
                  "check"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "provider": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "category": {
                    "type": "string",
                    "maxLength": 40
                  },
                  "description": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "documentation": {
                    "type": "string",
                    "format": "uri",
                    "pattern": "^https://",
                    "maxLength": 500
                  },
                  "endpoint": {
                    "type": "string",
                    "format": "uri",
                    "pattern": "^https://",
                    "maxLength": 500
                  },
                  "method": {
                    "enum": [
                      "GET",
                      "POST"
                    ]
                  },
                  "output": {
                    "enum": [
                      "json",
                      "text",
                      "image"
                    ]
                  },
                  "parameters": {
                    "type": "array",
                    "maxItems": 8,
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "name"
                      ],
                      "properties": {
                        "name": {
                          "type": "string",
                          "pattern": "^[a-zA-Z][a-zA-Z0-9_-]*$",
                          "maxLength": 40
                        },
                        "label": {
                          "type": "string",
                          "maxLength": 80
                        },
                        "type": {
                          "enum": [
                            "text",
                            "enum",
                            "url",
                            "url-list"
                          ],
                          "default": "text"
                        },
                        "required": {
                          "type": "boolean",
                          "default": true
                        },
                        "maxLength": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 2048,
                          "description": "Per-item length for url-list (up to 2048); other types allow up to 500."
                        },
                        "minItems": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 100
                        },
                        "maxItems": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 100
                        },
                        "example": {
                          "type": "string",
                          "maxLength": 2048
                        },
                        "choices": {
                          "type": "array",
                          "minItems": 1,
                          "maxItems": 30,
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  },
                  "example": {
                    "type": "object",
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "array",
                          "maxItems": 100,
                          "items": {
                            "type": "string",
                            "format": "uri",
                            "maxLength": 2048
                          }
                        }
                      ]
                    }
                  },
                  "fixedQuery": {
                    "type": "object",
                    "maxProperties": 8,
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 512
                    }
                  },
                  "fixedHeaders": {
                    "type": "object",
                    "maxProperties": 8,
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 512
                    }
                  },
                  "bodyTemplate": {
                    "type": "object",
                    "description": "For read-only POST requests. Replace \"$inputName\" values with the matching input."
                  },
                  "queryTemplate": {
                    "type": "object",
                    "maxProperties": 8,
                    "description": "For GET queries: {{inputName}} becomes a quoted JSON/SPARQL string literal, never raw query code. References must name required inputs.",
                    "additionalProperties": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 4000
                    }
                  },
                  "check": {
                    "description": "Required for submissions: expected JSON field/type, text value or PNG check.",
                    "oneOf": [
                      {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "path",
                          "type"
                        ],
                        "properties": {
                          "path": {
                            "type": "string",
                            "maxLength": 160
                          },
                          "type": {
                            "enum": [
                              "object",
                              "array",
                              "string",
                              "number",
                              "boolean",
                              "null"
                            ]
                          },
                          "equals": {
                            "type": [
                              "string",
                              "number",
                              "boolean",
                              "null"
                            ]
                          }
                        }
                      },
                      {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "contains"
                        ],
                        "properties": {
                          "contains": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 500
                          }
                        }
                      },
                      {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "equals"
                        ],
                        "properties": {
                          "equals": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 500
                          }
                        }
                      },
                      {
                        "type": "object",
                        "maxProperties": 0
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Saved for review"
          },
          "400": {
            "description": "Invalid definition"
          },
          "409": {
            "description": "Duplicate tool"
          },
          "429": {
            "description": "Rate limited"
          }
        }
      }
    },
    "/api/submissions/{id}": {
      "get": {
        "summary": "Check submission status",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Submission status"
          },
          "404": {
            "description": "Unknown submission"
          }
        }
      }
    },
    "/api/reports/{id}": {
      "post": {
        "summary": "Report a listed tool",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "reason"
                ],
                "properties": {
                  "reason": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Report received"
          },
          "429": {
            "description": "Rate limited"
          }
        }
      }
    },
    "/api/operations": {
      "get": {
        "summary": "Search operations",
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "category",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "provider",
            "schema": {
              "type": "string"
            },
            "description": "Exact group value from /api/providers or /api/endpoints."
          },
          {
            "in": "query",
            "name": "endpoint",
            "schema": {
              "type": "string"
            },
            "description": "Exact group value from /api/providers or /api/endpoints."
          }
        ],
        "responses": {
          "200": {
            "description": "List of operations"
          }
        }
      }
    },
    "/api/providers": {
      "get": {
        "summary": "List providers and their tool IDs",
        "responses": {
          "200": {
            "description": "Provider groups"
          }
        }
      }
    },
    "/api/endpoints": {
      "get": {
        "summary": "List provider endpoints and their tool IDs",
        "description": "Groups share the same HTTP method and exact URL path; fixed query parameters may differ.",
        "responses": {
          "200": {
            "description": "Endpoint groups"
          }
        }
      }
    },
    "/api/compatibility/{source}": {
      "get": {
        "summary": "Look up versioned MDN or Can I use data hosted by listof.tools",
        "parameters": [
          {
            "in": "path",
            "name": "source",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "mdn",
                "caniuse"
              ]
            }
          },
          {
            "in": "query",
            "name": "feature",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 160
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Up to five source records, dataset version and total matching count"
          },
          "400": {
            "description": "Invalid input"
          },
          "422": {
            "description": "Use a narrower feature key"
          },
          "429": {
            "description": "Rate limited"
          },
          "503": {
            "description": "Dataset unavailable"
          }
        }
      }
    },
    "/api/operations/{id}": {
      "get": {
        "summary": "Get operation specification",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Operation details"
          }
        }
      }
    },
    "/api/run/{id}": {
      "get": {
        "summary": "Execute an allowlisted operation",
        "description": "Use the parameter schema returned by /api/operations/{id}. Responses may be plain text, JSON or PNG.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result"
          },
          "400": {
            "description": "Invalid input"
          },
          "429": {
            "description": "Rate limited"
          },
          "502": {
            "description": "Provider failure"
          }
        }
      }
    }
  }
}