{
  "openapi": "3.1.0",
  "info": {
    "title": "Within20 Search",
    "version": "0.2.0",
    "description": "Individual secondhand searches. No API key. Shared budgets; no bulk indexing. Original listing citations required.",
    "termsOfService": "https://within20.lanekingsbery.chatgpt.site/terms"
  },
  "servers": [
    {
      "url": "https://within20.lanekingsbery.chatgpt.site",
      "description": "Public beta"
    }
  ],
  "paths": {
    "/api/v1/search": {
      "post": {
        "operationId": "searchSecondhand",
        "summary": "Search connected secondhand inventories",
        "description": "Server-side clients need no Origin header or cookies. Browsers must be same-origin. Maximum request body 4096 bytes.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Search completed; sources can still be unavailable or partial. No-store.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Request could not be completed. Never treat as empty successful coverage.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Hosting or origin access denied. This is not an empty inventory response. Do not retry with another identity."
          },
          "413": {
            "description": "Request could not be completed. Never treat as empty successful coverage.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "415": {
            "description": "Request could not be completed. Never treat as empty successful coverage.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Request could not be completed. Never treat as empty successful coverage.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Request could not be completed. Never treat as empty successful coverage.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Request could not be completed. Never treat as empty successful coverage.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds before retry."
              }
            }
          }
        },
        "security": [
          {
            "HostingAccess": []
          }
        ]
      }
    },
    "/api/sources": {
      "get": {
        "operationId": "getSources",
        "summary": "List searchable sources",
        "responses": {
          "200": {
            "description": "Active inventory sources. Per-search responses report actual source availability.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "connected"
                  ],
                  "properties": {
                    "connected": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Request could not be completed. Never treat as empty successful coverage.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Hosting or origin access denied. This is not an empty inventory response. Do not retry with another identity."
          }
        },
        "security": [
          {
            "HostingAccess": []
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "SearchInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "string",
            "minLength": 2,
            "maxLength": 180
          },
          "location": {
            "type": "string",
            "maxLength": 180,
            "default": "",
            "description": "Optional U.S. ZIP, city and state, or address. Omit or leave empty to search nationwide; no location lookup occurs."
          },
          "radiusMiles": {
            "type": "number",
            "minimum": 1,
            "maximum": 100,
            "default": 20,
            "description": "Applies only when a location is supplied."
          },
          "includeShipping": {
            "type": "boolean",
            "description": "Defaults to true for nationwide search, false when a location is supplied. Nationwide searches cannot set this to false."
          },
          "brand": {
            "type": "string",
            "maxLength": 60
          },
          "model": {
            "type": "string",
            "maxLength": 60
          },
          "maxPrice": {
            "type": "number",
            "minimum": 0,
            "maximum": 100000,
            "description": "USD price ceiling. Unknown prices and non-guaranteed auction bids may be omitted."
          },
          "sourceIds": {
            "type": "array",
            "maxItems": 5,
            "items": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,79}$"
            }
          }
        }
      },
      "Location": {
        "type": "object",
        "required": [
          "label",
          "latitude",
          "longitude",
          "precision",
          "provider"
        ],
        "properties": {
          "label": {
            "type": "string"
          },
          "postalCode": {
            "type": "string"
          },
          "latitude": {
            "type": "number"
          },
          "longitude": {
            "type": "number"
          },
          "precision": {
            "enum": [
              "postcode",
              "city",
              "address"
            ]
          },
          "provider": {
            "type": "string"
          }
        }
      },
      "Result": {
        "type": "object",
        "required": [
          "id",
          "title",
          "url",
          "store",
          "sourceId",
          "sourceName",
          "observedAt",
          "evidence",
          "distanceMiles",
          "matchLabel"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "store": {
            "type": "string"
          },
          "sourceId": {
            "type": "string"
          },
          "sourceName": {
            "type": "string"
          },
          "condition": {
            "type": "string"
          },
          "pickupNote": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "imageUrl": {
            "type": "string",
            "format": "uri"
          },
          "price": {
            "type": "object",
            "properties": {
              "amount": {
                "type": "number"
              },
              "currency": {
                "type": "string"
              }
            }
          },
          "priceType": {
            "enum": [
              "asking",
              "current_bid"
            ]
          },
          "location": {
            "$ref": "#/components/schemas/Location"
          },
          "distanceMiles": {
            "type": [
              "number",
              "null"
            ]
          },
          "distanceBasis": {
            "enum": [
              "straight_line",
              "unknown"
            ]
          },
          "fulfillment": {
            "const": "shipping",
            "description": "When present, this is shipping-only discovery; it establishes no local pickup."
          },
          "conditionBasis": {
            "enum": [
              "catalog_inference",
              "listing_text"
            ]
          },
          "locationBasis": {
            "const": "listing_area"
          },
          "pickupSupported": {
            "type": "boolean"
          },
          "observedAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "freshness": {
            "enum": [
              "fresh",
              "aging",
              "stale"
            ]
          },
          "evidence": {
            "enum": [
              "confirmed_inventory",
              "online_listing",
              "recently_observed"
            ]
          },
          "matchConfidence": {
            "type": "number"
          },
          "matchLabel": {
            "enum": [
              "Strong match",
              "Possible match"
            ]
          },
          "matchReasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sourceConfidence": {
            "enum": [
              "direct_sync",
              "merchant_catalog",
              "marketplace_listing"
            ]
          },
          "likelyDuplicateUrls": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "displayGroup": {
            "const": "ebay"
          }
        }
      },
      "SourceReport": {
        "type": "object",
        "required": [
          "id",
          "name",
          "status",
          "resultCount"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "searchMode": {
            "const": "shipping"
          },
          "status": {
            "enum": [
              "ok",
              "cached",
              "unavailable",
              "cooldown",
              "stale"
            ]
          },
          "observedAt": {
            "type": "string",
            "format": "date-time"
          },
          "message": {
            "type": "string"
          },
          "failureCode": {
            "enum": [
              "rate_limited",
              "access_denied",
              "bad_response",
              "unavailable"
            ]
          },
          "resultCount": {
            "type": "integer"
          },
          "upstreamHttpStatus": {
            "type": "integer"
          }
        }
      },
      "SearchResponse": {
        "type": "object",
        "required": [
          "request",
          "results",
          "sources",
          "coverage",
          "searchedAt",
          "strongMatchCount",
          "omittedUnknownLocation",
          "omittedUnknownPrice",
          "truncated",
          "externalChecks"
        ],
        "properties": {
          "request": {
            "type": "object",
            "properties": {
              "query": {
                "type": "string",
                "minLength": 2,
                "maxLength": 180
              },
              "location": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/Location"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Null for nationwide searches; never a guessed location."
              },
              "radiusMiles": {
                "type": "number",
                "minimum": 1,
                "maximum": 100,
                "default": 20
              },
              "includeShipping": {
                "type": "boolean",
                "default": false
              },
              "brand": {
                "type": "string",
                "maxLength": 60
              },
              "model": {
                "type": "string",
                "maxLength": 60
              },
              "maxPrice": {
                "type": "number",
                "minimum": 0,
                "maximum": 100000,
                "description": "USD price ceiling. Unknown prices and non-guaranteed auction bids may be omitted."
              },
              "sourceIds": {
                "type": "array",
                "maxItems": 5,
                "items": {
                  "type": "string",
                  "pattern": "^[a-z0-9][a-z0-9-]{0,79}$"
                }
              }
            }
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Result"
            },
            "description": "Nearby matches only."
          },
          "shippingResults": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Result"
            },
            "description": "Separate opt-in shipped finds; never imply pickup."
          },
          "sources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SourceReport"
            }
          },
          "coverage": {
            "enum": [
              "connected_sources",
              "no_connected_sources",
              "sources_unavailable"
            ],
            "description": "Nearby coverage; also inspect shipping source reports."
          },
          "searchedAt": {
            "type": "string",
            "format": "date-time"
          },
          "strongMatchCount": {
            "type": "integer",
            "description": "Nearby strong matches only."
          },
          "omittedUnknownLocation": {
            "type": "integer"
          },
          "omittedUnknownPrice": {
            "type": "integer"
          },
          "truncated": {
            "type": "boolean"
          },
          "externalChecks": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "note": {
                  "type": "string"
                },
                "evidence": {
                  "const": "external_check"
                }
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "HostingAccess": {
        "type": "apiKey",
        "in": "header",
        "name": "OAI-Sites-Authorization",
        "description": "Where hosting access controls apply, use Bearer followed by a private access token supplied for an authorized integration. Do not publish credentials. Anonymous access on the current host is not verified."
      }
    }
  }
}
