"""Create a pending property and physical unit; standard library only.""" import json import os import uuid from urllib.error import HTTPError from urllib.parse import urlencode from urllib.request import Request, urlopen required = ("OUTRESERVE_SUPPLY_BASE_URL", "OUTRESERVE_SUPPLY_API_KEY", "OUTRESERVE_EXTERNAL_PROPERTY_ID", "OUTRESERVE_COUNTRY_CODE", "OUTRESERVE_STATE_CODE", "OUTRESERVE_DESTINATION_SLUG", "OUTRESERVE_PROPERTY_TIMEZONE") missing = [name for name in required if not os.environ.get(name)] if missing: raise SystemExit(f"Set these variables: {', '.join(missing)}") if os.environ.get("OUTRESERVE_CONFIRM_CREATE") != "yes": raise SystemExit("Set OUTRESERVE_CONFIRM_CREATE=yes to create a pending property and unit") base = os.environ["OUTRESERVE_SUPPLY_BASE_URL"].rstrip("/") keys = { "property": os.environ.get("OUTRESERVE_PROPERTY_IDEMPOTENCY_KEY") or str(uuid.uuid4()), "unit": os.environ.get("OUTRESERVE_UNIT_IDEMPOTENCY_KEY") or str(uuid.uuid4()), "submit": os.environ.get("OUTRESERVE_SUBMIT_IDEMPOTENCY_KEY") or str(uuid.uuid4()), } print("Persist these keys before any retry:", keys) def request(path, method="GET", body=None, idempotency_key=None): """Send an authenticated Supply request and expose structured failures.""" data = json.dumps(body).encode() if body is not None else None headers = {"Authorization": f'Bearer {os.environ["OUTRESERVE_SUPPLY_API_KEY"]}'} if data is not None: headers["Content-Type"] = "application/json" if idempotency_key: headers["Idempotency-Key"] = idempotency_key operation = Request(f"{base}{path}", data=data, headers=headers, method=method) try: with urlopen(operation, timeout=30) as response: return json.load(response) except HTTPError as error: raw = error.read().decode("utf-8", errors="replace") try: detail = json.loads(raw) except json.JSONDecodeError: detail = raw raise SystemExit(f"Supply API {error.code}: {detail}") from error connection = request("/connection") print("Connection:", json.dumps(connection["data"]["capabilities"], indent=2)) location_query = urlencode({ "level": "destinations", "country_code": os.environ["OUTRESERVE_COUNTRY_CODE"], "state_code": os.environ["OUTRESERVE_STATE_CODE"], "destination_slug": os.environ["OUTRESERVE_DESTINATION_SLUG"], }) location = request(f"/locations?{location_query}") if len(location["data"]) != 1: raise SystemExit("Expected exactly one matching destination; inspect GET /locations") print("Selected location:", location["data"][0]["id"]) property_result = request("/properties", "POST", {"property": { "external_property_id": os.environ["OUTRESERVE_EXTERNAL_PROPERTY_ID"], "name": "Example Cabin Property", "currency": "USD", "country_code": os.environ["OUTRESERVE_COUNTRY_CODE"], "state_code": os.environ["OUTRESERVE_STATE_CODE"], "destination_slug": os.environ["OUTRESERVE_DESTINATION_SLUG"], "timezone": os.environ["OUTRESERVE_PROPERTY_TIMEZONE"], }}, keys["property"]) property_id = property_result["data"]["id"] print("Pending property:", property_id) unit_result = request(f"/properties/{property_id}/units", "POST", {"unit": { "external_unit_id": os.environ.get("OUTRESERVE_EXTERNAL_UNIT_ID", "sample-cabin-1"), "name": "Cabin 1", "unit_type": "Cabin", "inventory_mode": "physical", "capacity": 1, }}, keys["unit"]) print("Unit:", unit_result["data"]["id"]) submitted = request(f"/properties/{property_id}/submit", "POST", idempotency_key=keys["submit"]) print("Submitted:", {key: submitted["data"][key] for key in ("id", "approval_status", "booking_ready")})