{
  "openapi": "3.0.0",
  "info": {
    "title": "Spacio Real Estate API",
    "description": "Complete API documentation for Spacio real estate platform. Manage properties, leads, brokerages, and teams.",
    "version": "2.0.0",
    "contact": {
      "name": "Spacio Support",
      "url": "https://spac.io"
    },
    "license": {
      "name": "API License",
      "url": "https://spac.io/terms"
    }
  },
  "servers": [
    {
      "url": "https://ws.spac.io/api/v1",
      "description": "Production API v1",
      "variables": {}
    },
    {
      "url": "https://ws.spac.io/api/v2",
      "description": "Production API v2 (Limited availability)"
    }
  ],
  "paths": {
    "/getProperties": {
      "post": {
        "tags": ["Properties"],
        "summary": "Get Agent Properties",
        "description": "Retrieve a list of properties associated with an agent. Returns paginated results of all properties the agent manages.",
        "operationId": "getProperties",
        "parameters": [
          {
            "name": "apikey",
            "in": "header",
            "description": "API key for authentication",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Request parameters for retrieving agent properties",
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "agent_key": {
                    "type": "string",
                    "description": "Unique identifier for the agent"
                  },
                  "page": {
                    "type": "integer",
                    "description": "Page number for pagination (default: 1)"
                  },
                  "limit": {
                    "type": "integer",
                    "description": "Number of results per page (default: 50, max: 100)"
                  }
                },
                "required": ["agent_key"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response with agent properties",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PropertiesResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "success": true,
                      "data": [
                        {
                          "property_id": "12345",
                          "address": "123 Main St",
                          "city": "Los Angeles",
                          "state": "CA",
                          "zip": "90001",
                          "price": 750000,
                          "bedrooms": 3,
                          "bathrooms": 2,
                          "sqft": 2500,
                          "status": "active",
                          "list_date": "2024-01-15",
                          "mls_id": "ABC123456"
                        }
                      ],
                      "pagination": {
                        "current_page": 1,
                        "total_pages": 5,
                        "total_results": 234
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "x-code-samples": [
          {
            "lang": "curl",
            "source": "curl -X POST 'https://ws.spac.io/api/v1/getProperties' \\\n  -H 'apikey: your-api-key' \\\n  -d 'agent_key=agent_12345&page=1&limit=50'"
          },
          {
            "lang": "python",
            "source": "import requests\n\nheaders = {'apikey': 'your-api-key'}\ndata = {'agent_key': 'agent_12345', 'page': 1, 'limit': 50}\nresponse = requests.post('https://ws.spac.io/api/v1/getProperties', headers=headers, data=data)\nproperties = response.json()"
          },
          {
            "lang": "javascript",
            "source": "const formData = new FormData();\nformData.append('agent_key', 'agent_12345');\nformData.append('page', '1');\nformData.append('limit', '50');\n\nfetch('https://ws.spac.io/api/v1/getProperties', {\n  method: 'POST',\n  headers: {'apikey': 'your-api-key'},\n  body: formData\n}).then(r => r.json()).then(console.log)"
          }
        ]
      }
    },
    "/getProperty": {
      "post": {
        "tags": ["Properties"],
        "summary": "Get Single Property Details",
        "description": "Retrieve detailed information about a specific property by ID.",
        "operationId": "getProperty",
        "parameters": [
          {
            "name": "apikey",
            "in": "header",
            "description": "API key for authentication",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Property identifier",
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "property_id": {
                    "type": "string",
                    "description": "Unique identifier for the property"
                  }
                },
                "required": ["property_id"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response with property details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PropertyDetailResponse"
                }
              }
            }
          },
          "404": {
            "description": "Property not found"
          },
          "401": {
            "description": "Unauthorized"
          }
        },
        "x-code-samples": [
          {
            "lang": "curl",
            "source": "curl -X POST 'https://ws.spac.io/api/v1/getProperty' \\\n  -H 'apikey: your-api-key' \\\n  -d 'property_id=12345'"
          },
          {
            "lang": "python",
            "source": "import requests\n\nheaders = {'apikey': 'your-api-key'}\ndata = {'property_id': '12345'}\nresponse = requests.post('https://ws.spac.io/api/v1/getProperty', headers=headers, data=data)\nproperty_detail = response.json()"
          }
        ]
      }
    },
    "/getOHSessions": {
      "post": {
        "tags": ["Properties"],
        "summary": "Get Open House Sessions",
        "description": "Retrieve open house sessions for properties.",
        "operationId": "getOHSessions",
        "parameters": [
          {
            "name": "apikey",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "agent_key": {
                    "type": "string"
                  },
                  "property_id": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string",
                    "enum": ["scheduled", "completed", "cancelled"],
                    "description": "Filter by session status"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OHSessionsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/getRegistrants": {
      "post": {
        "tags": ["Leads"],
        "summary": "Get Property Leads",
        "description": "Retrieve lead registrants for a specific property.",
        "operationId": "getRegistrants",
        "parameters": [
          {
            "name": "apikey",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "property_id": {
                    "type": "string",
                    "description": "Property identifier"
                  },
                  "page": {
                    "type": "integer"
                  },
                  "limit": {
                    "type": "integer"
                  }
                },
                "required": ["property_id"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegistrantsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/getAccessToken": {
      "post": {
        "tags": ["Authentication"],
        "summary": "Get Agent Access Token",
        "description": "Obtain a session access token for an agent.",
        "operationId": "getAccessToken",
        "parameters": [
          {
            "name": "apikey",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "agent_id": {
                    "type": "string"
                  }
                },
                "required": ["agent_id"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Access token generated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccessTokenResponse"
                }
              }
            }
          }
        }
      }
    },
    "/getAccessTokenBM": {
      "post": {
        "tags": ["Authentication"],
        "summary": "Get Brokerage Manager Access Token",
        "description": "Obtain a session access token for a brokerage manager.",
        "operationId": "getAccessTokenBM",
        "parameters": [
          {
            "name": "apikey",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "manager_id": {
                    "type": "string"
                  }
                },
                "required": ["manager_id"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Access token generated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccessTokenResponse"
                }
              }
            }
          }
        }
      }
    },
    "/getRegistrantsByBrokerage": {
      "post": {
        "tags": ["Brokerages"],
        "summary": "Get Registrants by Brokerage",
        "description": "Retrieve all registrants associated with a brokerage. Available in v1 and v2.",
        "operationId": "getRegistrantsByBrokerage",
        "parameters": [
          {
            "name": "apikey",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "brokerage_id": {
                    "type": "string"
                  },
                  "page": {
                    "type": "integer"
                  },
                  "limit": {
                    "type": "integer"
                  }
                },
                "required": ["brokerage_id"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegistrantsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/getClaimedList": {
      "post": {
        "tags": ["Brokerages"],
        "summary": "Get Claimed Accounts List",
        "description": "Retrieve list of claimed accounts for a brokerage.",
        "operationId": "getClaimedList",
        "parameters": [
          {
            "name": "apikey",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "brokerage_id": {
                    "type": "string"
                  }
                },
                "required": ["brokerage_id"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimedListResponse"
                }
              }
            }
          }
        }
      }
    },
    "/getActivityList": {
      "post": {
        "tags": ["Brokerages"],
        "summary": "Get User Activity List",
        "description": "Retrieve user activity logs for brokerage monitoring.",
        "operationId": "getActivityList",
        "parameters": [
          {
            "name": "apikey",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "brokerage_id": {
                    "type": "string"
                  },
                  "start_date": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "end_date": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "required": ["brokerage_id"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActivityListResponse"
                }
              }
            }
          }
        }
      }
    },
    "/getOHSessionCounts": {
      "post": {
        "tags": ["Brokerages"],
        "summary": "Get Open House Session Counts",
        "description": "Retrieve open house session statistics for a brokerage.",
        "operationId": "getOHSessionCounts",
        "parameters": [
          {
            "name": "apikey",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "brokerage_id": {
                    "type": "string"
                  }
                },
                "required": ["brokerage_id"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OHSessionCountsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/getRegistrantsByTeam": {
      "post": {
        "tags": ["Teams"],
        "summary": "Get Team Leads",
        "description": "Retrieve all lead registrants associated with a team.",
        "operationId": "getRegistrantsByTeam",
        "parameters": [
          {
            "name": "apikey",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "team_id": {
                    "type": "string"
                  },
                  "page": {
                    "type": "integer"
                  },
                  "limit": {
                    "type": "integer"
                  }
                },
                "required": ["team_id"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegistrantsResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Property": {
        "type": "object",
        "description": "Real estate property information",
        "properties": {
          "property_id": {
            "type": "string",
            "description": "Unique property identifier"
          },
          "address": {
            "type": "string",
            "description": "Street address"
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "description": "Two-letter state code"
          },
          "zip": {
            "type": "string"
          },
          "price": {
            "type": "number",
            "format": "double",
            "description": "List price in USD"
          },
          "bedrooms": {
            "type": "integer"
          },
          "bathrooms": {
            "type": "number",
            "description": "Full and half bathrooms"
          },
          "sqft": {
            "type": "integer",
            "description": "Square footage"
          },
          "status": {
            "type": "string",
            "enum": ["active", "pending", "sold", "expired", "withdrawn"],
            "description": "Current listing status"
          },
          "list_date": {
            "type": "string",
            "format": "date",
            "description": "Date property was listed"
          },
          "mls_id": {
            "type": "string",
            "description": "MLS number"
          },
          "property_type": {
            "type": "string",
            "enum": ["single_family", "condo", "townhouse", "multi_unit", "land", "commercial"],
            "description": "Type of property"
          },
          "lot_size": {
            "type": "string",
            "description": "Lot size (e.g., 0.25 acres)"
          },
          "year_built": {
            "type": "integer"
          }
        }
      },
      "Registrant": {
        "type": "object",
        "description": "Lead registrant information",
        "properties": {
          "registrant_id": {
            "type": "string"
          },
          "first_name": {
            "type": "string"
          },
          "last_name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "phone": {
            "type": "string"
          },
          "registration_date": {
            "type": "string",
            "format": "date-time",
            "description": "When lead was captured"
          },
          "property_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": ["new", "contacted", "qualified", "converted", "closed"],
            "description": "Lead status in sales pipeline"
          },
          "lead_source": {
            "type": "string",
            "enum": ["open_house", "website", "search", "inquiry"],
            "description": "How lead was captured"
          },
          "answers": {
            "type": "array",
            "description": "Custom form answers provided by lead",
            "items": {
              "type": "object",
              "properties": {
                "question": {
                  "type": "string"
                },
                "answer": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "PropertiesResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Property"
            }
          },
          "pagination": {
            "type": "object",
            "properties": {
              "current_page": {
                "type": "integer"
              },
              "total_pages": {
                "type": "integer"
              },
              "total_results": {
                "type": "integer"
              }
            }
          }
        }
      },
      "PropertyDetailResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "$ref": "#/components/schemas/Property"
          }
        }
      },
      "OHSessionsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "session_id": {
                  "type": "string"
                },
                "property_id": {
                  "type": "string"
                },
                "start_time": {
                  "type": "string",
                  "format": "date-time"
                },
                "end_time": {
                  "type": "string",
                  "format": "date-time"
                },
                "status": {
                  "type": "string",
                  "enum": ["scheduled", "completed", "cancelled"]
                },
                "attendees": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "RegistrantsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Registrant"
            }
          },
          "pagination": {
            "type": "object",
            "properties": {
              "current_page": {
                "type": "integer"
              },
              "total_pages": {
                "type": "integer"
              },
              "total_results": {
                "type": "integer"
              }
            }
          }
        }
      },
      "AccessTokenResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "token": {
            "type": "string",
            "description": "Session access token"
          },
          "expires_in": {
            "type": "integer",
            "description": "Token expiration in seconds"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ClaimedListResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "account_id": {
                  "type": "string"
                },
                "claimed_by": {
                  "type": "string"
                },
                "claimed_date": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          }
        }
      },
      "ActivityListResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "activity_id": {
                  "type": "string"
                },
                "user_id": {
                  "type": "string"
                },
                "action": {
                  "type": "string",
                  "description": "Type of action performed"
                },
                "timestamp": {
                  "type": "string",
                  "format": "date-time"
                },
                "details": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "OHSessionCountsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "total_sessions": {
                "type": "integer"
              },
              "scheduled": {
                "type": "integer"
              },
              "completed": {
                "type": "integer"
              },
              "cancelled": {
                "type": "integer"
              }
            }
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "example": false
          },
          "error": {
            "type": "string",
            "description": "Error code identifier"
          },
          "message": {
            "type": "string",
            "description": "Human-readable error message"
          }
        }
      }
    }
  },
  "x-topics": [
    {
      "id": "a-getting-started",
      "title": "Getting Started & Authentication",
      "description": "Quick start guide for integrating with the Spacio API",
      "category": "guides",
      "content": "## Getting Started\n\nThe Spacio API provides real estate data and lead management capabilities. To begin:\n\n### 1. Obtain API Key\nContact Spacio support to receive your API key. Each brokerage or agent account receives a unique key.\n\n### 2. Authentication\nAll requests require the API key in the header:\n```\nHeader: apikey: your-api-key\n```\n\n### 3. Base URL\nUse one of these base URLs:\n- v1: `https://ws.spac.io/api/v1/`\n- v2: `https://ws.spac.io/api/v2/`\n\n### 4. First Request\nTest authentication with:\n```bash\ncurl -X POST 'https://ws.spac.io/api/v1/getProperties' \\\n  -H 'apikey: your-api-key' \\\n  -d 'agent_key=your_agent_key'\n```\n\n### 5. Response Format\nAll responses are JSON:\n```json\n{\n  \"success\": true,\n  \"data\": [...],\n  \"pagination\": {...}\n}\n```"
    },
    {
      "id": "b-api-keys-security",
      "title": "API Keys & Security Best Practices",
      "description": "Secure your API key and implement security best practices",
      "category": "guides",
      "content": "## API Keys & Security\n\n### Protecting Your API Key\n1. **Never expose in client-side code** - Keep keys on your backend server\n2. **Use environment variables** - Store keys in .env files, never in source code\n3. **Rotate regularly** - Request new keys periodically from Spacio\n4. **Use separate keys** - Maintain different keys for dev, staging, and production\n5. **Monitor usage** - Track API usage to detect unauthorized access\n\n### Implementation Example\n```python\nimport os\nfrom dotenv import load_dotenv\n\nload_dotenv()\napi_key = os.getenv('SPACIO_API_KEY')\n\n# Use api_key in headers\nheaders = {'apikey': api_key}\n```\n\n### IP Whitelisting\nContact support to enable IP whitelisting for additional security.\n\n### Rate Limiting\nYour account has a 12,000 request/hour limit by default. Implement exponential backoff for retry logic.\n\n### Error Handling\nAlways check for 401 (Unauthorized) responses indicating compromised keys."
    },
    {
      "id": "c-rate-limiting",
      "title": "Rate Limiting & Throttling",
      "description": "Understand and handle rate limits effectively",
      "category": "guides",
      "content": "## Rate Limiting\n\n### Default Limits\n- 12,000 requests per hour (200 per minute average)\n- Calculated on a rolling window basis\n- Limits apply per API key\n\n### Rate Limit Headers\nEach response includes headers:\n```\nX-RateLimit-Limit: 12000\nX-RateLimit-Remaining: 11945\nX-RateLimit-Reset: 1695850800\n```\n\n### Handling Rate Limits\nWhen you receive a 429 (Too Many Requests) response:\n\n1. **Respect the reset time** - Wait until X-RateLimit-Reset\n2. **Implement exponential backoff**:\n```python\nimport time\n\ndef make_request_with_backoff(url, headers, data, max_retries=3):\n    for attempt in range(max_retries):\n        response = requests.post(url, headers=headers, data=data)\n        if response.status_code == 429:\n            wait_time = 2 ** attempt\n            time.sleep(wait_time)\n            continue\n        return response\n```\n\n### Optimization Strategies\n- **Batch requests** - Fetch multiple properties in one call\n- **Cache results** - Store data locally to reduce API calls\n- **Pagination** - Use limit and page parameters efficiently\n- **Schedule requests** - Distribute API calls throughout the hour"
    },
    {
      "id": "d-pagination-guide",
      "title": "Pagination Guide",
      "description": "Navigate large result sets with pagination",
      "category": "guides",
      "content": "## Pagination\n\n### Pagination Parameters\nMany endpoints support pagination:\n- `page` - Page number (default: 1)\n- `limit` - Results per page (default: 50, max: 100)\n\n### Example Request\n```bash\ncurl -X POST 'https://ws.spac.io/api/v1/getProperties' \\\n  -H 'apikey: your-api-key' \\\n  -d 'agent_key=agent_123&page=2&limit=50'\n```\n\n### Pagination Response\n```json\n{\n  \"success\": true,\n  \"data\": [...],\n  \"pagination\": {\n    \"current_page\": 2,\n    \"total_pages\": 5,\n    \"total_results\": 234\n  }\n}\n```\n\n### Iterating Through All Results\n```python\ndef get_all_properties(agent_key, api_key):\n    all_properties = []\n    page = 1\n    while True:\n        response = requests.post(\n            'https://ws.spac.io/api/v1/getProperties',\n            headers={'apikey': api_key},\n            data={'agent_key': agent_key, 'page': page, 'limit': 100}\n        ).json()\n        \n        all_properties.extend(response['data'])\n        \n        if page >= response['pagination']['total_pages']:\n            break\n        page += 1\n    \n    return all_properties\n```"
    },
    {
      "id": "e-date-time-handling",
      "title": "Date & Time Handling",
      "description": "Work with dates, times, and timezones in the API",
      "category": "guides",
      "content": "## Date & Time Handling\n\n### UTC Standard\nAll timestamps are in UTC (Coordinated Universal Time). Always convert to user's local timezone when displaying.\n\n### Supported Formats\n\n#### Date Format (date)\n- ISO 8601: YYYY-MM-DD\n- Example: 2024-01-15\n\n#### DateTime Format (date-time)\n- ISO 8601 with timezone: YYYY-MM-DDTHH:MM:SSZ\n- Example: 2024-01-15T14:30:00Z\n\n### Timezone Examples\n```python\nfrom datetime import datetime, timezone\nimport pytz\n\n# Parse UTC timestamp from API\nutc_time = datetime.fromisoformat('2024-01-15T14:30:00Z')\n\n# Convert to user timezone\npacific = pytz.timezone('US/Pacific')\nlocal_time = utc_time.astimezone(pacific)\nprint(local_time)  # 2024-01-15 06:30:00-08:00\n\n# Send date to API\ntoday = datetime.now(timezone.utc).date().isoformat()\ndata = {'start_date': today, ...}\n```\n\n### Open House DateTime Example\nOpen house sessions use full datetime:\n```json\n{\n  \"session_id\": \"oh_123\",\n  \"start_time\": \"2024-02-10T14:00:00Z\",\n  \"end_time\": \"2024-02-10T16:00:00Z\"\n}\n```"
    },
    {
      "id": "f-common-use-cases",
      "title": "Common Use Cases & Workflows",
      "description": "Real-world patterns and workflows for common tasks",
      "category": "guides",
      "content": "## Common Use Cases\n\n### 1. Lead Management Workflow\nRetrieve leads for a property and track status:\n```python\n# Get property leads\nregistrants = get_registrants(property_id='prop_123')\n\n# Process each lead\nfor lead in registrants:\n    if lead['status'] == 'new':\n        send_follow_up_email(lead['email'])\n        update_crm(lead['registrant_id'], status='contacted')\n```\n\n### 2. Brokerage Dashboard\nAggregate data for brokerage reporting:\n```python\n# Get all agent properties\nproperties = get_all_agent_properties(brokerage_id)\n\n# Calculate metrics\nactive_listings = len([p for p in properties if p['status'] == 'active'])\ntotal_value = sum(p['price'] for p in properties)\n\nmetrics = {\n    'active_listings': active_listings,\n    'total_inventory_value': total_value,\n    'average_price': total_value / len(properties)\n}\n```\n\n### 3. Open House Management\nSchedule and manage open house events:\n```python\n# Get scheduled open houses\nsessions = get_oh_sessions(agent_key=agent_id, status='scheduled')\n\n# Send reminders before session starts\nfor session in sessions:\n    if minutes_until(session['start_time']) <= 60:\n        send_reminder_notifications(session)\n```\n\n### 4. Integration with CRM\nSync Spacio leads to external CRM:\n```python\nregistrants = get_registrants(property_id='prop_123')\nfor registrant in registrants:\n    crm.add_contact({\n        'name': f\"{registrant['first_name']} {registrant['last_name']}\",\n        'email': registrant['email'],\n        'phone': registrant['phone'],\n        'source': 'spacio',\n        'property': registrant['property_id']\n    })\n```"
    },
    {
      "id": "g-integration-patterns",
      "title": "Integration Patterns & Examples",
      "description": "Best practices for integrating Spacio API with systems",
      "category": "guides",
      "content": "## Integration Patterns\n\n### 1. Webhook Simulation\nRegularly poll for changes:\n```python\nimport schedule\nimport time\n\ndef check_new_leads():\n    registrants = get_registrants(property_id='prop_123')\n    new_leads = filter(lambda r: r['status'] == 'new', registrants)\n    for lead in new_leads:\n        process_lead(lead)\n\nschedule.every(5).minutes.do(check_new_leads)\n```\n\n### 2. Caching Strategy\nReduce API calls with intelligent caching:\n```python\nimport redis\nfrom datetime import timedelta\n\ndef get_cached_property(property_id, ttl=3600):\n    cache_key = f\"property:{property_id}\"\n    cached = redis.get(cache_key)\n    \n    if cached:\n        return json.loads(cached)\n    \n    property_data = api.get_property(property_id)\n    redis.setex(cache_key, ttl, json.dumps(property_data))\n    return property_data\n```\n\n### 3. Batch Processing\nHandle multiple resources efficiently:\n```python\ndef process_brokerage_data(brokerage_id):\n    # Get all registrants\n    all_registrants = []\n    page = 1\n    while True:\n        response = get_registrants_by_brokerage(brokerage_id, page=page)\n        all_registrants.extend(response['data'])\n        if page >= response['pagination']['total_pages']:\n            break\n        page += 1\n    \n    # Process in batches\n    batch_size = 50\n    for i in range(0, len(all_registrants), batch_size):\n        batch = all_registrants[i:i+batch_size]\n        bulk_update_crm(batch)\n```\n\n### 4. Error Handling\nRobust error management:\n```python\ndef safe_api_call(endpoint, params, retries=3):\n    for attempt in range(retries):\n        try:\n            return make_api_request(endpoint, params)\n        except RateLimitError:\n            time.sleep(2 ** attempt)\n        except AuthError:\n            log_error('Invalid API key')\n            raise\n        except ServerError:\n            if attempt < retries - 1:\n                time.sleep(5)\n            else:\n                raise\n```"
    },
    {
      "id": "h-migration-guide",
      "title": "Migration Guide (v1 to v2)",
      "description": "Migrate your integration from API v1 to v2",
      "category": "guides",
      "content": "## Migration from v1 to v2\n\n### What Changed\nv2 introduces improved performance and new features.\n\n### Endpoint Changes\nMost endpoints remain compatible. Changes:\n- New fields in responses\n- Improved error messages\n- Better pagination support\n\n### URL Migration\n```python\n# v1\nurl = 'https://ws.spac.io/api/v1/getProperties'\n\n# v2\nurl = 'https://ws.spac.io/api/v2/getProperties'\n```\n\n### Response Format\nAll responses maintain compatibility:\n```json\n{\n  \"success\": true,\n  \"data\": [...],\n  \"pagination\": {...}\n}\n```\n\n### New Fields in v2\nSome responses include additional fields:\n- `updated_at` - Last modification timestamp\n- `source` - Data source identifier\n- `metadata` - Additional context\n\n### Migration Checklist\n- [ ] Update base URL in config\n- [ ] Test all endpoints in v2\n- [ ] Verify response parsing still works\n- [ ] Check rate limit handling\n- [ ] Monitor error responses\n- [ ] Update documentation\n- [ ] Plan rollout schedule\n\n### Backward Compatibility\nv1 will be maintained for 12 months. Use v2 for new projects.\n\n### Support\nContact Spacio support for migration questions."
    },
    {
      "id": "i-error-codes-reference",
      "title": "Error Codes Reference",
      "description": "Complete error code directory with solutions",
      "category": "reference",
      "content": "## Error Codes\n\n### access-denied (403)\n**Meaning:** Your API key lacks permissions for this operation.\n**Solution:** \n- Verify API key is correct\n- Check account permissions with Spacio\n- Ensure key has brokerage/agent role access\n\n### invalid-bid (400)\n**Meaning:** Brokerage ID is invalid or malformed.\n**Solution:**\n- Verify brokerage_id format\n- Check ID exists in Spacio system\n- Confirm you have access to brokerage\n\n### invalid-email (400)\n**Meaning:** Email format is invalid.\n**Solution:**\n- Follow RFC 5322 email format\n- Example valid: user@example.com\n\n### invalid-sid (400)\n**Meaning:** Session ID is invalid or expired.\n**Solution:**\n- Request new session token with getAccessToken\n- Check token hasn't expired\n\n### invalid-tid (400)\n**Meaning:** Team ID is invalid.\n**Solution:**\n- Verify team_id value\n- Confirm team exists\n- Check access permissions\n\n### invalid-ukey (400)\n**Meaning:** Unknown API key or user key format.\n**Solution:**\n- Double-check API key spelling\n- Request new key from Spacio if needed\n- Verify header is 'apikey' not 'api-key'\n\n### no-results (404)\n**Meaning:** Query returned no matching records.\n**Solution:**\n- Verify search parameters\n- Check property/lead ID exists\n- Try broader search criteria\n- Confirm data hasn't been deleted\n\n### not-authorized (401)\n**Meaning:** Authentication failed.\n**Solution:**\n- Verify API key in header\n- Check key hasn't been revoked\n- Ensure header name is exactly 'apikey'\n- Contact support if locked out\n\n### rate-reached (429)\n**Meaning:** Rate limit exceeded (12,000/hour).\n**Solution:**\n- Wait until hour window passes\n- Implement exponential backoff\n- Cache results to reduce calls\n- Contact Spacio for higher limits"
    },
    {
      "id": "j-field-definitions",
      "title": "Field Definitions & Data Types",
      "description": "Reference for all API field definitions and types",
      "category": "reference",
      "content": "## Field Definitions\n\n### Property Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| property_id | string | Unique property identifier |\n| address | string | Street address (max 255 chars) |\n| city | string | City name |\n| state | string | 2-letter state code (CA, NY, etc) |\n| zip | string | ZIP/postal code |\n| price | number | List price in USD |\n| bedrooms | integer | Number of bedrooms |\n| bathrooms | number | Full/half bathrooms (e.g., 3.5) |\n| sqft | integer | Square footage of living space |\n| status | string | active, pending, sold, expired, withdrawn |\n| list_date | date | YYYY-MM-DD format |\n| mls_id | string | MLS number |\n| property_type | string | See Property Types section |\n| lot_size | string | e.g., '0.25 acres' |\n| year_built | integer | Construction year |\n\n### Registrant Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| registrant_id | string | Unique lead identifier |\n| first_name | string | Lead first name |\n| last_name | string | Lead last name |\n| email | string | Email address (RFC 5322) |\n| phone | string | Phone number (various formats accepted) |\n| registration_date | date-time | When lead registered |\n| property_id | string | Associated property |\n| status | string | new, contacted, qualified, converted, closed |\n| lead_source | string | open_house, website, search, inquiry |\n| answers | array | Custom form responses |\n\n### Common Data Types\n\n**string:** Text data, variable length\n**integer:** Whole numbers (no decimals)\n**number:** Decimal numbers (e.g., bathrooms: 2.5)\n**boolean:** true or false\n**date:** YYYY-MM-DD format\n**date-time:** YYYY-MM-DDTHH:MM:SSZ (UTC)\n**array:** List of items [item1, item2]\n**object:** Named key-value pairs {key: value}"
    },
    {
      "id": "k-property-types-status",
      "title": "Property Types & Status Codes",
      "description": "Enumeration of property types and listing statuses",
      "category": "reference",
      "content": "## Property Types\n\n### Residential\n- **single_family** - Detached single-family home\n- **condo** - Condominium unit\n- **townhouse** - Townhouse or row house\n- **multi_unit** - Multi-family building (2-4 units)\n- **apartment** - Apartment complex (5+ units)\n\n### Non-Residential\n- **land** - Vacant land or lot\n- **commercial** - Commercial property\n- **industrial** - Industrial/warehouse\n- **retail** - Retail space\n- **office** - Office building\n\n## Listing Status Codes\n\n### Active Status\n- **active** - Actively listed on market\n- **coming_soon** - Pre-listing, not yet active\n\n### Contingent Status\n- **pending** - Offer accepted, conditions pending\n- **contingent** - Sale dependent on conditions\n\n### Inactive Status\n- **sold** - Sale closed\n- **expired** - Listing expired, no sale\n- **withdrawn** - Seller withdrew listing\n- **terminated** - Listing terminated by agreement\n\n### Status Transitions\n```\nactive → pending → sold (normal sale)\nactive → pending → withdrawn (buyer backed out)\nactive → expired (no offer in time period)\nactive → withdrawn (seller changed mind)\n```\n\n## Status Timestamps\n\nEach status change includes timestamp:\n```json\n{\n  \"property_id\": \"prop_123\",\n  \"status\": \"pending\",\n  \"status_change_date\": \"2024-01-10T14:30:00Z\"\n}\n```"
    },
    {
      "id": "l-lead-status-answers",
      "title": "Lead Status & Answer Types",
      "description": "Lead pipeline stages and form answer structures",
      "category": "reference",
      "content": "## Lead Status Pipeline\n\n### Status Progression\n\n```\nnew → contacted → qualified → converted → closed\n  ↓                              ↓\n  └──────→ no_response      lost_deal\n```\n\n### Status Definitions\n\n| Status | Meaning |\n|--------|----------|\n| **new** | Freshly captured lead |\n| **contacted** | Agent has reached out |\n| **qualified** | Lead shows buying intent |\n| **converted** | Lead scheduled viewing |\n| **closed** | Deal completed |\n| **no_response** | Lead unresponsive |\n| **lost_deal** | Opportunity missed |\n\n## Answer Object Structure\n\nLeads can answer custom form questions:\n\n```json\n{\n  \"registrant_id\": \"reg_123\",\n  \"answers\": [\n    {\n      \"question\": \"How soon are you looking to buy?\",\n      \"answer\": \"Within 3 months\",\n      \"answer_type\": \"single_select\"\n    },\n    {\n      \"question\": \"Interested in financing?\",\n      \"answer\": \"true\",\n      \"answer_type\": \"boolean\"\n    },\n    {\n      \"question\": \"Additional comments\",\n      \"answer\": \"Very interested in this property\",\n      \"answer_type\": \"text\"\n    }\n  ]\n}\n```\n\n### Answer Types\n\n- **text** - Free-form text response\n- **single_select** - One choice from options\n- **multi_select** - Multiple choices\n- **boolean** - Yes/No answer\n- **date** - Date response\n- **phone** - Phone number\n- **email** - Email address\n\n## Lead Scoring\n\nScore leads by conversion likelihood:\n```python\ndef score_lead(lead):\n    score = 0\n    if lead['status'] == 'qualified':\n        score += 50\n    if lead['status'] == 'contacted':\n        score += 25\n    if lead['registration_date'] < 7_days_ago:\n        score += 10\n    return score\n```"
    },
    {
      "id": "m-api-versioning",
      "title": "API Versioning Policy",
      "description": "Information about API versions and upgrade paths",
      "category": "reference",
      "content": "## API Versioning\n\n### Version Strategy\nSpacio uses semantic versioning:\n- **Major (v1, v2)** - Breaking changes\n- **Minor updates** - New features, backward compatible\n- **Patch updates** - Bug fixes\n\n### Current Versions\n\n**v1** (Stable)\n- Mature, widely used\n- Full feature set\n- Long-term support\n\n**v2** (Current)\n- New features\n- Improved performance\n- Enhanced error messages\n\n### Upgrade Timeline\n\n```\nToday        6 months      12 months\n  v2            v1           v1\n  v1          Support      Sunset\n```\n\n### Breaking Changes Policy\n\n1. **Announcement** - 3 months notice via email\n2. **Transition Period** - Both versions available\n3. **Sunset** - Old version disabled\n\n### What Constitutes Breaking\n\n❌ Breaking changes:\n- Endpoint URL changes\n- Required field removal\n- Response format changes\n- Authentication changes\n\n✅ Non-breaking changes:\n- New optional fields\n- New endpoints\n- New status values\n- Performance improvements\n\n### Version-Specific Features\n\n**v1 Features**\n- Basic property queries\n- Lead retrieval\n- Agent authentication\n\n**v2 Features**\n- All v1 features plus:\n- Enhanced metadata\n- Improved pagination\n- Better error details\n\n### Checking Version\n\nResponses include version info:\n```json\n{\n  \"success\": true,\n  \"api_version\": \"2.0.0\",\n  \"data\": [...]\n}\n```\n\n### Support\nContact support@spac.io for version questions."
    },
    {
      "id": "n-webhooks-notifications",
      "title": "Webhooks & Notifications",
      "description": "Setting up webhooks and notification preferences",
      "category": "reference",
      "content": "## Webhooks (Beta)\n\nEnable real-time notifications instead of polling.\n\n### Supported Events\n\n- `lead.registered` - New lead captured\n- `lead.status_changed` - Lead status updated\n- `property.status_changed` - Property listing status changed\n- `property.price_changed` - Price updated\n- `open_house.scheduled` - Open house created\n- `open_house.cancelled` - Open house cancelled\n\n### Webhook Setup\n\n1. Configure endpoint in Spacio dashboard\n2. Spacio will POST events to your URL\n3. Respond with 200 status within 10 seconds\n\n### Webhook Payload\n\n```json\n{\n  \"event\": \"lead.registered\",\n  \"timestamp\": \"2024-01-15T14:30:00Z\",\n  \"data\": {\n    \"registrant_id\": \"reg_123\",\n    \"property_id\": \"prop_456\",\n    \"email\": \"buyer@example.com\"\n  },\n  \"signature\": \"sha256_hash\"\n}\n```\n\n### Verification\n\nVerify webhook authenticity:\n```python\nimport hmac\nimport hashlib\n\ndef verify_webhook(payload, signature, secret):\n    expected = hmac.new(\n        secret.encode(),\n        payload.encode(),\n        hashlib.sha256\n    ).hexdigest()\n    return hmac.compare_digest(signature, expected)\n```\n\n### Retry Policy\n\nSpacio retries failed deliveries:\n- First attempt: Immediate\n- 2nd-4th attempts: Exponential backoff\n- Max 24 hour window\n\n### Notification Preferences\n\nConfigure which events to receive in dashboard:\n- Email notifications\n- SMS alerts\n- Webhook deliveries\n- Frequency preferences\n\n### Best Practices\n\n1. **Respond quickly** - 10 second timeout\n2. **Idempotency** - Handle duplicate events\n3. **Queue processing** - Don't process synchronously\n4. **Verify signature** - Ensure authenticity\n5. **Log all webhooks** - For debugging"
    },
    {
      "id": "o-postman-collection",
      "title": "Postman Collection Info",
      "description": "Using the Spacio API Postman collection for testing",
      "category": "reference",
      "content": "## Postman Collection\n\n### Import Collection\n\n1. Open Postman\n2. Click Import\n3. Paste or upload `spacio-api-collection.json`\n4. Collection appears in sidebar\n\n### Setup Environment\n\nCreate Postman environment with variables:\n\n**Variables:**\n- `base_url` = https://ws.spac.io/api/v1\n- `api_key` = your-api-key-here\n- `agent_key` = your-agent-id\n- `property_id` = test-property-id\n- `brokerage_id` = your-brokerage-id\n\n### Using Variables\n\nIn request URLs:\n```\n{{base_url}}/getProperties\n```\n\nIn headers:\n```\nHeader: apikey: {{api_key}}\n```\n\nIn body:\n```\nagent_key={{agent_key}}&page=1\n```\n\n### Pre-request Scripts\n\nAutomatically set timestamps:\n```javascript\npm.environment.set('timestamp', new Date().toISOString());\n```\n\n### Test Scripts\n\nValidate responses:\n```javascript\npm.test('Status code is 200', function() {\n  pm.response.to.have.status(200);\n});\n\npm.test('Response has success', function() {\n  var json = pm.response.json();\n  pm.expect(json.success).to.be.true;\n});\n```\n\n### Running Collections\n\nUse Collection Runner:\n1. Select collection\n2. Set iteration count\n3. Set delays between requests\n4. Click Run\n\n### Monitoring\n\nSetup monitoring to run collection on schedule:\n1. Select collection\n2. Click Monitors\n3. Create new monitor\n4. Set frequency (hourly/daily)\n\n### Export Results\n\nGenerate reports:\n- Execution summary\n- Pass/fail statistics\n- Response times\n- Error logs"
    },
    {
      "id": "p-faq-troubleshooting",
      "title": "FAQ & Troubleshooting",
      "description": "Frequently asked questions and common troubleshooting",
      "category": "reference",
      "content": "## FAQ\n\n### Q: How long are API keys valid?\n**A:** API keys don't expire but can be revoked. Contact support for new keys.\n\n### Q: Can I use one API key for multiple applications?\n**A:** Yes, but monitor usage separately with different API keys for better security.\n\n### Q: What's the maximum number of properties per agent?\n**A:** No limit. Use pagination to handle large result sets.\n\n### Q: Are there batch endpoints for multiple properties?\n**A:** Not currently. Use pagination to retrieve multiple properties efficiently.\n\n### Q: Can I filter properties by price range?\n**A:** Not in the API. Filter results in your application.\n\n### Q: How often is property data updated?\n**A:** Data updates hourly from MLS feeds.\n\n### Q: Can I get historical property data?\n**A:** Contact support for historical data access.\n\n### Q: Is there a sandbox/test environment?\n**A:** Use v2 with test API keys for testing.\n\n## Troubleshooting\n\n### Problem: 401 Unauthorized\n\n**Causes:**\n- API key missing or incorrect\n- API key revoked\n- Wrong header name\n\n**Solution:**\n```bash\n# Verify header format\ncurl -H 'apikey: YOUR_KEY' https://ws.spac.io/api/v1/getProperties\n\n# Not: api-key or Api-Key\n```\n\n### Problem: 429 Rate Limited\n\n**Causes:**\n- Exceeded 12,000 requests/hour\n- Too many concurrent requests\n\n**Solution:**\n- Wait for rate limit reset\n- Implement exponential backoff\n- Cache frequently accessed data\n\n### Problem: Empty Results\n\n**Causes:**\n- Wrong property/agent ID\n- Data doesn't exist\n- No access permissions\n\n**Solution:**\n```python\n# Verify ID exists\nif response['success'] and response['data']:\n    print(response['data'])\nelse:\n    print('No results found')\n```\n\n### Problem: Slow Responses\n\n**Causes:**\n- Large result sets\n- Network latency\n- Server load\n\n**Solution:**\n- Reduce page limit\n- Use caching\n- Add timeout handling\n\n### Problem: Inconsistent Data\n\n**Causes:**\n- Data updated between requests\n- Timing issues\n\n**Solution:**\n- Add updated_at timestamp comparison\n- Implement caching strategy\n- Sync less frequently if needed\n\n### Getting Help\n\n- Email: support@spac.io\n- Phone: 1-800-SPACIO-1\n- Status page: status.spac.io\n- Community: forums.spac.io"
    }
  ]
}
