{"openapi":"3.1.1","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"Stay Portland Public API","version":"1.0.0","description":"Search Stay Portland public rentals and obtain temporary quotes. No API key is required. These bounded endpoints create no reservation and collect no payment; give the checkout URL to the guest. Dates use America/Los_Angeles and stays must be 1 to 30 nights. Other website account, payment and administrative routes are not part of this public API.","contact":{"name":"Stay Portland","url":"https://www.stayportland.com/contact"}},"servers":[{"url":"https://www.stayportland.com","description":"Stay Portland production website"}],"security":[],"externalDocs":{"description":"Stay Portland developer documentation and sandbox","url":"https://www.stayportland.com/developers"},"tags":[{"name":"Public rental tools","description":"Public inventory search and temporary booking quotes."}],"paths":{"/api/site-tools/search":{"post":{"operationId":"searchStayPortlandRentals","summary":"Search Stay Portland rentals","description":"Search public rentals with optional dates, occupancy and feature criteria. Undated results are a catalog browse; dated results check availability. Prices are indicative until quoted. Follow nextOffset for pagination. This endpoint supports one date pair; flexible date windows are available through MCP.","tags":["Public rental tools"],"security":[],"requestBody":{"required":true,"description":"JSON object, at most 16384 bytes. No API key or account is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchRequest"},"example":{"guests":2,"limit":8}}}},"responses":{"200":{"description":"Successful result. Responses are private and must not be cached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"Malformed JSON, invalid or unknown input fields, invalid dates, or a safe public validation failure. Correct the request using code, hint and issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"The endpoint accepts POST, with OPTIONS for method discovery.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Allow":{"description":"Supported methods for this endpoint.","schema":{"type":"string","const":"POST, OPTIONS"}}}},"413":{"description":"Request body exceeds 16384 bytes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-IP or deployment-wide rate limit exceeded, or the fail-closed limiter cannot confirm capacity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Number of seconds to wait before retrying.","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining requests in the rate-limit bucket that rejected this request.","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Reset time for that bucket, in milliseconds since the Unix epoch.","schema":{"type":"integer"}}}},"502":{"description":"The upstream search or quote service is temporarily unavailable. Private provider details are not returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rate-limit":{"windowSeconds":600,"requestsPerIp":6,"requestsPerDeployment":120}}},"/api/site-tools/priced-availability":{"post":{"operationId":"searchStayPortlandPricedAvailability","summary":"Search rentals with current all-in quotes","description":"Search one date pair and obtain temporary all-in quotes for up to six results per page. Results without a confirmed current quote are omitted and counted in unpricedCount. Quotes create no reservation. Supply current or future dates in place of the illustrative example dates.","tags":["Public rental tools"],"security":[],"requestBody":{"required":true,"description":"JSON object, at most 16384 bytes. No API key or account is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricedAvailabilityRequest"},"example":{"checkin":"2027-06-18","checkout":"2027-06-21","guests":2,"limit":6}}}},"responses":{"200":{"description":"Successful result. Responses are private and must not be cached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricedAvailabilityResponse"}}}},"400":{"description":"Malformed JSON, invalid or unknown input fields, invalid dates, or a safe public validation failure. Correct the request using code, hint and issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"The endpoint accepts POST, with OPTIONS for method discovery.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Allow":{"description":"Supported methods for this endpoint.","schema":{"type":"string","const":"POST, OPTIONS"}}}},"413":{"description":"Request body exceeds 16384 bytes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-IP or deployment-wide rate limit exceeded, or the fail-closed limiter cannot confirm capacity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Number of seconds to wait before retrying.","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining requests in the rate-limit bucket that rejected this request.","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Reset time for that bucket, in milliseconds since the Unix epoch.","schema":{"type":"integer"}}}},"502":{"description":"The upstream search or quote service is temporarily unavailable. Private provider details are not returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rate-limit":{"windowSeconds":600,"requestsPerIp":3,"requestsPerDeployment":20}}},"/api/site-tools/quote":{"post":{"operationId":"quoteStayPortlandRental","summary":"Get a temporary quote for a rental","description":"Get a current all-in quote and guest checkout URL for one listing. Use a slug from search and current or future dates in place of the illustrative example values. Quotes are temporary, create no reservation and do not collect payment. A fresh quote is required if the checkout link expires.","tags":["Public rental tools"],"security":[],"requestBody":{"required":true,"description":"JSON object, at most 16384 bytes. No API key or account is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequest"},"example":{"listing":"replace-with-slug-from-search","checkin":"2027-06-18","checkout":"2027-06-21","guests":2}}}},"responses":{"200":{"description":"Temporary all-in quote and a checkout URL for the guest.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"400":{"description":"Malformed JSON, invalid or unknown input fields, invalid dates, or a safe public validation failure. Correct the request using code, hint and issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"The endpoint accepts POST, with OPTIONS for method discovery.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Allow":{"description":"Supported methods for this endpoint.","schema":{"type":"string","const":"POST, OPTIONS"}}}},"409":{"description":"The requested dates are no longer available. Search again before requesting a new quote.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body exceeds 16384 bytes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-IP or deployment-wide rate limit exceeded, or the fail-closed limiter cannot confirm capacity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Number of seconds to wait before retrying.","schema":{"type":"integer","minimum":1}},"X-RateLimit-Remaining":{"description":"Remaining requests in the rate-limit bucket that rejected this request.","schema":{"type":"integer","minimum":0}},"X-RateLimit-Reset":{"description":"Reset time for that bucket, in milliseconds since the Unix epoch.","schema":{"type":"integer"}}}},"502":{"description":"The upstream search or quote service is temporarily unavailable. Private provider details are not returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rate-limit":{"windowSeconds":600,"requestsPerIp":12,"requestsPerDeployment":120}}}},"components":{"schemas":{"SearchRequest":{"type":"object","properties":{"checkin":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Arrival date (YYYY-MM-DD), today or later in America/Los_Angeles. Provide checkout together with checkin.","format":"date"},"checkout":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Departure date (YYYY-MM-DD), after checkin, for a stay of 1 to 30 nights.","format":"date"},"guests":{"type":"integer","minimum":1,"maximum":16,"description":"Total number of guests, including children."},"bedrooms":{"type":"integer","minimum":0,"maximum":8,"description":"Minimum bedrooms; 0 includes studios."},"bathrooms":{"type":"integer","minimum":0,"maximum":12,"description":"Minimum bathrooms."},"beds":{"type":"integer","minimum":0,"maximum":24,"description":"Minimum beds."},"pets":{"type":"boolean","description":"Filter for pet-friendly homes when true."},"neighborhood":{"type":"string","maxLength":200,"description":"Portland neighborhood filter."},"q":{"description":"Public feature, neighborhood, or listing-copy criteria.","type":"string","maxLength":200},"maxNightly":{"type":"number","exclusiveMinimum":0,"maximum":10000,"description":"Maximum indicative nightly price in USD; use a live quote for the all-in stay total."},"sort":{"type":"string","enum":["recommended","price_low","price_high","rating","capacity_fit"],"description":"Result ordering. Defaults to recommended. Priced search sorts the current page by exact total for price_low or price_high.","default":"recommended"},"offset":{"type":"integer","minimum":0,"maximum":300,"description":"Pagination offset; use nextOffset from the previous response.","default":0},"limit":{"type":"integer","minimum":1,"maximum":20,"description":"Maximum results on the current page.","default":8}},"additionalProperties":false,"description":"Search public rentals with an optional date pair. Unknown fields are rejected. Date pairs are checked at runtime against the current Portland date and the 30-night maximum.","dependentRequired":{"checkin":["checkout"],"checkout":["checkin"]}},"PricedAvailabilityRequest":{"type":"object","properties":{"checkin":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Arrival date (YYYY-MM-DD), today or later in America/Los_Angeles. Provide checkout together with checkin.","format":"date"},"checkout":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Departure date (YYYY-MM-DD), after checkin, for a stay of 1 to 30 nights.","format":"date"},"guests":{"type":"integer","minimum":1,"maximum":16,"description":"Total number of guests, including children.","default":2},"bedrooms":{"type":"integer","minimum":0,"maximum":8,"description":"Minimum bedrooms; 0 includes studios."},"bathrooms":{"type":"integer","minimum":0,"maximum":12,"description":"Minimum bathrooms."},"beds":{"type":"integer","minimum":0,"maximum":24,"description":"Minimum beds."},"pets":{"type":"boolean","description":"Filter for pet-friendly homes when true."},"neighborhood":{"type":"string","maxLength":200,"description":"Portland neighborhood filter."},"q":{"description":"Public feature, neighborhood, or listing-copy criteria.","type":"string","maxLength":200},"maxNightly":{"type":"number","exclusiveMinimum":0,"maximum":10000,"description":"Maximum indicative nightly price in USD; use a live quote for the all-in stay total."},"propertyTypes":{"maxItems":7,"type":"array","items":{"type":"string","enum":["apartment","house","condominium","townhouse","loft","bungalow","cabin"]},"description":"Allowed property types to include in results."},"amenities":{"maxItems":12,"type":"array","items":{"type":"string","enum":["hot_tub","fireplace","backyard","workspace","wifi","air_conditioning","washer","dryer","kitchen","crib","high_chair","elevator","parking"]},"description":"Public amenities required in matching listings."},"personas":{"maxItems":5,"type":"array","items":{"type":"string","enum":["family","groups","luxury","budget","extended_stay","remote_work","romantic"]},"description":"Traveler needs to match against public listing evidence."},"sort":{"type":"string","enum":["recommended","price_low","price_high","rating","capacity_fit"],"description":"Result ordering. Defaults to recommended. Priced search sorts the current page by exact total for price_low or price_high.","default":"recommended"},"offset":{"type":"integer","minimum":0,"maximum":300,"description":"Pagination offset; use nextOffset from the previous response.","default":0},"limit":{"type":"integer","minimum":1,"maximum":6,"description":"Maximum results on the current page.","default":6}},"required":["checkin","checkout"],"additionalProperties":false,"description":"Search one required date pair and request temporary all-in quotes for up to six results. Unknown fields are rejected."},"QuoteRequest":{"type":"object","properties":{"listing":{"type":"string","maxLength":200,"description":"The 24-character hexadecimal Guesty listing ID or property slug returned by a search."},"checkin":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Arrival date (YYYY-MM-DD), today or later in America/Los_Angeles. Provide checkout together with checkin.","format":"date"},"checkout":{"type":"string","maxLength":10,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Departure date (YYYY-MM-DD), after checkin, for a stay of 1 to 30 nights.","format":"date"},"guests":{"type":"integer","minimum":1,"maximum":16,"description":"Total number of guests, including children.","default":2}},"required":["listing","checkin","checkout"],"additionalProperties":false,"description":"Create a temporary quote for one public listing and date pair. This creates no reservation and collects no payment. Unknown fields are rejected."},"SearchResponse":{"type":"object","properties":{"properties":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"title":{"type":"string"},"sleeps":{"anyOf":[{"type":"number"},{"type":"null"}]},"bedrooms":{"anyOf":[{"type":"number"},{"type":"null"}]},"bathrooms":{"anyOf":[{"type":"number"},{"type":"null"}]},"beds":{"anyOf":[{"type":"number"},{"type":"null"}]},"propertyType":{"anyOf":[{"type":"string"},{"type":"null"}]},"neighborhood":{"anyOf":[{"type":"string"},{"type":"null"}]},"petsAllowed":{"type":"boolean"},"rating":{"anyOf":[{"type":"number"},{"type":"null"}]},"reviewCount":{"anyOf":[{"type":"number"},{"type":"null"}]},"fromNightly":{"anyOf":[{"type":"number"},{"type":"null"}]},"stayTotal":{"anyOf":[{"type":"number"},{"type":"null"}]},"currency":{"type":"string","const":"USD"},"image":{"anyOf":[{"type":"string"},{"type":"null"}]},"photos":{"maxItems":6,"type":"array","items":{"type":"string"}},"availableCheckin":{"type":"string"},"availableCheckout":{"type":"string"},"matchScore":{"type":"number"},"matchReasons":{"maxItems":6,"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["amenity","persona","query"]},"label":{"type":"string"},"evidence":{"type":"string"}},"required":["kind","label","evidence"],"additionalProperties":false}},"bookUrl":{"type":"string"},"markdownUrl":{"type":"string"}},"required":["slug","title","sleeps","bedrooms","bathrooms","neighborhood","petsAllowed","fromNightly","stayTotal","currency","image","bookUrl","markdownUrl"],"additionalProperties":false},"maxItems":20},"count":{"type":"number"},"availableCount":{"type":"number"},"hasMore":{"type":"boolean"},"nextOffset":{"anyOf":[{"type":"number"},{"type":"null"}]},"dated":{"type":"boolean"},"checkin":{"type":"string"},"checkout":{"type":"string"},"guests":{"type":"number"},"note":{"type":"string"}},"required":["properties","count","hasMore","nextOffset","dated","note"],"additionalProperties":false,"description":"Current search page. Search prices are indicative; request a quote for a confirmed all-in total. Undated search does not confirm availability."},"PricedAvailabilityResponse":{"type":"object","properties":{"properties":{"maxItems":6,"type":"array","items":{"type":"object","properties":{"property":{"type":"object","properties":{"slug":{"type":"string"},"title":{"type":"string"},"sleeps":{"anyOf":[{"type":"number"},{"type":"null"}]},"bedrooms":{"anyOf":[{"type":"number"},{"type":"null"}]},"bathrooms":{"anyOf":[{"type":"number"},{"type":"null"}]},"beds":{"anyOf":[{"type":"number"},{"type":"null"}]},"propertyType":{"anyOf":[{"type":"string"},{"type":"null"}]},"neighborhood":{"anyOf":[{"type":"string"},{"type":"null"}]},"petsAllowed":{"type":"boolean"},"rating":{"anyOf":[{"type":"number"},{"type":"null"}]},"reviewCount":{"anyOf":[{"type":"number"},{"type":"null"}]},"fromNightly":{"anyOf":[{"type":"number"},{"type":"null"}]},"stayTotal":{"anyOf":[{"type":"number"},{"type":"null"}]},"currency":{"type":"string","const":"USD"},"image":{"anyOf":[{"type":"string"},{"type":"null"}]},"photos":{"maxItems":6,"type":"array","items":{"type":"string"}},"availableCheckin":{"type":"string"},"availableCheckout":{"type":"string"},"matchScore":{"type":"number"},"matchReasons":{"maxItems":6,"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["amenity","persona","query"]},"label":{"type":"string"},"evidence":{"type":"string"}},"required":["kind","label","evidence"],"additionalProperties":false}},"bookUrl":{"type":"string"},"markdownUrl":{"type":"string"}},"required":["slug","title","sleeps","bedrooms","bathrooms","neighborhood","petsAllowed","fromNightly","stayTotal","currency","image","bookUrl","markdownUrl"],"additionalProperties":false},"quote":{"type":"object","properties":{"quoteId":{"type":"string"},"listingTitle":{"anyOf":[{"type":"string"},{"type":"null"}]},"checkin":{"type":"string"},"checkout":{"type":"string"},"guests":{"type":"number"},"nights":{"type":"number"},"accommodation":{"type":"number"},"cleaning":{"type":"number"},"taxes":{"type":"number"},"total":{"type":"number"},"currency":{"type":"string","const":"USD"},"checkoutUrl":{"type":"string"},"expiresNote":{"type":"string"},"note":{"type":"string"}},"required":["quoteId","listingTitle","checkin","checkout","guests","nights","accommodation","cleaning","taxes","total","currency","checkoutUrl","expiresNote","note"],"additionalProperties":false}},"required":["property","quote"],"additionalProperties":false}},"count":{"type":"number"},"availableCount":{"type":"number"},"unpricedCount":{"type":"number"},"hasMore":{"type":"boolean"},"nextOffset":{"anyOf":[{"type":"number"},{"type":"null"}]},"checkin":{"type":"string"},"checkout":{"type":"string"},"guests":{"type":"number"},"pagePriceRange":{"anyOf":[{"type":"object","properties":{"minTotal":{"type":"number"},"maxTotal":{"type":"number"},"currency":{"type":"string","const":"USD"}},"required":["minTotal","maxTotal","currency"],"additionalProperties":false},{"type":"null"}]},"note":{"type":"string"}},"required":["properties","count","availableCount","unpricedCount","hasMore","nextOffset","checkin","checkout","guests","pagePriceRange","note"],"additionalProperties":false,"description":"Only properties with confirmed temporary quotes are returned. unpricedCount records candidates omitted when a current quote could not be confirmed; nextOffset continues through inventory."},"QuoteResponse":{"type":"object","properties":{"quoteId":{"type":"string"},"listingTitle":{"anyOf":[{"type":"string"},{"type":"null"}]},"checkin":{"type":"string"},"checkout":{"type":"string"},"guests":{"type":"number"},"nights":{"type":"number"},"accommodation":{"type":"number"},"cleaning":{"type":"number"},"taxes":{"type":"number"},"total":{"type":"number"},"currency":{"type":"string","const":"USD"},"checkoutUrl":{"type":"string"},"expiresNote":{"type":"string"},"note":{"type":"string"}},"required":["quoteId","listingTitle","checkin","checkout","guests","nights","accommodation","cleaning","taxes","total","currency","checkoutUrl","expiresNote","note"],"additionalProperties":false,"description":"Temporary quote in whole USD. Accommodation, cleaning, taxes and total are rounded display amounts. The checkout URL hands payment to the guest; the API does not book or charge."},"Error":{"type":"object","properties":{"error":{"type":"string","description":"Legacy message string retained for browser clients."},"code":{"type":"string","enum":["INVALID_JSON","INVALID_PARAMETERS","REQUEST_TOO_LARGE","RATE_LIMITED","NOT_FOUND","METHOD_NOT_ALLOWED","AVAILABILITY_CHANGED","UPSTREAM_UNAVAILABLE"],"description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation of the failure."},"hint":{"type":"string","description":"Suggested recovery step."},"documentation":{"type":"string","format":"uri","description":"Public API documentation URL."},"issues":{"description":"Field-level input validation issues, when available.","type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"],"additionalProperties":false}}},"required":["error","code","message","hint","documentation"],"additionalProperties":false}}}}