{
  "openapi": "3.1.0",
  "info": {
    "title": "SelectBNBs Public Property and Registration API",
    "version": "1.1.0",
    "description": "Read-only public metadata for curated boutique accommodations and privacy-bounded Korean registration evidence. No authentication is required. Property booking remains on the linked booking platforms.",
    "contact": {
      "email": "hi@selectbnbs.com"
    },
    "license": {
      "name": "SelectBNBs content policy",
      "url": "https://selectbnbs.com/agents.json"
    }
  },
  "servers": [
    {
      "url": "https://selectbnbs.com"
    }
  ],
  "paths": {
    "/api/index.json": {
      "get": {
        "operationId": "getApiDirectory",
        "summary": "List SelectBNBs public data endpoints",
        "responses": {
          "200": {
            "description": "Current API directory.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonDocument"
                }
              }
            }
          }
        }
      }
    },
    "/api/properties_full.json": {
      "get": {
        "operationId": "listProperties",
        "summary": "Fetch the complete curated property catalog",
        "description": "Canonical bulk dataset including booking links, source citations, data-completeness signals, and approved public imagery metadata.",
        "responses": {
          "200": {
            "description": "The current public property catalog.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PropertyCatalog"
                }
              }
            }
          }
        }
      }
    },
    "/api/filters/{filter_slug}.json": {
      "get": {
        "operationId": "getPropertyFilter",
        "summary": "Fetch a pre-computed property subset",
        "parameters": [
          {
            "name": "filter_slug",
            "in": "path",
            "required": true,
            "description": "Published city or use-case filter, such as seoul, couples, or hanoks. Discover current values through /api/index.json.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A current pre-computed property subset.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FilteredPropertyCatalog"
                }
              }
            }
          },
          "404": {
            "description": "The requested filter is not published."
          }
        }
      }
    },
    "/api/area_guides.json": {
      "get": {
        "operationId": "getAreaGuides",
        "summary": "Fetch published city and neighborhood guidance",
        "responses": {
          "200": {
            "description": "Current area and booking-platform guidance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonDocument"
                }
              }
            }
          }
        }
      }
    },
    "/api/completeness.json": {
      "get": {
        "operationId": "getDataCompleteness",
        "summary": "Fetch completeness and freshness metadata",
        "responses": {
          "200": {
            "description": "Current per-property completeness and source metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonDocument"
                }
              }
            }
          }
        }
      }
    },
    "/api/registry/status": {
      "get": {
        "operationId": "getKoreanRegistryCoverage",
        "summary": "Inspect Korean accommodation registry coverage",
        "description": "Returns cache freshness and the eight Ministry of the Interior and Safety LOCALDATA accommodation datasets covered by SelectBNBs.",
        "responses": {
          "200": {
            "description": "Current registry cache coverage.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegistryStatus"
                }
              }
            }
          },
          "429": {
            "description": "Public rate limit exceeded."
          },
          "503": {
            "description": "Registry cache unavailable."
          }
        }
      }
    },
    "/api/registry/verify": {
      "post": {
        "operationId": "verifyKoreanAccommodationRegistration",
        "summary": "Check one Korean accommodation registration",
        "description": "Accepts one government management number, registered business name, road address, supported listing URL, or copied registration block. Official record status, listing identity, and SelectBNBs editorial judgment are returned independently. A not-found result never means illegal or unlicensed.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegistryVerificationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Evidence-bounded verification result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegistryVerificationResult"
                }
              }
            }
          },
          "422": {
            "description": "The submitted input is invalid."
          },
          "429": {
            "description": "Public rate limit exceeded."
          },
          "503": {
            "description": "Registry cache unavailable."
          }
        }
      }
    },
    "/api/imagery/{property_uid}.json": {
      "get": {
        "operationId": "getPropertyImagery",
        "summary": "Fetch approved public imagery for one property",
        "parameters": [
          {
            "name": "property_uid",
            "in": "path",
            "required": true,
            "description": "Stable property identifier such as prp_c901f93.",
            "schema": {
              "type": "string",
              "pattern": "^prp_[0-9a-f]{7}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Approved public imagery metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonDocument"
                }
              }
            }
          },
          "404": {
            "description": "The property imagery manifest was not found."
          }
        }
      }
    },
    "/api/media/{property_uid}.json": {
      "get": {
        "operationId": "getPropertyMediaAnalysis",
        "summary": "Fetch public asset-level visual analysis",
        "parameters": [
          {
            "name": "property_uid",
            "in": "path",
            "required": true,
            "description": "Stable property identifier such as prp_c901f93.",
            "schema": {
              "type": "string",
              "pattern": "^prp_[0-9a-f]{7}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Public media analysis and licensing metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonDocument"
                }
              }
            }
          },
          "404": {
            "description": "The property media manifest was not found."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "JsonDocument": {
        "type": "object",
        "additionalProperties": true
      },
      "RegistryVerificationRequest": {
        "type": "object",
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4000,
            "description": "One management number, registered name, road address, supported listing URL, or copied registration block."
          },
          "language": {
            "type": "string",
            "enum": [
              "en",
              "ko"
            ],
            "default": "en"
          }
        },
        "additionalProperties": false
      },
      "VerificationAxis": {
        "type": "object",
        "required": [
          "status",
          "label",
          "explanation"
        ],
        "properties": {
          "status": {
            "type": "string"
          },
          "label": {
            "type": "object",
            "required": [
              "en",
              "ko"
            ],
            "properties": {
              "en": {
                "type": "string"
              },
              "ko": {
                "type": "string"
              }
            }
          },
          "explanation": {
            "type": "object",
            "required": [
              "en",
              "ko"
            ],
            "properties": {
              "en": {
                "type": "string"
              },
              "ko": {
                "type": "string"
              }
            }
          }
        },
        "additionalProperties": true
      },
      "RegistryVerificationResult": {
        "type": "object",
        "required": [
          "schema_version",
          "official_record",
          "identity_match",
          "editorial",
          "records",
          "limitations",
          "relay_rules"
        ],
        "properties": {
          "schema_version": {
            "type": "string"
          },
          "generated_at": {
            "type": "string",
            "format": "date-time"
          },
          "official_record": {
            "$ref": "#/components/schemas/VerificationAxis"
          },
          "identity_match": {
            "$ref": "#/components/schemas/VerificationAxis"
          },
          "editorial": {
            "$ref": "#/components/schemas/VerificationAxis"
          },
          "records": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "limitations": {
            "type": "object",
            "required": [
              "en",
              "ko"
            ],
            "properties": {
              "en": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "ko": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "relay_rules": {
            "type": "object",
            "description": "Machine-readable constraints that must travel with an agent's summary of the result.",
            "additionalProperties": true
          },
          "resolution_guidance": {
            "type": "object",
            "description": "Additional evidence required before resolving ambiguous or unsupported identifiers.",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "RegistryStatus": {
        "type": "object",
        "required": [
          "schema_version",
          "source",
          "coverage"
        ],
        "properties": {
          "schema_version": {
            "type": "string"
          },
          "source": {
            "type": "object",
            "additionalProperties": true
          },
          "coverage": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "PropertyCatalog": {
        "type": "object",
        "required": [
          "schema_version",
          "property_count",
          "properties"
        ],
        "properties": {
          "schema_version": {
            "type": "string"
          },
          "updated": {
            "type": "string",
            "format": "date"
          },
          "property_count": {
            "type": "integer",
            "minimum": 0
          },
          "content_policy": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "properties": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Property"
            }
          }
        },
        "additionalProperties": true
      },
      "FilteredPropertyCatalog": {
        "type": "object",
        "required": [
          "filter",
          "property_count",
          "properties"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "updated": {
            "type": "string",
            "format": "date"
          },
          "source": {
            "type": "string"
          },
          "filter": {
            "type": "object",
            "additionalProperties": true
          },
          "property_count": {
            "type": "integer",
            "minimum": 0
          },
          "properties": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Property"
            }
          }
        },
        "additionalProperties": true
      },
      "Property": {
        "type": "object",
        "required": [
          "slug",
          "name",
          "location"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "country_iso": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2
          },
          "location": {
            "type": "string"
          },
          "neighborhood": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "has_page": {
            "type": "boolean"
          },
          "booking_links": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "platform": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "tracked_url": {
                  "type": "string"
                }
              },
              "additionalProperties": true
            }
          },
          "source_citations": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object",
              "properties": {
                "platform": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "fetched_at": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "additionalProperties": true
            }
          },
          "data_completeness": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      }
    }
  }
}
