{
 "openapi": "3.1.0",
 "info": {
  "title": "Vellium & Co Testing Lab API",
  "version": "1",
  "description": "Independent checks of paid x402 data services and of how well AI agents can use major shopping and travel websites. Free, CORS-open, no key. MCP: POST /mcp. Paid detail: GET /api/seller (x402 v2)."
 },
 "servers": [
  {
   "url": "https://velliumandco.com"
  }
 ],
 "paths": {
  "/api/v1/seller": {
   "get": {
    "operationId": "check_seller",
    "summary": "Latest check of one seller",
    "parameters": [
     {
      "name": "resource",
      "in": "query",
      "required": false,
      "description": "seller URL, any spelling",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "in": "query",
      "required": false,
      "description": "12-hex seller id",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK (JSON; every answer carries `freshness`)"
     },
     "400": {
      "description": "Bad request: JSON error with `fix`"
     },
     "404": {
      "description": "Not found: JSON with a hint"
     }
    }
   }
  },
  "/api/v1/sellers": {
   "get": {
    "operationId": "sellers_on_domain",
    "summary": "Every seller on a host",
    "parameters": [
     {
      "name": "domain",
      "in": "query",
      "required": true,
      "description": "host",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "max rows",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK (JSON; every answer carries `freshness`)"
     },
     "400": {
      "description": "Bad request: JSON error with `fix`"
     },
     "404": {
      "description": "Not found: JSON with a hint"
     }
    }
   }
  },
  "/api/v1/search": {
   "get": {
    "operationId": "search_sellers",
    "summary": "Ranked sellers in a category",
    "parameters": [
     {
      "name": "category",
      "in": "query",
      "required": true,
      "description": "category slug (see /api/v1/categories)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "description": "text match",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "max_price",
      "in": "query",
      "required": false,
      "description": "max USDC per call",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "min_buyers",
      "in": "query",
      "required": false,
      "description": "min paying buyers in 30 days",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "answering",
      "in": "query",
      "required": false,
      "description": "true = only sellers answering on our latest check",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "sort",
      "in": "query",
      "required": false,
      "description": "buyers | price | latency",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "1-100",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "cursor",
      "in": "query",
      "required": false,
      "description": "from next_cursor",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK (JSON; every answer carries `freshness`)"
     },
     "400": {
      "description": "Bad request: JSON error with `fix`"
     },
     "404": {
      "description": "Not found: JSON with a hint"
     }
    }
   }
  },
  "/api/v1/categories": {
   "get": {
    "operationId": "list_categories",
    "summary": "All categories and how we check them",
    "responses": {
     "200": {
      "description": "OK (JSON; every answer carries `freshness`)"
     },
     "400": {
      "description": "Bad request: JSON error with `fix`"
     },
     "404": {
      "description": "Not found: JSON with a hint"
     }
    }
   }
  },
  "/api/v1/website": {
   "get": {
    "operationId": "check_website",
    "summary": "Can AI agents use this website",
    "parameters": [
     {
      "name": "domain",
      "in": "query",
      "required": true,
      "description": "e.g. walmart.com",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK (JSON; every answer carries `freshness`)"
     },
     "400": {
      "description": "Bad request: JSON error with `fix`"
     },
     "404": {
      "description": "Not found: JSON with a hint"
     }
    }
   }
  },
  "/api/v1/websites": {
   "get": {
    "operationId": "list_websites",
    "summary": "Rated websites",
    "parameters": [
     {
      "name": "market",
      "in": "query",
      "required": false,
      "description": "e.g. United States, Japan",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "plain_agent",
      "in": "query",
      "required": false,
      "description": "open | blocked | timeout | unavailable | connection_error | unclear",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "detail",
      "in": "query",
      "required": false,
      "description": "full = per-agent tables for every site",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "1-300, default 40",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "cursor",
      "in": "query",
      "required": false,
      "description": "from next_cursor",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK (JSON; every answer carries `freshness`)"
     },
     "400": {
      "description": "Bad request: JSON error with `fix`"
     },
     "404": {
      "description": "Not found: JSON with a hint"
     }
    }
   }
  },
  "/api/v1/route": {
   "get": {
    "operationId": "find_route",
    "summary": "Where to go for any job: the best tested free source with its exact call, the topic, and registry-listed sources for it",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": true,
      "description": "what you need, in any of the lab's 19 languages",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "country",
      "in": "query",
      "required": false,
      "description": "ISO 3166 alpha-2, to rank that country's sources first",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "detail",
      "in": "query",
      "required": false,
      "description": "full = also paid sellers, registry-listed and other sources (a strong match otherwise returns the route alone)",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK (JSON; every answer carries `freshness`)"
     },
     "400": {
      "description": "Bad request: JSON error with `fix`"
     },
     "404": {
      "description": "Not found: JSON with a hint"
     }
    }
   }
  },
  "/api/v1/routes": {
   "get": {
    "operationId": "list_routes",
    "summary": "Every tested route",
    "parameters": [
     {
      "name": "family",
      "in": "query",
      "required": false,
      "description": "a route family",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "field",
      "in": "query",
      "required": false,
      "description": "a field of research",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK (JSON; every answer carries `freshness`)"
     },
     "400": {
      "description": "Bad request: JSON error with `fix`"
     },
     "404": {
      "description": "Not found: JSON with a hint"
     }
    }
   }
  },
  "/api/v1/source": {
   "get": {
    "operationId": "catalogue_source",
    "summary": "The full record of a listed source (the `more` link of a where_to_look entry)",
    "parameters": [
     {
      "name": "id",
      "in": "query",
      "required": true,
      "description": "id from where_to_look",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK (JSON; every answer carries `freshness`)"
     },
     "400": {
      "description": "Bad request: JSON error with `fix`"
     },
     "404": {
      "description": "Not found: JSON with a hint"
     }
    }
   }
  },
  "/api/v1/corrections": {
   "get": {
    "operationId": "corrections",
    "summary": "Every published reading later found wrong, with the reason",
    "responses": {
     "200": {
      "description": "OK (JSON; every answer carries `freshness`)"
     },
     "400": {
      "description": "Bad request: JSON error with `fix`"
     },
     "404": {
      "description": "Not found: JSON with a hint"
     }
    }
   }
  },
  "/api/v1/changes": {
   "get": {
    "operationId": "changes",
    "summary": "What changed since a day (no since = the latest day)",
    "parameters": [
     {
      "name": "since",
      "in": "query",
      "required": false,
      "description": "YYYY-MM-DD",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "items per page, default 400",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "cursor",
      "in": "query",
      "required": false,
      "description": "from next_cursor",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK (JSON; every answer carries `freshness`)"
     },
     "400": {
      "description": "Bad request: JSON error with `fix`"
     },
     "404": {
      "description": "Not found: JSON with a hint"
     }
    }
   }
  },
  "/api/v1/retest": {
   "get": {
    "operationId": "retest_status",
    "summary": "One re-test request and every step since",
    "parameters": [
     {
      "name": "id",
      "in": "query",
      "required": true,
      "description": "request id",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK (JSON; every answer carries `freshness`)"
     },
     "400": {
      "description": "Bad request: JSON error with `fix`"
     },
     "404": {
      "description": "Not found: JSON with a hint"
     }
    }
   },
   "post": {
    "operationId": "ask_retest",
    "summary": "Ask us to check a seller or website again",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "kind",
         "target",
         "reason"
        ],
        "properties": {
         "kind": {
          "type": "string",
          "enum": [
           "seller",
           "website"
          ]
         },
         "target": {
          "type": "string"
         },
         "reason": {
          "type": "string",
          "enum": [
           "now_fixed",
           "not_answering_wrong",
           "answer_marked_wrong",
           "blocked_wrongly",
           "price_wrong",
           "other"
          ]
         },
         "note": {
          "type": "string"
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK (JSON; every answer carries `freshness`)"
     },
     "400": {
      "description": "Bad request: JSON error with `fix`"
     },
     "404": {
      "description": "Not found: JSON with a hint"
     }
    }
   }
  },
  "/api/seller": {
   "get": {
    "operationId": "paid_seller_detail",
    "summary": "Paid detail for one seller ($0.001, x402 v2: 402 then PAYMENT-SIGNATURE)",
    "parameters": [
     {
      "name": "resource",
      "in": "query",
      "required": true,
      "description": "seller URL",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "detail"
     },
     "402": {
      "description": "payment terms in PAYMENT-REQUIRED"
     }
    }
   }
  }
 }
}