openapi: 3.1.0
info:
  title: RentEngine Public API
  description: >
    Integrate your systems anywhere with RentEngine.


    ## Authorization


    This API uses JWT Bearer token authentication. Follow these steps to obtain
    and use your API tokens:


    ### Obtaining API Tokens


    1. Log in to your RentEngine [developer
    portal](https://app.rentengine.io/developer/portal)

    2. In the top corner, click the "Create New API Key" button

    3. Provide a name for your token (e.g., "Integration Name")

    4. Click Create

    5. Copy the token to your clipboard and save it securely as it will not be
    displayed again


    **Important Security Notice:** Your token will only be displayed ONCE at
    creation time. Make sure to copy it and store it securely. For security
    reasons, we cannot display the token again after this point.


    ### Using API Tokens


    Include your token in all API requests as a Bearer token in the
    Authorization header:


    ```

    Authorization: Bearer your_token_here

    ```


    ### Token Security Best Practices


    - Store tokens securely in environment variables or a secure vault

    - Never hardcode tokens in your application code

    - Do not share tokens in public repositories or client-side code

    - Use separate tokens for different integrations or environments


    ### Token Permissions


    Each token generated by a user will have the full permissions of the user
    that created it across all accounts associated with that user.

    Actions will be logged in the name of that user & token.


    ### Invalidating Tokens


    Tokens will not expire. (Well not for 100 years at least). If a token is
    compromised or no longer needed:


    1. Log in to your RentEngine [developer
    portal](https://app.rentengine.io/developer/portal)

    2. Find the token you wish to invalidate in the table in the API Keys
    section

    3. Click the "Revoke Token" icon that looks like a trash can


    Once revoked, a token cannot be restored. You'll need to create a new token
    if needed.


    ### Pagination


    Most list endpoints in the RentEngine API support pagination to efficiently
    handle large datasets. Paginated endpoints accept the same query parameters,
    but there are **two response formats** in use. Check the endpoint's response
    schema to determine which format it returns. A few endpoints return a fixed,
    bounded result set instead of paging (e.g. `GET /market-tool/comps` returns
    up to 200 most recently active comparables) — these do not accept pagination
    parameters.


    **Pagination Parameters (all list endpoints)**


    - `limit` - Controls how many items to return per page (default: 50, max:
    100)

    - `page_number` - Specifies which page to retrieve (0-indexed, default: 0)


    Example request with pagination:

    ```

    GET /api/public/v1/lockboxes?limit=25&page_number=1

    ```


    This would return the second page of results with 25 items per page.


    #### Response Format A — Bare Array (legacy)


    Most list endpoints return a bare JSON array containing only the requested
    page of items. The response does **not** include the total count or an
    explicit end-of-data marker.


    Endpoints using this format include:

    - `/lockboxes`

    - `/lockbox_events`

    - `/lockbox_installations`

    - `/units`

    - `/prospects`

    - `/subteams`

    - `/prescreening_templates`

    - `/rental_applications`


    Example response:

    ```json

    [
      { "id": "...", "...": "..." },
      { "id": "...", "...": "..." }
    ]

    ```


    To iterate, increment `page_number` until the response array is shorter than
    the requested `limit` — that indicates the last page.


    #### Response Format B — Envelope with Page Metadata


    Newer list endpoints wrap the data in an envelope that includes explicit
    pagination metadata, so you don't have to infer the end of the dataset from
    the array length.


    Endpoints using this format include:

    - `/rental_application_groups`


    Example response:

    ```json

    {
      "data": [
        { "id": "...", "...": "..." },
        { "id": "...", "...": "..." }
      ],
      "page": {
        "limit": 50,
        "page_number": 0,
        "has_more": true,
        "next_page_number": 1
      }
    }

    ```


    Fields in the `page` object:

    - `limit` - The `limit` value used for this response (echoes the request)

    - `page_number` - The 0-indexed page returned (echoes the request)

    - `has_more` - `true` if additional pages are available, `false` on the
    final page

    - `next_page_number` - The page number to request next, or `null` when
    `has_more` is `false`


    To iterate, follow `next_page_number` until it is `null` (or `has_more` is
    `false`).


    **Performance Considerations**


    - Use appropriate `limit` values based on your needs. Smaller values reduce
    payload size but require more API calls, which can slow down performance and
    be subject to rate limits.

    - When filtering data, apply filters in the query parameters first to reduce
    the total number of items that need to be fetched.


    ## Rate Limiting


    To ensure fair usage and protect our infrastructure, all API endpoints are
    rate limited. Rate limits are applied per user (based on your API token).


    **Default Rate Limits**


    | Tier | Requests | Window |

    |------|----------|--------|

    | Standard | 30 | 5 seconds |

    | Strict | 10 | 5 seconds |

    | Market Tool | 40 | 24 hours |


    Most endpoints use the "Standard" tier. Endpoints that return PII or

    stream binary artifacts — `GET /rental_applications/{id}` and

    `GET /rental_applications/{id}/documents/{documentId}` — use the

    "Strict" tier (2 req/s).


    The market comps endpoint — `GET /market-tool/comps` — uses the "Market

    Tool" tier (40 requests per 24 hours) and is **metered: each successful

    call incurs a $0.50 charge** to your account. The strict daily limit and

    per-call charge exist to prevent abuse of this data-intensive endpoint.


    **Rate Limit Headers**


    All API responses include headers to help you track your rate limit status:


    | Header | Description |

    |--------|-------------|

    | `X-RateLimit-Limit` | Maximum requests allowed in the current window |

    | `X-RateLimit-Remaining` | Number of requests remaining in the current
    window |

    | `X-RateLimit-Reset` | Unix timestamp (milliseconds) when the rate limit
    resets |


    **Handling Rate Limits**


    When you exceed the rate limit, you'll receive a `429 Too Many Requests`
    response with a `Retry-After` header indicating how many seconds to wait
    before retrying.


    ```json

    {
      "error": "Too Many Requests",
      "message": "Rate limit exceeded. Please try again later.",
      "retryAfter": 4
    }

    ```


    **Best Practices**


    - Monitor the `X-RateLimit-Remaining` header to avoid hitting limits

    - Implement exponential backoff when retrying after a 429 response

    - Cache responses when possible to reduce API calls

    - Use webhooks for real-time updates instead of polling


    ## Webhooks


    RentEngine provides webhooks to notify your systems about events in
    real-time. This allows you to build integrations that respond immediately to
    changes in your RentEngine data.


    **Setting Up Webhooks**


    Webhooks can be configured through the RentEngine [developer
    portal](https://app.rentengine.io/developer/portal). You'll need to specify:


    1. The target URL where webhook events should be sent

    2. The data you want to monitor (e.g., lockboxes, units, lockbox_events)

    3. The event types you want to receive (INSERT, UPDATE, DELETE)

    4. An optional API key that will be included in webhook requests to your
    endpoint


    **Webhook Payload Structure**


    Webhook payloads follow this general structure:


    ```json

    {
      "type": "INSERT|UPDATE|DELETE",
      "table": "table_name",
      "record": { /* The current state of the record (null for DELETE) */ },
      "old_record": { /* The previous state of the record (null for INSERT) */ }
    }

    ```


    The specific fields in `record` and `old_record` will depend on the table
    that triggered the event.


    **Event Types**


    - `INSERT`: Sent when a new record is created

    - `UPDATE`: Sent when an existing record is modified

    - `DELETE`: Sent when a record is deleted


    **Security Considerations**


    - Webhook endpoints should be HTTPS to ensure secure transmission of data

    - Validate the API key included in the webhook request to ensure it's coming
    from RentEngine

    - Implement idempotency in your webhook handlers to prevent duplicate
    processing


    **Webhook Delivery**


    RentEngine uses a reliable delivery system (QStash) to ensure webhooks are
    delivered even during temporary outages. If your endpoint is unavailable,
    we'll retry delivery with exponential backoff.
  version: 1.1.1
  contact:
    email: eng@rentengine.io
    url: https://rentengine.io
  license:
    name: Proprietary
    url: https://www.rentengine.io/termsofuse
servers:
  - url: https://app.rentengine.io/api/public/v1
    description: Production environment
  - url: https://staging-app.rentengine.io/api/public/v1
    description: Staging environment
paths:
  /lockboxes:
    get:
      summary: Get lockboxes
      description: Retrieve lockboxes with optional filtering and pagination
      operationId: getLockboxes
      tags:
        - Lockboxes
      parameters:
        - name: serial_numbers
          in: query
          description: Filter by comma-separated list of lockbox provider serial numbers
          schema:
            type: array
            items:
              type: string
              example: '1234567'
          style: form
          explode: false
          example:
            - '1234567'
            - '7654321'
        - name: lockbox_ids
          in: query
          description: Filter by comma-separated list of RentEngine lockbox IDs
          schema:
            type: array
            items:
              type: string
              example: 123e4567-e89b-12d3-a456-426614174000
          style: form
          explode: false
          example:
            - 123e4567-e89b-12d3-a456-426614174000
            - 123e4567-e89b-12d3-a456-426614174001
        - name: account_id
          in: query
          description: >-
            Filter by lockboxes associated with a specific RentEngine account by
            the account's id
          schema:
            type: string
            example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        - name: lockbox_type
          in: query
          description: |
            Filter by lockbox type. All types are filterable; note that
            CREATING lockboxes via the API is Sentrilock-only (see
            PostLockboxesRequest).
          schema:
            $ref: '#/components/schemas/LockboxTypeValue'
        - $ref: '#/components/parameters/PaginationLimit'
        - $ref: '#/components/parameters/PaginationPage'
      responses:
        '200':
          description: Success. Returns a list of lockboxes.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Lockbox'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
    post:
      summary: Create lockboxes
      description: Create new lockboxes (currently only SentriLock type is supported)
      operationId: postLockboxes
      tags:
        - Lockboxes
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostLockboxesRequest'
            example:
              lockbox_type: Sentrilock
              serial_numbers:
                - '1234567'
                - '7654321'
              account_id: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
      responses:
        '201':
          description: Lockboxes created successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Lockbox'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /lockboxes/transfer_accounts:
    post:
      summary: Transfer lockboxes between accounts
      description: >-
        Moves lockboxes between accounts. The user must have access to both the
        lockboxes and the target account.
      operationId: postLockboxesTransferAccounts
      tags:
        - Lockboxes
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostLockboxTransferAccountsRequest'
            example:
              lockbox_ids:
                - 123e4567-e89b-12d3-a456-426614174000
                - 123e4567-e89b-12d3-a456-426614174001
              new_account_id: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
      responses:
        '200':
          description: Lockboxes transferred successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Lockbox'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            Forbidden - User does not have access to the target account or the
            specified lockboxes
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                unauthorized-account:
                  value:
                    error: Unauthorized to transfer lockboxes to this account
                unauthorized-lockboxes:
                  value:
                    error: Unauthorized to transfer these lockboxes.
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /lockbox_events:
    get:
      summary: Get lockbox events
      description: Retrieve lockbox events with optional filtering and pagination
      operationId: getLockboxEvents
      tags:
        - Lockbox Events
      parameters:
        - name: serial_numbers
          in: query
          description: Filter by comma-separated list of serial numbers
          schema:
            type: array
            items:
              type: string
              example: '1234567'
          style: form
          explode: false
          example:
            - '1234567'
            - '7654321'
        - name: lockbox_ids
          in: query
          description: Filter by comma-separated list of lockbox IDs
          schema:
            type: array
            items:
              type: string
              example: 123e4567-e89b-12d3-a456-426614174000
          style: form
          explode: false
          example:
            - 123e4567-e89b-12d3-a456-426614174000
            - 123e4567-e89b-12d3-a456-426614174001
        - name: lockbox_event_ids
          in: query
          description: Filter by comma-separated list of lockbox event IDs
          schema:
            type: array
            items:
              type: string
              example: 123e4567-e89b-12d3-a456-426614174002
          style: form
          explode: false
          example:
            - 123e4567-e89b-12d3-a456-426614174002
            - 123e4567-e89b-12d3-a456-426614174003
        - name: account_id
          in: query
          description: Filter by account ID
          schema:
            type: string
            example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        - name: lockbox_type
          in: query
          description: Filter by lockbox type
          schema:
            $ref: '#/components/schemas/LockboxTypeValue'
        - name: event_types
          in: query
          description: Filter by event types
          schema:
            type: array
            items:
              $ref: '#/components/schemas/LockboxEventType'
          style: form
          explode: false
          example:
            - Install
            - Uninstall
        - name: created_at_from
          in: query
          description: Filter events created after this timestamp (ISO 8601 format)
          schema:
            type: string
            format: date-time
            example: '2023-01-01T00:00:00Z'
        - name: created_at_to
          in: query
          description: Filter events created before this timestamp (ISO 8601 format)
          schema:
            type: string
            format: date-time
            example: '2023-12-31T23:59:59Z'
        - name: unit_ids
          in: query
          description: Filter by comma-separated list of unit IDs
          schema:
            type: array
            items:
              type: string
              example: '12345'
          style: form
          explode: false
          example:
            - '12345'
            - '67890'
        - $ref: '#/components/parameters/PaginationLimit'
        - $ref: '#/components/parameters/PaginationPage'
      responses:
        '200':
          description: Success. Returns a list of lockbox events.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/LockboxEvent'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
    post:
      summary: Create lockbox events
      description: Create new lockbox events (Install or Uninstall)
      operationId: postLockboxEvents
      tags:
        - Lockbox Events
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostLockboxEventsRequest'
            example:
              events:
                - lockbox_id: 123e4567-e89b-12d3-a456-426614174000
                  event_type: Install
                  unit_id: 12345
                - lockbox_id: 123e4567-e89b-12d3-a456-426614174001
                  event_type: Uninstall
                  unit_id: 67890
      responses:
        '201':
          description: Lockbox events created successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/LockboxEvent'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /lockbox_installations:
    get:
      summary: Get lockbox installations
      description: >-
        Retrieve lockbox installations with optional filtering and pagination.
        Lockbox installations can only be created by inserting a lockbox event
        with event_type "Install".
      operationId: getLockboxInstallations
      tags:
        - Lockbox Installations
      parameters:
        - name: lockbox_ids
          in: query
          description: Filter by comma-separated list of lockbox IDs
          schema:
            type: array
            items:
              type: string
              example: 123e4567-e89b-12d3-a456-426614174000
          style: form
          explode: false
          example:
            - 123e4567-e89b-12d3-a456-426614174000
            - 123e4567-e89b-12d3-a456-426614174001
        - name: unit_ids
          in: query
          description: Filter by comma-separated list of unit IDs
          schema:
            type: array
            items:
              type: string
              example: '12345'
          style: form
          explode: false
          example:
            - '12345'
            - '67890'
        - $ref: '#/components/parameters/PaginationLimit'
        - $ref: '#/components/parameters/PaginationPage'
      responses:
        '200':
          description: Success. Returns a list of lockbox installations.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/LockboxInstallation'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /units:
    get:
      summary: Get units
      description: Retrieve units with optional filtering and pagination
      operationId: getUnits
      tags:
        - Units
      parameters:
        - name: unitIds
          in: query
          description: Filter by comma-separated list of unit IDs
          schema:
            type: array
            items:
              type: number
              example: 12345
          style: form
          explode: false
          example:
            - 12345
            - 67890
        - name: extracted_from
          in: query
          description: >-
            Any string that can be used to identify the unit in an external
            system. Essentially the same as an external_id, but not limited to
            an ID format. Uniqueness is not enforced.
          schema:
            type: string
            example: f78125c
        - name: accountId
          in: query
          description: Filter by account ID
          schema:
            type: string
            example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        - name: statuses
          in: query
          description: Filter by comma-separated list of unit statuses
          schema:
            type: array
            items:
              type: string
              example: Incomplete
              enum:
                - Under Review
                - Available
                - Application Recieved
                - Application Approved
                - Lease Out For Signing
                - Lease Signed
                - Lease Signed & Deposit Paid
                - Leased
                - On Hold
                - Expired
                - Withdrawn
                - Withdrawal Requested
                - Incomplete
                - Price Analysis
                - Archived
          example:
            - Available
            - Incomplete
        - $ref: '#/components/parameters/PaginationLimit'
        - $ref: '#/components/parameters/PaginationPage'
      responses:
        '200':
          description: Success. Returns a list of units.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Unit'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
    post:
      summary: Create or update a unit
      description: >
        Create a new unit or update an existing one.


        ## Insert vs Update

        - **Insert**: When no `id` is provided, a new unit will be created.
        Required fields for creation include `address`, `property_type`,
        `target_rental_rate`, and `account_id`.

        - **Update**: When an `id` is provided, an existing unit will be
        updated. No other fields are required.


        ## Address Updates

        When updating a unit, if you include the `address` field, you must
        provide all address components (`street_number`, `street_name`,
        `zip_code`, `state`, `city`). Partial address updates are not supported.


        ## Structured Access Instructions

        When providing `structured_access_instructions`, the `showing_method`
        field must also be set. The structure of the access instructions depends
        on the showing method:

        - For "Self Guided", "Remote Guided", or "Remote Guided with Gated
        Access" methods: Include fields like `lockbox_location`, `lockbox_code`,
        etc.

        - For "Accompanied" method: Include fields like `assigned_user_ids`,
        `meeting_location`, etc.
      operationId: postUnit
      tags:
        - Units
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpsertUnitRequest'
      responses:
        '200':
          description: Unit successfully created or updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  unit:
                    $ref: '#/components/schemas/Unit'
        '400':
          description: Bad request - invalid input parameters or request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                validation-error:
                  value:
                    error: Invalid request body
                    details:
                      - keyword: required
                        dataPath: ''
                        schemaPath: '#/required'
                        params:
                          missingProperty: address
                        message: should have required property 'address'
                foreign-key-error:
                  value:
                    error: Invalid foreign IDs
                    details:
                      - field: account_id
                        id: invalid-uuid
                        message: Account with ID invalid-uuid does not exist
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /multifamily_properties:
    get:
      summary: Get multifamily properties
      description: Retrieve multifamily properties with optional filtering
      operationId: getMultifamilyProperties
      tags:
        - Multifamily Properties
      parameters:
        - name: account_id
          in: query
          description: Filter by account ID
          schema:
            type: string
            example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
            format: uuid
          required: false
          example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        - name: id
          in: query
          description: Filter by multifamily property ID
          schema:
            type: string
            example: 123e4567-e89b-12d3-a456-426614174000
            format: uuid
          example: 123e4567-e89b-12d3-a456-426614174000
        - name: deleted
          in: query
          description: Filter by deleted status
          schema:
            type: boolean
            example: false
            default: false
          example: false
      responses:
        '200':
          description: Success. Returns a list of multifamily properties.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/MultifamilyProperty'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
    post:
      summary: Create or update a multifamily property
      description: Create a new multifamily property or update an existing one
      operationId: postMultifamilyProperties
      tags:
        - Multifamily Properties
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpsertMultifamilyPropertyRequest'
            example:
              community_name: Sunset Towers
              building_count: 3
              unit_count: 75
              description: Luxury apartment community with amenities
              structure_type: Mid Rise
              year_built: 2008
              photos:
                - path: https://example.com/images/sunset-towers.jpg
                  hidden: false
              text_address: 123 Main St, San Francisco, CA 94111
              account_id: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
      responses:
        '200':
          description: Multifamily property successfully created or updated
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/MultifamilyProperty'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /floorplans:
    get:
      summary: Get floorplans
      description: Retrieve multifamily_prs with optional filtering
      operationId: getFloorplans
      tags:
        - Floorplans
      parameters:
        - name: multifamily_property_id
          in: query
          description: Filter by multifamily property ID
          schema:
            type: string
            example: 123e4567-e89b-12d3-a456-426614174000
            format: uuid
          required: false
          example: 123e4567-e89b-12d3-a456-426614174000
        - name: account_id
          in: query
          description: Filter by account ID
          schema:
            type: string
            example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
            format: uuid
          required: false
          example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        - name: id
          in: query
          description: Filter by floorplan ID
          schema:
            type: string
            example: 123e4567-e89b-12d3-a456-426614174000
            format: uuid
          example: 123e4567-e89b-12d3-a456-426614174000
        - name: deleted
          in: query
          description: Filter by deleted status
          schema:
            type: boolean
            example: false
            default: false
          example: false
      responses:
        '200':
          description: Success. Returns a list of floorplans.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Floorplan'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
    post:
      summary: Create or update a floorplan
      description: Create a new floorplan or update an existing one
      operationId: postFloorplans
      tags:
        - Floorplans
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpsertFloorplanRequest'
            example:
              multifamily_property_id: 123e4567-e89b-12d3-a456-426614174000
              name: The Willow
              bedroom_count: 2
              bathroom_count: 2.5
              unit_count: 15
              units_available: 3
              market_rent: 1850
              min_sqft: 950
              max_sqft: 1100
              photos:
                - path: https://example.com/images/willow-floorplan.jpg
                  hidden: false
              description: Spacious 2-bedroom layout with modern finishes
      responses:
        '200':
          description: Floorplan successfully created or updated
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Floorplan'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /prospects:
    get:
      summary: Get prospects
      description: Retrieve prospects with optional filtering and pagination
      operationId: getProspects
      tags:
        - Prospects
      parameters:
        - name: id
          in: query
          description: Filter by prospect ID
          schema:
            type: number
            example: 123
        - name: account_id
          in: query
          description: >-
            Filter by prospects associated with a specific RentEngine account by
            the account's id
          schema:
            type: string
            format: uuid
            example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        - name: units_of_interest
          in: query
          description: >-
            Filter by prospects interested in specific units (comma-separated
            list of unit IDs)
          schema:
            type: array
            items:
              type: number
              example: 234
          style: form
          explode: false
          example:
            - 123
            - 124
        - name: status
          in: query
          description: Filter prospects by status
          schema:
            type: string
            example: Showing Scheduled
        - name: source
          in: query
          description: Filter prospects by source
          schema:
            type: string
            example: Zillow
        - name: created_after
          in: query
          description: Filter prospects created after this timestamp (ISO 8601 format)
          schema:
            type: string
            format: date-time
            example: '2023-01-15T12:00:00Z'
        - name: created_before
          in: query
          description: Filter prospects created before this timestamp (ISO 8601 format)
          schema:
            type: string
            format: date-time
            example: '2023-01-17T12:00:00Z'
        - $ref: '#/components/parameters/PaginationLimit'
        - $ref: '#/components/parameters/PaginationPage'
      responses:
        '200':
          description: Success. Returns a list of prospects.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Prospect'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
    post:
      summary: Create a prospect
      description: >
        Create a new prospect. Reuses the standard new-prospect workflow,

        which handles the initial leasing event, the new-lead notification to
        the

        account team, and (by default) sending the acknowledgement SMS to the

        prospect.


        ## Identifying the property

        Provide exactly one of:
          - `unit_id` — the RentEngine unit ID. Access is scoped to the
            authenticated user's account; a `404` is returned if the unit
            is not visible.
          - `unit_address` — a free-text address that will be fuzzy-matched against
            units in the account named by `account_id`. If no unit matches, a `404`
            is returned. The top match is used when there is one.
          - `floorplan_id` — a multifamily floorplan. Creates a floorplan-level
            lead (not bound to a specific unit). `404` if the floorplan is not
            visible.
          - `multifamily_property_id` — a multifamily building/community. Creates
            a building-level lead. `404` if the property is not visible.
          - `account_id` alone — an account-level lead with no unit, floorplan,
            or building. `404` if the account is not visible to the caller.

        Floorplan, building, and account-level creates require `phone` (the

        unitless persist path keys on phone). `account_id` may also be sent

        alongside `unit_id` / `floorplan_id` / `multifamily_property_id`; it is

        ignored in favor of the account derived from that property.


        ## SMS

        By default the prospect receives the account's configured
        acknowledgement

        SMS (varies by unit availability / apply-first settings; building and

        floorplan leads use the matching inquiry templates). Set

        `sms.send` to `false` to skip sending entirely — useful when the

        integrating system has already messaged the prospect. `phone` is

        required whenever `sms.send` is `true` (the default), `ai_enabled`

        is `false` (the per-prospect AI flag is keyed on phone), or the lead

        is unitless.


        ## AI

        AI responses to this prospect are enabled by default. Set `ai_enabled`

        to `false` to opt this prospect out of AI replies for their phone

        number within the account.


        ## Duplicate handling

        This endpoint is idempotent on `(phone, scope)`. If a prospect with the

        same phone already exists for the resolved unit, floorplan, building, or

        account, the existing record is reused — no new row is created — and the

        response includes `re_engaged: true` with the existing `prospect_id`.

        The status code is `200 OK` on re-engagement and `201 Created` when a

        brand-new prospect row was inserted. `notes` and `prospect_type` are

        applied only on fresh creates so they don't clobber a re-engaged

        prospect mid-flow.


        ## Rate limiting

        This endpoint uses the **Strict** tier (10 requests / 5 seconds).
      operationId: postProspect
      tags:
        - Prospects
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostProspectsRequest'
            examples:
              byUnitId:
                summary: Create a prospect against a known unit ID
                value:
                  source: Zillow
                  name: Jane Doe
                  email: jane@example.com
                  phone: '+12155551234'
                  unit_id: 12345
                  notes: Came in via partner site
                  prospect_type: Self
              byUnitAddress:
                summary: Create a prospect by fuzzy-matching a unit address
                value:
                  source: Zillow
                  name: Jane Doe
                  email: jane@example.com
                  phone: '+12155551234'
                  account_id: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
                  unit_address: 2516 Cecil Ave, Philadelphia PA
              skipSmsAndDisableAi:
                summary: Create a prospect without sending an SMS and with AI disabled
                value:
                  source: Custom Integration
                  name: Jane Doe
                  email: jane@example.com
                  phone: '+12155551234'
                  unit_id: 12345
                  ai_enabled: false
                  sms:
                    send: false
              byFloorplan:
                summary: Create a floorplan-level prospect
                value:
                  source: Company Website
                  name: Jane Doe
                  email: jane@example.com
                  phone: '+12155551234'
                  floorplan_id: 6eac2077-a67e-4888-846b-6ff15015c855
              byBuilding:
                summary: Create a building-level prospect
                value:
                  source: Company Website
                  name: Jane Doe
                  email: jane@example.com
                  phone: '+12155551234'
                  multifamily_property_id: 6eac2077-a67e-4888-846b-6ff15015c855
              byAccount:
                summary: Create an account-level prospect with no property
                value:
                  source: Custom Integration
                  name: Jane Doe
                  email: jane@example.com
                  phone: '+12155551234'
                  account_id: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
      responses:
        '200':
          description: >
            An existing prospect was re-engaged. The `re_engaged` field is
            `true`

            and `prospect_id` references the pre-existing record.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateProspectResponse'
        '201':
          description: |
            A new prospect row was created. The `re_engaged` field is `false`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateProspectResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: |
            The property could not be resolved — `unit_id`, `floorplan_id`,
            `multifamily_property_id`, or `account_id` is not visible to the
            caller, or `unit_address` did not fuzzy-match any unit in the given
            account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                unit-id-not-found:
                  value:
                    error: Unit 12345 not found
                no-fuzzy-match:
                  value:
                    error: >-
                      No unit matched the address "2516 Cecil Ave, Philadelphia
                      PA"
                floorplan-not-found:
                  value:
                    error: Floorplan 6eac2077-a67e-4888-846b-6ff15015c855 not found
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /lockboxes/generate_code:
    post:
      summary: Generate a lockbox code
      description: >-
        Generate a one-time code for a lockbox. The code can be generated by
        providing either a lockbox_id, serial_number, or unit_id. The code will
        be valid for the specified date.
      operationId: postGenerateLockboxCode
      tags:
        - Lockboxes
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostGenerateLockboxCodeRequest'
            example:
              lockbox_id: 123e4567-e89b-12d3-a456-426614174000
              date: '2024-03-15'
              created_for: John Doe
              code_type: ACCESS
      responses:
        '200':
          description: Success. Returns the generated code and lockbox type.
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: string
                    description: The generated lockbox code
                    example: '1234'
                  lockboxType:
                    type: string
                    enum:
                      - Sentrilock
                      - Codebox
                    description: Type of the lockbox
                    example: Sentrilock
                  instructions:
                    type: string
                    description: >-
                      Optional instructions for using the code. May or may not
                      be provided, depending on the lockbox.
                    example: 'Enter code followed by #'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /subteams:
    get:
      summary: Get subteams
      description: Retrieve subteams with optional filtering and pagination
      operationId: getSubteams
      tags:
        - Subteams
      parameters:
        - name: subteam_ids
          in: query
          description: Filter by comma-separated list of subteam IDs
          schema:
            type: array
            items:
              type: string
              example: 123e4567-e89b-12d3-a456-426614174000
          style: form
          explode: false
          example:
            - 123e4567-e89b-12d3-a456-426614174000
            - 123e4567-e89b-12d3-a456-426614174001
        - name: account_id
          in: query
          description: Filter by account ID
          schema:
            type: string
            example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        - $ref: '#/components/parameters/PaginationLimit'
        - $ref: '#/components/parameters/PaginationPage'
      responses:
        '200':
          description: Success. Returns a list of subteams.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Subteam'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /prescreening_templates:
    get:
      summary: Get prescreening templates
      description: Retrieve prescreening templates with optional filtering and pagination
      operationId: getPrescreeningTemplates
      tags:
        - Prescreening Templates
      parameters:
        - name: templateIds
          in: query
          description: Filter by comma-separated list of template IDs
          schema:
            type: array
            items:
              type: string
              example: 123e4567-e89b-12d3-a456-426614174000
          style: form
          explode: false
          example:
            - 123e4567-e89b-12d3-a456-426614174000
            - 123e4567-e89b-12d3-a456-426614174001
        - name: accountId
          in: query
          description: Filter by account ID
          schema:
            type: string
            example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        - name: isDefault
          in: query
          description: Filter by default template status
          schema:
            type: boolean
            example: true
        - $ref: '#/components/parameters/PaginationLimit'
        - $ref: '#/components/parameters/PaginationPage'
      responses:
        '200':
          description: Success. Returns a list of prescreening templates.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PrescreeningTemplate'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /showings/availability:
    get:
      summary: Get unit showing availability
      description: >-
        Retrieve showing availability for a specific unit, including available
        and preferred showing windows
      operationId: getShowingAvailability
      tags:
        - Showings
      parameters:
        - name: unitId
          in: query
          description: ID of the unit to get availability for
          schema:
            type: number
            example: 12345
          required: true
      responses:
        '200':
          description: Success. Returns showing availability for the unit.
          content:
            application/json:
              schema:
                type: object
                properties:
                  availability:
                    $ref: '#/components/schemas/UnitShowingAvailability'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /showings/create:
    post:
      summary: Create a showing
      description: >
        Create a new showing for a unit. This endpoint handles both new showings
        and rescheduling of existing showings.


        ## Prospect Types

        - **Self**: Regular prospect who needs to complete prescreening

        - **Agent**: Real estate agent who needs to provide a valid agent token


        ## Prescreening

        For self prospects, the system will automatically run prescreening based
        on the unit's prescreen template.

        If prescreening fails, the showing will not be created and an
        appropriate error will be returned.


        ## Agent Tokens

        For agent prospects, a valid 6-character agent token must be provided in
        the `agentTk` field.


        ## Showing Methods

        The `desiredShowingMethod` field allows specifying the preferred showing
        method:

        - "Accompanied": Agent-guided showing

        - "Self Guided": Self-guided showing

        - "Remote Guided": Remote-guided showing

        - "Remote Guided with Gated Access": Remote-guided showing with gate
        access
      operationId: createShowing
      tags:
        - Showings
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateShowingRequest'
            example:
              unitId: 12345
              plannedForTime: '2024-03-15T10:00:00Z'
              prospectData:
                firstName: John
                lastName: Doe
                email: john.doe@example.com
                phone: '5551234567'
                creditScore: 700+
                income: $5000-$6000/month
                questionAnswers:
                  - question: Do you have a housing voucher (e.g. Section 8)?
                    fixedQuestionType: housing_voucher
                    type: yes_no
                    answer: false
                  - question: Have you been convicted of a felony?
                    type: yes_no
                    answer: false
                prospectType: Self
                voucherHolder: false
              desiredShowingMethod: Accompanied
      responses:
        '200':
          description: Showing created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateShowingResponse'
        '400':
          description: Bad request - validation error or business logic error
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Error message
                    example: Unit is on hold. Cannot create showing.
                required:
                  - message
              examples:
                unit-on-hold:
                  value:
                    message: Unit is on hold. Cannot create showing.
                showing-time-unavailable:
                  value:
                    message: Showing time is no longer available
                showing-method-unavailable:
                  value:
                    message: Showing method no longer available for desired slot
                past-showing-time:
                  value:
                    message: Cannot schedule a showing in the past
                invalid-agent-token:
                  value:
                    message: Agent token is invalid
                unit-unknown:
                  value:
                    message: Cannot schedule a showing for an unknown unit
                no-showing-time:
                  value:
                    message: No showing time provided
                prescreen-template-not-found:
                  value:
                    message: Showing prescreen template not found
                prospect-blocked:
                  value:
                    message: Showings are no longer available at this unit.
                prescreen-rejection:
                  value:
                    message: 'Prescreening rejected: Self Reported Income'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Error message
                    example: Failed to create showing.
                required:
                  - message
              examples:
                generic-error:
                  value:
                    message: Failed to create showing.
                coordinator-error:
                  value:
                    message: Failed to create showing
      security:
        - BearerAuth: []
  /notes:
    post:
      summary: Create a prospect note
      description: |
        Create a note on a prospect. Notes are keyed by phone number, so the
        note appears on every prospect record sharing that number.
      operationId: postNote
      tags:
        - Notes & Follow-ups
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostNoteRequest'
            examples:
              minimal:
                summary: Note
                value:
                  prospect_id: 12345
                  note: Spoke with prospect — interested in unit 5B
      responses:
        '201':
          description: Note created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NoteRow'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
    get:
      summary: List a prospect's notes
      description: >-
        Retrieve a prospect's notes (newest first), by prospect_id or phone
        (supply exactly one).
      operationId: getNotes
      tags:
        - Notes & Follow-ups
      parameters:
        - name: prospect_id
          in: query
          description: >-
            The prospect's numeric id. Provide either this or phone (exactly
            one).
          required: false
          schema:
            type: integer
            minimum: 1
            example: 12345
        - name: phone
          in: query
          description: >-
            A US phone number in any human-readable format (normalized to E.164
            server-side). Matches all prospect records sharing this number, so
            results may span more than one prospect_id.
          required: false
          schema:
            type: string
            example: (415) 555-0100
        - $ref: '#/components/parameters/ReportingLimit'
        - $ref: '#/components/parameters/ReportingPageNumber'
      responses:
        '200':
          description: Paginated note rows for the prospect.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotesList'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      security:
        - BearerAuth: []
  /followups:
    post:
      summary: Create a prospect follow-up
      description: |
        Create a follow-up (a scheduled reminder) on a prospect. If
        `remind_at` is set, a push notification is sent to the user at that
        time.
      operationId: postFollowup
      tags:
        - Notes & Follow-ups
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostFollowupRequest'
            examples:
              noteOnly:
                summary: Follow-up with no reminder
                value:
                  prospect_id: 12345
                  note: Touch base next week about renewal
              withReminder:
                summary: Follow-up with scheduled reminder
                value:
                  prospect_id: 12345
                  note: Call about rent application
                  remind_at: '2026-06-01T17:00:00Z'
                  channel: PHONE
      responses:
        '201':
          description: Follow-up created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FollowupRow'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
    get:
      summary: List a prospect's follow-ups
      description: >-
        Retrieve a prospect's active follow-ups (newest first), by prospect_id
        or phone (supply exactly one).
      operationId: getFollowups
      tags:
        - Notes & Follow-ups
      parameters:
        - name: prospect_id
          in: query
          description: >-
            The prospect's numeric id. Provide either this or phone (exactly
            one).
          required: false
          schema:
            type: integer
            minimum: 1
            example: 12345
        - name: phone
          in: query
          description: >-
            A US phone number in any human-readable format (normalized to E.164
            server-side). Matches all prospect records sharing this number, so
            results may span more than one prospect_id.
          required: false
          schema:
            type: string
            example: (415) 555-0100
        - $ref: '#/components/parameters/ReportingLimit'
        - $ref: '#/components/parameters/ReportingPageNumber'
      responses:
        '200':
          description: Paginated follow-up rows for the prospect.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FollowupsList'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      security:
        - BearerAuth: []
  /leasing_events:
    get:
      summary: List a prospect's leasing events
      description: >-
        Retrieve a prospect's leasing-event timeline (newest first), by
        prospect_id or phone (supply exactly one).
      operationId: getProspectLeasingEvents
      tags:
        - Leasing Events
      parameters:
        - name: prospect_id
          in: query
          description: >-
            The prospect's numeric id. Provide either this or phone (exactly
            one).
          required: false
          schema:
            type: integer
            minimum: 1
            example: 12345
        - name: phone
          in: query
          description: >-
            A US phone number in any human-readable format (normalized to E.164
            server-side). Matches all prospect records sharing this number, so
            results may span more than one prospect_id.
          required: false
          schema:
            type: string
            example: (415) 555-0100
        - $ref: '#/components/parameters/ReportingLimit'
        - $ref: '#/components/parameters/ReportingPageNumber'
      responses:
        '200':
          description: Paginated leasing-event rows for the prospect.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProspectLeasingEventList'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      security:
        - BearerAuth: []
    post:
      summary: Create leasing events
      description: >
        Create one or more leasing events. Additional event types will be
        supported in future releases.


        Currently supported event types:
          - **Assign to User** — assign one or more users to a prospect. The `context` object **must** include an `assignedToUserIds` array. See `AssignToUserContext`.
          - **Application Received** — log that an application has been received from an external system. The `context` object accepts optional metadata about the external application; see `ApplicationReceivedContext`.
      operationId: postLeasingEvents
      tags:
        - Leasing Events
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostLeasingEventsRequest'
            examples:
              assignToUser:
                summary: Assign a user to a prospect
                value:
                  events:
                    - prospect_id: 12345
                      event_type: Assign to User
                      source: Other
                      notes: Assigning to Alice
                      context:
                        assignedToUserIds:
                          - 1259ef6e-61ee-42cb-b6bd-7fe547569d7c
                        applyActionInBulk: false
              applicationReceived:
                summary: Log an application received from an external system
                value:
                  events:
                    - prospect_id: 12345
                      event_type: Application Received
                      source: Automation
                      notes: Application submitted via partner portal
                      context:
                        externalApplicationId: app_abc_123
                        externalSystem: Acme PMS
                        applicantName: Jane Doe
                        applicantEmail: jane@example.com
                        applicantPhone: +1 415 555 0100
                        applicationUrl: https://acme-pms.example.com/applications/app_abc_123
                        applicationSubmittedAt: '2026-04-30T15:04:05Z'
      responses:
        '201':
          description: Leasing events created successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/LeasingEvent'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /market-tool/comps:
    get:
      summary: Get market comps
      description: >
        Retrieve normalized rental market comparables for a location, filtered

        by coordinates plus optional bed/bath/sqft/days-on-market/date criteria.

        Results are de-identified — no listing-provider references. Returns up
        to

        200 most recently active comparables; narrow the radius or filters for a

        tighter result set.


        **Billing:** each successful call incurs a **$0.50** charge to your

        account. This charge, together with the strict limit of 40 requests per

        24 hours, exists to prevent abuse of this data-intensive endpoint.
      operationId: getMarketToolComps
      tags:
        - Market Tool
      parameters:
        - name: account_id
          in: query
          description: >-
            Account to bill, as a UUID. Required only when your token can access
            more than one account; a single-account token is resolved
            automatically.
          schema:
            type: string
            format: uuid
            example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        - name: latitude
          in: query
          required: true
          description: Latitude of the search center (WGS84).
          schema:
            type: number
            minimum: -90
            maximum: 90
            example: 25.7617
        - name: longitude
          in: query
          required: true
          description: Longitude of the search center (WGS84).
          schema:
            type: number
            minimum: -180
            maximum: 180
            example: -80.1918
        - name: radius_miles
          in: query
          description: >-
            Search radius in miles (max 25). Provide this or `zipcodes` — at
            least one is required.
          schema:
            type: number
            exclusiveMinimum: 0
            maximum: 25
            example: 2
        - name: zipcodes
          in: query
          description: >-
            Comma-separated 5-digit ZIP codes (max 50). Provide this or
            `radius_miles` — at least one is required.
          schema:
            type: array
            items:
              type: string
              example: '90210'
              pattern: ^\d{5}$
            maxItems: 50
          style: form
          explode: false
          example:
            - '33101'
            - '33139'
        - name: min_beds
          in: query
          description: Minimum bedrooms.
          schema:
            type: number
            example: 2
        - name: max_beds
          in: query
          description: Maximum bedrooms.
          schema:
            type: number
            example: 4
        - name: min_baths
          in: query
          description: Minimum bathrooms.
          schema:
            type: number
            example: 1.5
        - name: max_baths
          in: query
          description: Maximum bathrooms.
          schema:
            type: number
            example: 3
        - name: min_sqft
          in: query
          description: Minimum living area in square feet.
          schema:
            type: number
            example: 800
        - name: max_sqft
          in: query
          description: Maximum living area in square feet.
          schema:
            type: number
            example: 2500
        - name: min_days_on_market
          in: query
          description: Minimum days on market.
          schema:
            type: integer
            example: 5
        - name: max_days_on_market
          in: query
          description: Maximum days on market.
          schema:
            type: integer
            example: 90
        - name: start_date
          in: query
          description: Earliest listing date (inclusive), `YYYY-MM-DD`.
          schema:
            type: string
            format: date
            example: '2026-01-01'
        - name: end_date
          in: query
          description: Latest listing date (inclusive), `YYYY-MM-DD`.
          schema:
            type: string
            format: date
            example: '2026-05-01'
      responses:
        '200':
          description: Success. Returns a list of normalized market comparables.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/MarketComp'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /marketing/listings/{accountId}:
    get:
      summary: Get marketing listings
      description: >-
        Retrieve marketing listings for a specific account. This endpoint is
        designed for embedding listings on external websites and marketing
        platforms.
      operationId: getMarketingListings
      tags:
        - Marketing
      parameters:
        - name: accountId
          in: path
          description: The account ID to retrieve listings for
          required: true
          schema:
            type: string
            format: uuid
            example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        - name: utm_source
          in: query
          description: UTM source parameter for tracking
          schema:
            type: string
            example: website_widget
        - $ref: '#/components/parameters/PaginationLimit'
        - $ref: '#/components/parameters/PaginationPage'
      responses:
        '200':
          description: Success. Returns a list of marketing listings.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/MarketingListing'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /reporting/leasing-performance/units/{unitId}:
    get:
      summary: Get unit leasing performance
      description: >
        Retrieve leasing performance metrics for a specific unit within a date
        range.


        This endpoint provides comprehensive leasing activity data including:

        - Days on market

        - Property health assessment

        - Lead volume and conversion metrics

        - Showing activity (scheduled, completed, upcoming)

        - Application metrics

        - Communication activity (texts, calls)

        - Detailed showing feedback from completed showings
      operationId: getUnitLeasingPerformance
      tags:
        - Reporting
      parameters:
        - name: unitId
          in: path
          description: ID of the unit to get leasing performance for
          required: true
          schema:
            type: integer
            example: 12345
        - name: start
          in: query
          description: Start date/time for the reporting period (ISO 8601 format)
          required: true
          schema:
            type: string
            format: date-time
            example: '2024-01-01T00:00:00Z'
        - name: end
          in: query
          description: End date/time for the reporting period (ISO 8601 format)
          required: true
          schema:
            type: string
            format: date-time
            example: '2024-01-31T23:59:59Z'
      responses:
        '200':
          description: Success. Returns leasing performance metrics for the unit.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnitLeasingPerformance'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Unit not found or no leasing performance data available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                unit-not-found:
                  value:
                    error: Unit not found
                no-data:
                  value:
                    error: No leasing performance data found
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /reporting/prospects:
    get:
      summary: List prospects report
      description: >
        Row-level prospect data backing the Intelligence dashboard's Prospects
        table,

        for the given accounts and date range.
      operationId: getReportingProspects
      tags:
        - Reporting
      parameters:
        - $ref: '#/components/parameters/ReportingAccountIds'
        - $ref: '#/components/parameters/ReportingStart'
        - $ref: '#/components/parameters/ReportingEnd'
        - $ref: '#/components/parameters/ReportingSubteamIds'
        - $ref: '#/components/parameters/ReportingMultifamilyPropertyIds'
        - $ref: '#/components/parameters/ReportingLimit'
        - $ref: '#/components/parameters/ReportingPageNumber'
      responses:
        '200':
          description: Paginated prospect report rows.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReportingProspects'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /reporting/units:
    get:
      summary: List units report
      description: >
        Row-level unit/property data backing the Intelligence dashboard's
        Properties table,

        for the given accounts and date range.
      operationId: getReportingUnits
      tags:
        - Reporting
      parameters:
        - $ref: '#/components/parameters/ReportingAccountIds'
        - $ref: '#/components/parameters/ReportingStart'
        - $ref: '#/components/parameters/ReportingEnd'
        - $ref: '#/components/parameters/ReportingSubteamIds'
        - $ref: '#/components/parameters/ReportingMultifamilyPropertyIds'
        - $ref: '#/components/parameters/ReportingLimit'
        - $ref: '#/components/parameters/ReportingPageNumber'
      responses:
        '200':
          description: Paginated unit report rows.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReportingUnits'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /reporting/showings:
    get:
      summary: List showings report
      description: >
        Row-level showing data backing the Intelligence dashboard's Showings
        table,

        for the given accounts and date range.
      operationId: getReportingShowings
      tags:
        - Reporting
      parameters:
        - $ref: '#/components/parameters/ReportingAccountIds'
        - $ref: '#/components/parameters/ReportingStart'
        - $ref: '#/components/parameters/ReportingEnd'
        - $ref: '#/components/parameters/ReportingSubteamIds'
        - $ref: '#/components/parameters/ReportingMultifamilyPropertyIds'
        - $ref: '#/components/parameters/ReportingLimit'
        - $ref: '#/components/parameters/ReportingPageNumber'
      responses:
        '200':
          description: Paginated showing report rows.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReportingShowings'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /reporting/prescreening:
    get:
      summary: List prescreening report
      description: >
        Row-level prescreening data backing the Intelligence dashboard's
        Prescreening table,

        for the given accounts and date range.
      operationId: getReportingPrescreening
      tags:
        - Reporting
      parameters:
        - $ref: '#/components/parameters/ReportingAccountIds'
        - $ref: '#/components/parameters/ReportingStart'
        - $ref: '#/components/parameters/ReportingEnd'
        - $ref: '#/components/parameters/ReportingSubteamIds'
        - $ref: '#/components/parameters/ReportingMultifamilyPropertyIds'
        - $ref: '#/components/parameters/ReportingLimit'
        - $ref: '#/components/parameters/ReportingPageNumber'
      responses:
        '200':
          description: Paginated prescreening report rows.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReportingPrescreening'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /reporting/calls:
    get:
      summary: List calls report
      description: |
        Row-level call data backing the Intelligence dashboard's Calls table,
        for the given accounts and date range.
      operationId: getReportingCalls
      tags:
        - Reporting
      parameters:
        - $ref: '#/components/parameters/ReportingAccountIds'
        - $ref: '#/components/parameters/ReportingStart'
        - $ref: '#/components/parameters/ReportingEnd'
        - $ref: '#/components/parameters/ReportingSubteamIds'
        - $ref: '#/components/parameters/ReportingMultifamilyPropertyIds'
        - $ref: '#/components/parameters/ReportingLimit'
        - $ref: '#/components/parameters/ReportingPageNumber'
      responses:
        '200':
          description: Paginated call report rows.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReportingCalls'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /reporting/marketing-sources:
    get:
      summary: List marketing sources report
      description: >
        Per-source marketing performance backing the Intelligence dashboard's
        Marketing Sources

        table, for the given accounts and date range.
      operationId: getReportingMarketingSources
      tags:
        - Reporting
      parameters:
        - $ref: '#/components/parameters/ReportingAccountIds'
        - $ref: '#/components/parameters/ReportingStart'
        - $ref: '#/components/parameters/ReportingEnd'
        - $ref: '#/components/parameters/ReportingSubteamIds'
        - $ref: '#/components/parameters/ReportingMultifamilyPropertyIds'
        - $ref: '#/components/parameters/ReportingLimit'
        - $ref: '#/components/parameters/ReportingPageNumber'
      responses:
        '200':
          description: Paginated marketing-source report rows.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReportingMarketingSources'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /reporting/applications:
    get:
      summary: List applications report
      description: >
        Row-level application-group data backing the Intelligence dashboard's
        Applications table,

        for the given accounts and date range.
      operationId: getReportingApplications
      tags:
        - Reporting
      parameters:
        - $ref: '#/components/parameters/ReportingAccountIds'
        - $ref: '#/components/parameters/ReportingStart'
        - $ref: '#/components/parameters/ReportingEnd'
        - $ref: '#/components/parameters/ReportingSubteamIds'
        - $ref: '#/components/parameters/ReportingMultifamilyPropertyIds'
        - $ref: '#/components/parameters/ReportingLimit'
        - $ref: '#/components/parameters/ReportingPageNumber'
      responses:
        '200':
          description: Paginated application report rows.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReportingApplications'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /reporting/agent-performance:
    get:
      summary: List agent performance report
      description: >
        Per-agent performance metrics backing the Intelligence dashboard's Agent
        Performance

        table, for the given accounts and date range.
      operationId: getReportingAgentPerformance
      tags:
        - Reporting
      parameters:
        - $ref: '#/components/parameters/ReportingAccountIds'
        - $ref: '#/components/parameters/ReportingStart'
        - $ref: '#/components/parameters/ReportingEnd'
        - $ref: '#/components/parameters/ReportingSubteamIds'
        - $ref: '#/components/parameters/ReportingMultifamilyPropertyIds'
        - $ref: '#/components/parameters/ReportingLimit'
        - $ref: '#/components/parameters/ReportingPageNumber'
      responses:
        '200':
          description: Paginated agent-performance report rows.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReportingAgentPerformance'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /calls:
    get:
      summary: List a prospect's calls
      description: >-
        Retrieve a prospect's call history (newest first), by prospect_id or
        phone (supply exactly one).
      operationId: getProspectCalls
      tags:
        - Calls
      parameters:
        - $ref: '#/components/parameters/ReportingAccountIds'
        - name: prospect_id
          in: query
          description: >-
            The prospect's numeric id. Provide either this or phone (exactly
            one).
          required: false
          schema:
            type: integer
            minimum: 1
            example: 12345
        - name: phone
          in: query
          description: >-
            A US phone number in any human-readable format (normalized to E.164
            server-side). Matches all prospect records sharing this number, so
            results may span more than one prospect_id.
          required: false
          schema:
            type: string
            example: (415) 555-0100
        - $ref: '#/components/parameters/ReportingLimit'
        - $ref: '#/components/parameters/ReportingPageNumber'
      responses:
        '200':
          description: Paginated call rows for the prospect.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProspectCallList'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      security:
        - BearerAuth: []
  /messages:
    get:
      summary: List a prospect's messages
      description: >-
        Retrieve a prospect's SMS history (newest first), by prospect_id or
        phone (supply exactly one).
      operationId: getProspectMessages
      tags:
        - Messages
      parameters:
        - $ref: '#/components/parameters/ReportingAccountIds'
        - name: prospect_id
          in: query
          description: >-
            The prospect's numeric id. Provide either this or phone (exactly
            one).
          required: false
          schema:
            type: integer
            minimum: 1
            example: 12345
        - name: phone
          in: query
          description: >-
            A US phone number in any human-readable format (normalized to E.164
            server-side). Matches all prospect records sharing this number, so
            results may span more than one prospect_id.
          required: false
          schema:
            type: string
            example: (415) 555-0100
        - $ref: '#/components/parameters/ReportingLimit'
        - $ref: '#/components/parameters/ReportingPageNumber'
      responses:
        '200':
          description: Paginated message rows for the prospect.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProspectMessageList'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      security:
        - BearerAuth: []
  /rental_application_groups:
    get:
      summary: List rental application groups
      description: >
        Retrieve rental application groups with filters, sorting, and
        pagination. Each group

        represents a single party applying to a unit and bundles one or more
        applicants.

        The response embeds a non-PII summary for each applicant including
        screening status.


        For the full applicant record including PII (personal details, income,
        address history),

        fetch the individual applicant via `GET /rental_applications/{id}`.
      operationId: listRentalApplicationGroups
      tags:
        - Rental Applications
      parameters:
        - name: id
          in: query
          description: Filter by one or more rental application group IDs (comma-separated)
          schema:
            type: array
            items:
              type: string
              example: 123e4567-e89b-12d3-a456-426614174000
              format: uuid
          style: form
          explode: false
          example:
            - 123e4567-e89b-12d3-a456-426614174000
            - 223e4567-e89b-12d3-a456-426614174111
        - name: account_id
          in: query
          description: Filter by account ID (via the associated unit)
          schema:
            type: string
            example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
            format: uuid
          example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        - name: subteam_id
          in: query
          description: Filter by subteam ID (via the associated unit)
          schema:
            type: string
            example: 123e4567-e89b-12d3-a456-426614174000
            format: uuid
        - name: unit_id
          in: query
          description: Filter by one or more unit IDs (comma-separated)
          schema:
            type: array
            items:
              type: integer
              example: 123
          style: form
          explode: false
          example:
            - 12345
            - 67890
        - name: status
          in: query
          description: Filter by one or more application group statuses (comma-separated)
          schema:
            type: array
            items:
              $ref: '#/components/schemas/RentalApplicationStatus'
          style: form
          explode: false
          example:
            - Submitted
            - Approved
        - name: created_after
          in: query
          description: Only include groups created at or after this ISO-8601 datetime
          schema:
            type: string
            example: '2026-01-01T00:00:00Z'
            format: date-time
          example: '2026-01-01T00:00:00Z'
        - name: created_before
          in: query
          description: Only include groups created at or before this ISO-8601 datetime
          schema:
            type: string
            example: '2024-01-15T09:30:00Z'
            format: date-time
        - name: updated_after
          in: query
          description: Only include groups updated at or after this ISO-8601 datetime
          schema:
            type: string
            example: '2024-01-15T09:30:00Z'
            format: date-time
        - name: updated_before
          in: query
          description: Only include groups updated at or before this ISO-8601 datetime
          schema:
            type: string
            example: '2024-01-15T09:30:00Z'
            format: date-time
        - name: sort
          in: query
          description: Field to sort by
          schema:
            type: string
            example: created_at
            enum:
              - created_at
              - updated_at
              - status
            default: created_at
        - name: direction
          in: query
          description: Sort direction
          schema:
            type: string
            example: asc
            enum:
              - asc
              - desc
            default: desc
        - $ref: '#/components/parameters/PaginationLimit'
        - $ref: '#/components/parameters/PaginationPage'
      responses:
        '200':
          description: Paginated list of rental application groups.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedRentalApplicationGroups'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /rental_application_groups/{id}:
    get:
      summary: Get a rental application group
      description: >
        Retrieve a single rental application group with its applicants (non-PII
        summary),

        screening status for each applicant, and the full decision history.
      operationId: getRentalApplicationGroup
      tags:
        - Rental Applications
      parameters:
        - name: id
          in: path
          required: true
          description: Rental application group ID
          schema:
            type: string
            example: 123e4567-e89b-12d3-a456-426614174000
            format: uuid
      responses:
        '200':
          description: The rental application group.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RentalApplicationGroupDetail'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /rental_applications/{id}:
    get:
      summary: Get a rental application
      description: >
        Retrieve a single rental application (applicant record) with all data
        broken out

        and structured, including PII (personal details, income, address
        history, co-applicants,

        pets, vehicles, custom questions). Includes a `documents` array with
        opaque

        `document_id` values that can be passed to

        `GET /rental_applications/{id}/documents/{documentId}` to stream the
        actual file bytes.


        Access is gated by the authenticated user's permissions on the
        underlying account.


        **Rate limit:** Strict tier — 2 req/s (10 per 5 seconds).
      operationId: getRentalApplication
      tags:
        - Rental Applications
      parameters:
        - name: id
          in: path
          required: true
          description: Rental application ID
          schema:
            type: string
            example: 123e4567-e89b-12d3-a456-426614174000
            format: uuid
      responses:
        '200':
          description: The rental application with PII and document listing.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RentalApplication'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /rental_applications/{id}/documents/{documentId}:
    get:
      summary: Download a rental application document
      description: >
        Stream the raw bytes of a document associated with a rental application.


        The `documentId` is an opaque encrypted identifier returned by

        `GET /rental_applications/{id}` on each entry in the `documents` array.

        It identifies which underlying artifact to fetch — an applicant-uploaded
        file,

        a TransUnion screening report (credit / criminal / eviction), or an ID

        verification artifact (front / back / selfie). A fresh `documentId` is
        minted

        on every detail fetch, so the same document yields a different value
        each

        time — do not cache by this id.


        Response `Content-Type` reflects the underlying document (typically

        `application/pdf` for screening reports, `image/jpeg` for ID artifacts,

        and the original MIME type for applicant uploads). By default the

        `Content-Disposition` is `inline`; pass `?download=true` to force

        `attachment` for a browser download prompt.


        **Rate limit:** Strict tier — 2 req/s (10 per 5 seconds).
      operationId: getRentalApplicationDocument
      tags:
        - Rental Applications
      parameters:
        - name: id
          in: path
          required: true
          description: Rental application ID
          schema:
            type: string
            example: 123e4567-e89b-12d3-a456-426614174000
            format: uuid
        - name: documentId
          in: path
          required: true
          description: >-
            Opaque document identifier from the `documents` array on the rental
            application
          schema:
            type: string
            example: >-
              a9J7gI7Gc0Yo9CFhDg5-m9SpMKrUiNKDp5DbpgNiYdp9hzwoKDRwDArG57jwqrdJ9DTHll_M3fxAu_qKmcf66Odvt62turHgBRVGqW31ebJWIKsnrM3b-ys2B4ellJII
        - name: download
          in: query
          required: false
          description: >-
            When true, responds with `Content-Disposition: attachment` to
            trigger a browser download
          schema:
            type: boolean
            example: false
            default: false
      responses:
        '200':
          description: The document bytes.
          headers:
            Content-Type:
              description: MIME type of the underlying document
              schema:
                type: string
                example: application/pdf
            Content-Disposition:
              description: Either `inline; filename="..."` or `attachment; filename="..."`
              schema:
                type: string
                example: inline; filename="transunion_credit_report.pdf"
            Content-Length:
              schema:
                type: integer
                example: 1024
          content:
            '*/*':
              schema:
                type: string
                example: <binary file contents>
                format: binary
                description: >
                  Raw bytes of the underlying document. The actual MIME type is

                  returned in the `Content-Type` response header. Typical
                  values:

                  `application/pdf` for TransUnion screening reports,

                  `image/jpeg` for ID verification artifacts, and the original

                  upload MIME type for applicant-uploaded documents (which can

                  be any of png, jpeg, pdf, heic, webp, etc.).
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: >-
            The rental application or the requested document could not be found,
            or the caller does not have access.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
  /rental_applications/{id}/income:
    get:
      summary: Get a rental application's submitted income
      description: >
        Retrieve the applicant's **submitted income**, computed exactly as the

        Household / Applicant Summary does — the average of every present income

        source (income documents, payroll connection, bank connection) at its
        raw

        OCR / provider amount. No income is excluded for fraud or name/DOB

        mismatch; every present source with a positive amount contributes.


        This is a secondary sub-resource kept separate from

        `GET /rental_applications/{id}` because computing payroll/bank income

        requires live provider fetches. Each source is returned both as a

        summary total and with the underlying per-document / per-employment /

        per-account detail shown on screen.


        Income document PDFs are downloadable: each entry in

        `sources.documents.items` carries a `document_id` — pass it to

        `GET /rental_applications/{id}/documents/{documentId}` to stream the

        file bytes. A fresh `document_id` is minted on every call, so do not

        cache by this id.


        Identity data is minimized: SSN is returned as the last four digits

        only (`ssn_last4`), and payroll date of birth / home address are not

        included. Bank account numbers are likewise returned as the last four

        digits only. Access is controlled by the API token.


        **Rate limit:** Strict tier — 2 req/s (10 per 5 seconds).
      operationId: getRentalApplicationIncome
      tags:
        - Rental Applications
      parameters:
        - name: id
          in: path
          required: true
          description: Rental application ID
          schema:
            type: string
            example: 123e4567-e89b-12d3-a456-426614174000
            format: uuid
      responses:
        '200':
          description: The applicant's submitted income with per-source detail.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RentalApplicationIncome'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - BearerAuth: []
components:
  schemas:
    RentalApplicationIncome:
      type: object
      description: >-
        An applicant's submitted income, computed like the Household / Applicant
        Summary (average of every present source at its raw amount; no
        fraud/mismatch exclusion), with per-source detail.
      properties:
        rental_application_id:
          type: string
          example: 123e4567-e89b-12d3-a456-426614174000
          format: uuid
        submitted_monthly_income:
          type: number
          description: >-
            The headline figure — the average of the applicant's present income
            sources (documents / payroll / bank), each counted only when it
            reports a positive amount. `0` when no source reports income.
          example: 5087.74
        self_reported_monthly_income:
          type: number
          description: >-
            Monthly income the applicant entered themselves (from
            `income_details`).
          example: 4500
        sources:
          type: object
          properties:
            documents:
              type: object
              description: Income derived from applicant-uploaded documents (OCR).
              properties:
                monthly_income:
                  type:
                    - number
                    - 'null'
                  description: >-
                    De-duplicated total across document sources; `null` when
                    there is no document income.
                  example: 5087.74
                breakdown:
                  type: array
                  description: >-
                    Per-source rollup (de-duplicated by employer/account), as
                    shown on the summary card.
                  items:
                    $ref: '#/components/schemas/IncomeDocumentBreakdownSource'
                items:
                  type: array
                  description: >-
                    Per-document detail, one entry per completed income
                    document.
                  items:
                    $ref: '#/components/schemas/IncomeDocumentItem'
            payroll:
              oneOf:
                - $ref: '#/components/schemas/PayrollIncome'
                - type: 'null'
              description: >-
                Payroll-connection income (Argyle VOIE); `null` when no payroll
                report exists.
            bank:
              oneOf:
                - $ref: '#/components/schemas/BankIncome'
                - type: 'null'
              description: >-
                Bank-connection income (Argyle open banking); `null` when no
                bank report exists.
    IncomeDocumentBreakdownSource:
      type: object
      description: A de-duplicated income source rolled up from one or more documents.
      properties:
        source_key:
          type: string
          example: doordash
        doc_type:
          type: string
          example: paystub
        display_name:
          type: string
          example: DoorDash
        monthly_income:
          type: number
          example: 5087.74
        document_count:
          type: integer
          example: 2
    IncomeDocumentItem:
      type: object
      description: A single completed income document with the fields shown on its card.
      properties:
        document_id:
          type:
            - string
            - 'null'
          description: >-
            Opaque, encrypted id for downloading this PDF via `GET
            /rental_applications/{id}/documents/{documentId}`. Minted fresh per
            call — do not cache. `null` if the document is no longer a listed
            application document.
          example: >-
            a9J7gI7Gc0Yo9CFhDg5-m9SpMKrUiNKDp5DbpgNiYdp9hzwoKDRwDArG57jwqrdJ9DTHll_M3fxAu_qKmcf66Odvt62turHgBRVGqW31ebJWIKsnrM3b-ys2B4ellJII
        document_type:
          type: string
          enum:
            - paystub
            - w2
            - bank_statement
            - '1099'
            - '1040'
            - tax_return
            - employment_letter
            - unknown
          example: paystub
        status:
          type: string
          example: completed
        applicant_name:
          type:
            - string
            - 'null'
          description: >-
            Name extracted from this document (may differ per document; useful
            for mismatch detection).
          example: Ada Lovelace
        computed_monthly_income:
          type:
            - number
            - 'null'
          description: >-
            The card's "Est. Monthly" value derived from this document; `null`
            when it can't be computed.
          example: 5087.74
        income_basis:
          type: string
          example: gross
          enum:
            - gross
            - net
        details:
          type: object
          additionalProperties: true
          description: >
            Fields specific to `document_type`, mirroring that document's info
            card:

            - **paystub**: `employer_name`, `pay_frequency`, `pay_period_start`,
            `pay_period_end`, `gross_pay_current`, `net_pay_current`,
            `gross_pay_ytd`, `hourly_rate`

            - **w2**: `employer_name`, `employer_ein`, `tax_year`,
            `wages_tips_compensation`, `federal_tax_withheld`,
            `social_security_wages`, `medicare_wages`, `state_tax_withheld`

            - **bank_statement**: `bank_name`, `account_last4`,
            `statement_period_start`, `statement_period_end`, `opening_balance`,
            `closing_balance`, `total_deposits`, `total_withdrawals`,
            `payroll_deposits[]` (`date`, `description`, `amount`)

            - **employment_letter**: `employer_name`, `position_title`,
            `employment_status`, `annual_salary`, `hourly_rate`,
            `pay_frequency`, `employment_start_date`, `letter_date`,
            `signatory_name`, `signatory_title`

            - **1040 / tax_return**: `tax_year`, `filing_status`, `ssn_last4`,
            `spouse_name`, `spouse_ssn_last4`, `total_income`,
            `adjusted_gross_income`, `total_tax`

            - **1099**: `payer_name`, `form_variant`, `tax_year`,
            `gross_income`, `nonemployee_compensation`, `federal_tax_withheld`
    PayrollIncome:
      type: object
      description: Income from a connected payroll provider (Argyle VOIE).
      properties:
        status:
          type: string
          enum:
            - ok
            - error
          description: >
            `ok` when the payroll report was fetched successfully. `error` when
            a

            report exists but its data couldn't be retrieved — it may still be

            generating, or the fetch timed out / errored. `monthly_income` is
            then

            0, the detail is empty, and this source did NOT contribute to

            `submitted_monthly_income`.
          example: ok
        monthly_income:
          type: number
          description: Total monthly income across all employments.
          example: 5000
        employments:
          type: array
          items:
            $ref: '#/components/schemas/PayrollEmployment'
        income_totals:
          type: array
          description: Income totals by year.
          items:
            $ref: '#/components/schemas/PayrollIncomePeriod'
    PayrollEmployment:
      type: object
      properties:
        employer:
          type:
            - string
            - 'null'
          example: Acme Corp
        job_title:
          type:
            - string
            - 'null'
          example: Software Engineer
        status:
          type:
            - string
            - 'null'
          example: active
        employment_type:
          type:
            - string
            - 'null'
          example: full_time
        pay_cycle:
          type:
            - string
            - 'null'
          example: biweekly
        start_date:
          type:
            - string
            - 'null'
          example: '2024-01-01'
        end_date:
          type:
            - string
            - 'null'
          description: >-
            `null` while the applicant is still employed there, as in this
            sample.
          example: null
        length_of_work:
          type:
            - object
            - 'null'
          properties:
            years:
              type:
                - string
                - 'null'
              example: '2'
            months:
              type:
                - string
                - 'null'
              example: '6'
        monthly_income:
          type:
            - number
            - 'null'
          example: 5000
        base_pay:
          type:
            - object
            - 'null'
          properties:
            amount:
              type:
                - string
                - 'null'
              example: '60000'
            period:
              type:
                - string
                - 'null'
              example: annual
        last_paystub_date:
          type:
            - string
            - 'null'
          example: '2026-07-15'
        full_name:
          type:
            - string
            - 'null'
          example: Ada Lovelace
        email:
          type:
            - string
            - 'null'
          example: ada@example.com
        phone_number:
          type:
            - string
            - 'null'
          example: '5551234567'
        ssn_last4:
          type:
            - string
            - 'null'
          description: Last four digits of the SSN. The full number is never returned.
          example: '6789'
        income:
          type: array
          description: Per-period income history.
          items:
            $ref: '#/components/schemas/PayrollIncomePeriod'
    PayrollIncomePeriod:
      type: object
      properties:
        period:
          type:
            - string
            - 'null'
          description: The period these figures cover, as the provider labels it.
          example: '2025'
        gross_pay:
          type:
            - string
            - 'null'
          example: '60000'
        deductions:
          type:
            - string
            - 'null'
          example: '3600'
        taxes:
          type:
            - string
            - 'null'
          example: '6000'
        net_pay:
          type:
            - string
            - 'null'
          example: '50400'
    BankIncome:
      type: object
      description: Income from a connected bank (Argyle open banking).
      properties:
        status:
          type: string
          enum:
            - ok
            - error
          description: >
            `ok` when the bank report was fetched successfully. `error` when a

            report exists but its data couldn't be retrieved — it may still be

            generating, or the fetch timed out / errored. `monthly_income` is
            then

            0, the detail is empty, and this source did NOT contribute to

            `submitted_monthly_income`.
          example: ok
        monthly_income:
          type: number
          description: Total average monthly income across active income streams.
          example: 4200
        assets:
          type:
            - object
            - 'null'
          description: Report-level balances across every connected account.
          properties:
            current_balance:
              type:
                - number
                - 'null'
              example: 5000
            two_month_average:
              type:
                - number
                - 'null'
              example: 4700
            six_month_average:
              type:
                - number
                - 'null'
              example: 4600
            beginning_balance:
              type:
                - number
                - 'null'
              example: 4000
        accounts:
          type: array
          items:
            $ref: '#/components/schemas/BankAccount'
    BankAccount:
      type: object
      properties:
        institution_name:
          type:
            - string
            - 'null'
          example: Chase
        account_name:
          type:
            - string
            - 'null'
          example: Checking
        account_last4:
          type:
            - string
            - 'null'
          description: Last four digits of the account number only.
          example: '1234'
        type:
          type:
            - string
            - 'null'
          example: checking
        currency:
          type:
            - string
            - 'null'
          example: USD
        current_balance:
          type:
            - number
            - 'null'
          example: 5000
        two_month_average:
          type:
            - number
            - 'null'
          example: 4700
        six_month_average:
          type:
            - number
            - 'null'
          example: 4600
        beginning_balance:
          type:
            - number
            - 'null'
          example: 4000
        average_monthly_balance:
          type:
            - number
            - 'null'
          example: 4800
        owner_name:
          type:
            - string
            - 'null'
          example: Ada Lovelace
        income_streams:
          type: array
          items:
            $ref: '#/components/schemas/BankIncomeStream'
    BankIncomeStream:
      type: object
      properties:
        name:
          type:
            - string
            - 'null'
          example: ACME PAYROLL
        status:
          type:
            - string
            - 'null'
          description: '"ACTIVE" or "INACTIVE".'
          example: ACTIVE
        average_monthly_income_net:
          type:
            - number
            - 'null'
          example: 4200
        confidence:
          type:
            - number
            - 'null'
          description: Provider-reported confidence in this stream, on a 0-to-100 scale.
          example: 95
        estimate_inclusion:
          type:
            - string
            - 'null'
          description: >-
            How the provider rated this stream for inclusion in its own
            estimate, passed through verbatim.
          example: HIGH
        cadence:
          type:
            - object
            - 'null'
          properties:
            days:
              type:
                - number
                - 'null'
              description: Days between deposits.
              example: 14
            start_date:
              type:
                - string
                - 'null'
              example: '2025-01-15T12:00:00.000Z'
            stop_date:
              type:
                - string
                - 'null'
              description: '`null` while the stream is still active, as in this sample.'
              example: null
        net_monthly:
          type: array
          description: Per-month net income history.
          items:
            type: object
            properties:
              month:
                type:
                  - string
                  - 'null'
                description: The first of the month, as an ISO-8601 timestamp.
                example: '2026-06-01T06:00:00.000Z'
              net:
                type:
                  - number
                  - 'null'
                example: 4200
    MarketComp:
      type: object
      description: >-
        A normalized, provider-free rental market comparable. Contains no
        listing-provider identifiers or references.
      properties:
        address:
          type: string
          example: 123 Main St, Miami, FL
        beds:
          type: number
          example: 2
        baths:
          type: number
          example: 2
        sqft:
          type: number
          description: Living area in square feet.
          example: 1100
        rent:
          type: number
          description: Latest asking or rented price.
          example: 2400
        days_on_market:
          type: integer
          example: 12
        date_rented:
          type: string
          format: date
          description: Date the unit was rented; null while still available.
          example: '2025-03-15'
        features:
          type: array
          items:
            type: string
            example: Pool
          description: Human-readable feature labels.
          example:
            - Pool
            - In-unit laundry
        status:
          type: string
          enum:
            - available
            - rented
          example: available
        latitude:
          type: number
          example: 25.7617
        longitude:
          type: number
          example: -80.1918
        property_type:
          type: string
          description: >-
            Friendly property type (e.g. "Single Family", "Apartment", "Condo",
            "Townhouse", "Multi-Family", "Manufactured"). Null when unknown.
          example: Single Family
        image:
          type: string
          description: >-
            Listing photo URL routed through the RentEngine image proxy. Null
            when no photo is available.
          example: >-
            https://imageproxy.rentengine.io/jpeg/aHR0cHM6Ly9leGFtcGxlLmNvbS9waG90by5qcGc
        zipcode:
          type: string
          example: '33101'
        furnished:
          type: boolean
          description: Whether the unit is furnished; null when unknown.
          example: false
        in_apartment_complex:
          type: boolean
          description: Whether the unit is part of an apartment complex; null when unknown.
          example: true
        num_parking_spots:
          type: integer
          description: Number of parking spaces; null when unknown.
          example: 1
        description:
          type: string
          description: >-
            Listing description with all third-party rental-platform references
            removed. May be null or shortened when the original text consisted
            mostly of provider mentions.
          example: Bright 2-bed with in-unit laundry. Walk to the park.
    UnitLeasingPerformance:
      type: object
      description: Leasing performance metrics for a unit
      properties:
        unit_id:
          type: integer
          description: ID of the unit
          example: 12345
        days_on_market:
          type:
            - integer
            - 'null'
          description: Number of days the unit has been on the market
          example: 45
        property_health:
          type: string
          description: Overall health assessment of the property listing
          enum:
            - Off-Market
            - Healthy
            - At-risk
            - On Hold
            - Waitlist
            - Commercial
            - Unknown
          example: Healthy
        benchmark_leads_since_last_price_change:
          type: integer
          description: >-
            Expected number of leads based on bedroom count and time since last
            price change
          example: 12
        new_prospects:
          type: integer
          description: Number of new prospects in the reporting period
          example: 15
        showings_scheduled:
          type: integer
          description: Number of showings scheduled in the reporting period
          example: 8
        showings_completed:
          type: integer
          description: Number of showings completed in the reporting period
          example: 6
        applications_requested:
          type: integer
          description: Number of applications requested in the reporting period
          example: 3
        applications_submitted:
          type: integer
          description: Number of applications submitted in the reporting period
          example: 2
        active_prospects:
          type: integer
          description: >-
            Number of active (non-terminal status) prospects in the reporting
            period
          example: 5
        upcoming_showings:
          type: integer
          description: Number of upcoming scheduled showings
          example: 2
        outbound_texts:
          type: integer
          description: Number of outbound text messages sent in the reporting period
          example: 25
        total_calls:
          type: integer
          description: Total number of calls in the reporting period
          example: 10
        showing_feedback:
          type: array
          description: Feedback from completed showings in the reporting period
          items:
            $ref: '#/components/schemas/ShowingFeedbackItem'
      required:
        - unit_id
        - days_on_market
        - property_health
        - benchmark_leads_since_last_price_change
        - new_prospects
        - showings_scheduled
        - showings_completed
        - applications_requested
        - applications_submitted
        - active_prospects
        - upcoming_showings
        - outbound_texts
        - total_calls
        - showing_feedback
    ShowingFeedbackItem:
      type: object
      description: Feedback from a completed showing
      properties:
        prospect_id:
          type: integer
          description: ID of the prospect who attended the showing
          example: 789
        prospect_name:
          type: string
          description: Name of the prospect
          example: John Doe
        created_at:
          type: string
          format: date-time
          description: When the showing was completed
          example: '2024-01-15T14:30:00Z'
        feedback:
          type:
            - string
            - 'null'
          description: Feedback notes from the showing
          example: Prospect liked the kitchen but concerned about parking availability
      required:
        - prospect_id
        - prospect_name
        - created_at
        - feedback
    Error:
      type: object
      properties:
        error:
          type: string
          description: Error message
          example: Invalid request parameters
        details:
          type: array
          items:
            type: object
          description: Detailed error information
          example:
            - keyword: required
              dataPath: ''
              schemaPath: '#/required'
              params:
                missingProperty: account_id
              message: should have required property 'account_id'
      required:
        - error
    MarketingListing:
      type: object
      description: Marketing listing data formatted for external display and embedding
      properties:
        id:
          type: string
          description: Unique identifier for the listing
          example: '12345'
        email:
          type: string
          description: Contact email for the listing
          example: leasing@example.com
        phone:
          type: string
          description: Contact phone number (digits only)
          example: '5551234567'
        propertyType:
          type: string
          description: Type of property
          example: Single Family
          enum:
            - Single Family
            - Duplex
            - Apartment Unit
            - Condo Unit
            - Townhouse
            - ADU
            - Room
            - Commercial Office
            - Commercial Retail
            - Commercial Industrial
            - Garage
        companyName:
          type: string
          description: Name of the property management company
          example: ABC Property Management
        address:
          type: string
          description: Formatted address
          example: '123 Main St #2'
        city:
          type: string
          description: City name
          example: San Francisco
        state:
          type: string
          description: Full state name
          example: California
        zip:
          type: string
          description: ZIP code
          example: '94111'
        title:
          type: string
          description: Marketing title for the listing
          example: Beautiful 3BR Home in Prime Location
        description:
          type: string
          description: Marketing description of the property
          example: Spacious 3 bedroom home with modern amenities...
        beds:
          type: string
          description: Number of bedrooms
          example: '3'
        baths:
          type: string
          description: Number of bathrooms
          example: '2'
        dateAvailable:
          type: string
          description: Date the property is available for move-in
          example: 1/15/2024
        rentAmount:
          type: string
          description: Monthly rent amount in dollars
          example: '2500.23'
        depositAmount:
          type: string
          description: Security deposit amount in dollars
          example: '2500.23'
        squareFootage:
          type: string
          description: Square footage of the property
          example: '1500'
        latitude:
          type:
            - number
            - 'null'
          description: Latitude coordinate
          example: 37.7749
        longitude:
          type:
            - number
            - 'null'
          description: Longitude coordinate
          example: -122.4194
        applicationFee:
          type: string
          description: Application fee amount in dollars
          example: '50'
        leaseProcessingFee:
          type: string
          description: Total lease processing/move-in fees in dollars
          example: '150.00'
        isFurnished:
          type: boolean
          description: Whether the property is furnished
          example: false
        dogs:
          type: boolean
          description: Whether dogs are allowed
          example: true
        cats:
          type: boolean
          description: Whether cats are allowed
          example: true
        applyUrl:
          type: string
          description: URL to apply for the listing
          example: https://rentengine.io/listings/12345
        btnUrl:
          type: string
          description: URL for the schedule showing button
          example: https://app.rentengine.io/ss/12345
        btnText:
          type: string
          description: Text for the call-to-action button
          example: Schedule a Showing
        waitlistIcon:
          type: string
          description: Icon identifier for waitlist status
          example: snooze
        waitlistLabel:
          type: string
          description: Label for waitlist status
          example: Wait List
        waitlistTurnOffDate:
          type: string
          description: Date when waitlist status ends
          example: '2024-02-01'
        virtualTour:
          type:
            - string
            - 'null'
          description: URL for virtual tour video
          example: https://www.youtube.com/watch?v=abc123
        pmName:
          type: string
          description: Property manager name
          example: ABC Property Management
        pmEmail:
          type: string
          description: Property manager email
          example: pm@example.com
        pmPhone:
          type: string
          description: Property manager phone (digits only)
          example: '5551234567'
        externalId:
          type: string
          description: External system identifier
          example: EXT-12345
        propertyGroup:
          type:
            - string
            - 'null'
          description: Property group identifier
          example: null
        leaseDescription:
          type: string
          description: Description of lease terms
          example: 12 months
        moveInFees:
          type: array
          description: One-time fees required at move-in
          items:
            type: object
            properties:
              name:
                type: string
                description: Name of the fee
                example: Admin Fee
              amount:
                type: number
                description: Fee amount (dollar value or percentage based on type)
                example: 150
              type:
                type: string
                enum:
                  - percent
                  - dollar
                description: >-
                  Whether the amount is a fixed dollar value or percentage of
                  rent
                example: dollar
          example:
            - name: Admin Fee
              amount: 150
              type: dollar
        monthlyFees:
          type: array
          description: Recurring monthly fees in addition to rent
          items:
            type: object
            properties:
              name:
                type: string
                description: Name of the fee
                example: Pet Fee
              amount:
                type: number
                description: Fee amount (dollar value or percentage based on type)
                example: 50
              type:
                type: string
                enum:
                  - percent
                  - dollar
                description: >-
                  Whether the amount is a fixed dollar value or percentage of
                  rent
                example: dollar
          example:
            - name: Pet Fee
              amount: 50
              type: dollar
        specials:
          type: array
          description: >-
            Move-in specials and promotional offers. Combines specials from the
            unit, floorplan, and multifamily property (if applicable). Expired
            specials are filtered out. When end_date is omitted, the special has
            no end date (ongoing). Public listing pages should conditionally
            show the date range only when end_date is present.
          items:
            type: object
            properties:
              description:
                type: string
                description: Description of the special offer
                example: First month free!
              start_date:
                type: string
                format: date
                description: Start date of the special offer (YYYY-MM-DD)
                example: '2024-01-01'
              end_date:
                type: string
                format: date
                description: >-
                  Optional. End date of the special offer (YYYY-MM-DD). When
                  omitted, the special has no end date (ongoing).
                example: '2024-03-31'
          example:
            - description: First month free!
              start_date: '2024-01-01'
              end_date: '2024-03-31'
            - description: $500 off move-in costs
              start_date: '2024-01-15'
        photos:
          type: array
          description: Array of photo URLs
          items:
            type: string
            example: https://storage.example.com/images/photo1.jpg
          example:
            - https://storage.example.com/images/photo1.jpg
            - https://storage.example.com/images/photo2.jpg
      required:
        - id
        - propertyType
        - address
        - city
        - state
        - zip
        - beds
        - baths
        - rentAmount
        - photos
    Lockbox:
      type: object
      properties:
        id:
          $ref: '#/components/schemas/UuidProperty'
        lockbox_type:
          $ref: '#/components/schemas/LockboxTypeValue'
        serial_number:
          type: string
          description: Serial number of the lockbox
          example: '1234567'
        account_id:
          type: string
          description: ID of the account that owns the lockbox
          example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        created_at:
          type: string
          format: date-time
          description: Timestamp when the lockbox was created
          example: '2023-01-15T12:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: Timestamp when the lockbox was last updated
          example: '2023-01-16T14:30:00Z'
      required:
        - id
        - lockbox_type
        - serial_number
        - account_id
        - created_at
        - updated_at
    PostLockboxesRequest:
      type: object
      properties:
        lockbox_type:
          type: string
          enum:
            - Sentrilock
          description: Type of lockbox (currently only SentriLock is supported)
          example: Sentrilock
        serial_numbers:
          type: array
          items:
            type: string
            example: '1234567'
          minItems: 1
          maxItems: 100
          description: List of serial numbers for the lockboxes to create
          example:
            - '1234567'
            - '7654321'
        account_id:
          type: string
          description: ID of the account to associate with the lockboxes
          example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
      required:
        - lockbox_type
        - serial_numbers
        - account_id
    PostLockboxTransferAccountsRequest:
      type: object
      properties:
        lockbox_ids:
          type: array
          items:
            type: string
            example: 123e4567-e89b-12d3-a456-426614174000
            format: uuid
          minItems: 1
          description: List of lockbox IDs to be transferred to the new account
          example:
            - 123e4567-e89b-12d3-a456-426614174000
            - 123e4567-e89b-12d3-a456-426614174001
        new_account_id:
          type: string
          format: uuid
          description: ID of the account to which the lockboxes should be transferred
          example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
      required:
        - lockbox_ids
        - new_account_id
    LockboxTypeValue:
      type: string
      description: Lockbox hardware/provider type
      enum:
        - Codebox
        - Sentrilock
        - IglooWorks
        - eRentalLock
        - PointCentral
        - Master Lock
        - Rently
        - TTLock
      example: Sentrilock
    LockboxEventType:
      type: string
      description: Type of lockbox event
      enum:
        - Install
        - Activate
        - Deactivate
        - Uninstall
        - Generate Code
      example: Install
    LockboxEvent:
      type: object
      description: |
        A single lockbox lifecycle event. There is no `account_id` on the event
        itself; the owning account is reached through the embedded `lockbox`
        object, which also carries the lockbox's `serial_number`.
      properties:
        id:
          $ref: '#/components/schemas/UuidProperty'
        lockbox_id:
          type: string
          format: uuid
          description: ID of the lockbox this event belongs to
          example: 123e4567-e89b-12d3-a456-426614174000
        event_type:
          $ref: '#/components/schemas/LockboxEventType'
        unit_id:
          type:
            - integer
            - 'null'
          description: |
            Unit the event relates to. Null for events recorded against a
            building rather than a unit (see `multifamily_property_id`), and for
            lockboxes not currently assigned to a unit.
          example: 12345
        multifamily_property_id:
          type:
            - string
            - 'null'
          format: uuid
          description: Building the event relates to, when it is not unit-scoped
          example: 123e4567-e89b-12d3-a456-426614174000
        created_by:
          type:
            - string
            - 'null'
          format: uuid
          description: |
            Auth user who caused the event. Null for events created by an
            automated process rather than a person.
          example: 123e4567-e89b-12d3-a456-426614174000
        created_at:
          type: string
          format: date-time
          description: Timestamp when the event occurred
          example: '2023-01-15T12:30:00Z'
        data:
          type:
            - object
            - 'null'
          description: |
            Event-specific payload. The shape varies by `event_type` and is not
            guaranteed stable.

            SENSITIVE: for `Generate Code` events this contains the lockbox
            access code in plain text (`data.code`), alongside `date`,
            `codeType` (e.g. ACCESS, INSTALL) and `createdFor`. Treat responses
            from this endpoint as containing physical access credentials and
            handle them accordingly. `Deactivate` events instead carry
            provider metadata such as `provider`, `kind` and `reason`.
          example:
            code: '8594'
            codeType: ACCESS
            date: '2024-11-26T16:45:26.067Z'
        lockbox:
          type:
            - object
            - 'null'
          description: |
            The associated lockbox. Null only when the lockbox row is not
            visible to the caller. Filtering by `serial_numbers`, `account_id`
            or `lockbox_type` restricts results to events whose lockbox matches.
          properties:
            id:
              $ref: '#/components/schemas/UuidProperty'
            serial_number:
              type: string
              description: Serial number of the lockbox
              example: '2179676'
            lockbox_type:
              $ref: '#/components/schemas/LockboxTypeValue'
            account_id:
              type: string
              format: uuid
              description: ID of the account that owns the lockbox
              example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
      required:
        - id
        - lockbox_id
        - event_type
        - created_at
    PostLockboxEventsRequest:
      type: object
      properties:
        events:
          type: array
          items:
            type: object
            properties:
              lockbox_id:
                type: string
                description: ID of the lockbox
                example: 123e4567-e89b-12d3-a456-426614174000
              event_type:
                type: string
                enum:
                  - Install
                  - Uninstall
                description: Type of event
                example: Install
              unit_id:
                type: number
                description: ID of the unit to associate with the event
                example: 12345
            required:
              - lockbox_id
              - event_type
              - unit_id
          minItems: 1
          maxItems: 100
          description: List of lockbox events to create
          example:
            - lockbox_id: 123e4567-e89b-12d3-a456-426614174000
              event_type: Install
              unit_id: 12345
      required:
        - events
    UuidProperty:
      type: string
      format: uuid
      description: Unique identifier
      example: 123e4567-e89b-12d3-a456-426614174000
    LockboxInstallation:
      type: object
      properties:
        id:
          $ref: '#/components/schemas/UuidProperty'
        lockbox_id:
          $ref: '#/components/schemas/UuidProperty'
        unit_id:
          type: string
          description: ID of the unit where the lockbox is installed
          example: '12345'
      required:
        - id
        - lockbox_id
        - unit_id
    LeasingEvent:
      type: object
      properties:
        id:
          type: integer
          format: int64
          description: Unique identifier for the leasing event
          example: 12345
        created_at:
          type: string
          format: date-time
          description: Timestamp when the leasing event was created
          example: '2024-10-05T18:53:03.406168Z'
        notes:
          type: string
          description: Optional notes about the leasing event
          example: Reschedule
        prospect:
          type: integer
          format: int64
          description: ID of the associated prospect
          example: 12345
        planned_date_time:
          type: string
          format: date-time
          description: Planned date and time for the leasing event
          example: '2024-10-05T18:53:03.406168Z'
        source:
          type: string
          description: Source of the leasing event
          enum:
            - Phone Call
            - Text Message
            - Email
            - Facebook Message
            - WhatsApp
            - Other
            - Showing Scheduler
            - Automation
          example: Phone Call
        event_type:
          type: string
          description: Type of the leasing event
          enum:
            - New
            - Contacted, Awaiting Information
            - Showing Desired
            - Showing Scheduled
            - Showing Complete
            - Missed Showing
            - Ghosting
            - Application Sent to Prospect
            - Application Received
            - Application Pending
            - Application in Owner Review
            - Application Approved
            - Withdrawn
            - Application Rejected
            - Prescreen Submitted
            - Prescreen Rejected - Self reported credit
            - Prescreen Rejected - Self reported income
            - Prescreen Rejected - ID Verification
            - Prescreen Approved
            - Looking too early
            - Lease out for signing
            - Lease Signed
            - Deposit Received
            - Move-in Scheduled
            - Moved In
            - Unit of Interest Unavailable
            - Not Interested
            - Duplicate Lead
            - Still Deciding
            - HOA Application Sent To Prospect
            - HOA Application Submitted
            - HOA Application Approved
            - HOA Application Rejected
            - Showing Failed
            - Showing Canceled
            - Showing Confirmed
            - Awaiting PM Response
            - PM Response
            - Arrived for Showing
            - Showing Started
            - Log Note
            - Assign to User
            - Blocklist Prospect
            - Unblock Prospect
            - Reassign Showing
          example: New
        next_follow_up:
          type: string
          format: date-time
          description: Timestamp for the next follow-up
          example: '2024-10-05T18:53:03.406168Z'
        deleted:
          type: boolean
          default: false
          description: Flag indicating if the leasing event is deleted
          example: false
        created_by:
          type: string
          description: Identifier of the user who created the event
          example: '12345'
        context:
          type: object
          description: >-
            Additional context information for the event. Structure varies based
            on event_type.
          example:
            assignedToUserIds:
              - 1259ef6e-61ee-42cb-b6bd-7fe547569d7c
            createdByUserRole: Property Manager
            previousAssignedToUserIds: []
    Unit:
      type: object
      properties:
        id:
          type: integer
          description: Unique identifier for the unit
          example: 3318
        created_at:
          type: string
          format: date-time
          description: Timestamp when the unit was created
          example: '2024-10-05T18:53:03.406168Z'
        updated_at:
          type: string
          format: date-time
          description: Timestamp when the unit was last updated
          example: '2024-10-05T18:53:03.406168Z'
        address:
          type: object
          description: Address information for the unit
          properties:
            formatted_address:
              type: string
              description: Formatted first line of the address.
              example: '123 Main St #3'
            street_number:
              type: string
              description: Street number
              example: '123'
            street_name:
              type: string
              description: Street name
              example: Main St
            unit:
              type:
                - string
                - 'null'
              description: Unit/apartment number
              example: '#3'
            zip_code:
              type: string
              description: ZIP code
              example: '94111'
            coordinates:
              type:
                - array
                - 'null'
              description: Geographic coordinates as [longitude, latitude]
              items:
                type: number
                example: -90.189842
              minItems: 2
              maxItems: 2
              example:
                - -90.189842
                - 38.763467
            timezone:
              type:
                - object
                - 'null'
              description: Timezone information for the address
              properties:
                name:
                  type: string
                  description: IANA timezone name
                  example: America/New_York
                source:
                  type: string
                  description: Data source attribution
                  example: © OpenStreetMap contributors
                utc_offset:
                  type: number
                  description: UTC offset in hours
                  example: -5
                abbreviation:
                  type: string
                  description: Timezone abbreviation
                  example: EST
                observes_dst:
                  type: boolean
                  description: Whether the timezone observes daylight saving time
                  example: true
            city:
              type: string
              description: City name
              example: Miami
            state:
              type: string
              description: State full name
              example: Florida
            country:
              type: string
              description: Country
              example: United States
        property_type:
          type: string
          description: Type of property
          example: TOWNHOUSE
          enum:
            - SINGLE FAMILY RESIDENCE
            - DUPLEX
            - TRIPLEX
            - MULTI-FAMILY
            - CONDO
            - TOWNHOUSE
            - ROOM
            - ADU
            - GARAGE
        bedrooms:
          type: string
          description: Number of bedrooms
          example: '3'
        bathrooms:
          type: string
          description: Number of bathrooms
          example: '2'
        sqft:
          type: string
          description: Square footage of the unit
          example: '1378'
        furnished:
          type: boolean
          description: Whether the unit is furnished
          example: false
        renovated:
          type: string
          description: Whether the unit has been renovated
          example: 'No'
        num_parking_spots:
          type: string
          description: Number of parking spots
          example: '2'
        laundry:
          type: string
          description: Laundry options
          example: In Unit
          enum:
            - In Unit
            - Shared
            - Coin-op
            - Hookups but no machines
            - Machines In Unit - Tenant Responsible
            - None
        target_rental_rate:
          type: string
          description: >-
            Target rental rate for the unit in dollars per month. 1925 means
            $1925/month
          example: '1925'
        is_occupied:
          type: boolean
          description: Whether the unit is currently occupied
          example: false
        earliest_move_in_date:
          type: string
          format: date
          description: Earliest date the unit is available for move-in
          example: '2024-10-12'
        allow_cooperating_brokers:
          type:
            - boolean
            - 'null'
          description: Whether cooperating brokers are allowed
          example: true
        desired_lease_duration_months:
          type: array
          items:
            type: integer
            example: 12
          description: Desired lease duration in months
          example:
            - 12
        pets_allowed:
          type:
            - string
            - 'null'
          enum:
            - 'Yes'
            - Yes with pet fee
            - Dogs only
            - Dogs only with pet fee
            - Cats only
            - Cats only with pet fee
            - 'No'
          description: Pet policy
          example: Yes with pet fee
        pet_restrictions:
          type: string
          description: Restrictions on pets (breed/weight/size limits, not fees)
          example: Max 2 pets. Dogs must be under 50 lbs. No aggressive breeds.
        pet_fees:
          type:
            - array
            - 'null'
          items:
            type: object
            properties:
              fee_name:
                type: string
                description: Name of the pet fee
                example: Pet Deposit
              amount:
                type: number
                minimum: 0
                description: Fee amount (dollar value or percentage of rent)
                example: 500
              type:
                enum:
                  - dollar
                  - percent
                type: string
                description: Whether amount is a flat dollar value or percentage of rent
                example: dollar
              per_pet:
                type: boolean
                description: Whether the fee is charged per pet
                example: false
              required:
                type: boolean
                description: Whether the fee is mandatory
                example: true
              applies_to_esas:
                type: boolean
                description: Whether this fee applies to emotional support animals
                example: false
              fee_timing:
                enum:
                  - move_in
                  - monthly
                  - move_out
                  - annually
                type: string
                description: When the fee is charged
                example: move_in
              fee_refundable:
                enum:
                  - refundable
                  - nonRefundable
                  - partiallyRefundable
                type: string
                description: Refundability of the fee
                example: refundable
              depends_on_pet_screening_results:
                type: boolean
                description: Whether the fee amount may vary based on pet screening
                example: false
            required:
              - fee_name
              - amount
              - type
              - fee_timing
              - fee_refundable
          description: Structured pet fees for the unit
        hoa_app_required:
          type:
            - boolean
            - 'null'
          description: Whether HOA application is required
          example: true
        hoa_app_fee:
          type:
            - number
            - 'null'
          description: HOA application fee in dollars
          example: 100
        hoa_application_url:
          type:
            - string
            - 'null'
          description: URL for HOA application
          example: https://example.com/application
        key_access:
          type: string
          description: Key access information
          example: I will add this later
          enum:
            - Digital Lockbox Connected to RentEngine
            - Single code lockbox with key
            - Digital door lock with code
            - I will add this later
            - Accompanied Showing
        access_instructions:
          type: string
          description: Instructions for accessing the unit
          example: 'Lockbox/Door Code: Tenant Turner'
        min_resident_qualifications:
          type: string
          description: Minimum qualifications for residents
          example: ''
        utilities_included:
          type: array
          items:
            type: string
            example: Lawn Care
            enum:
              - Water
              - Sewer/Septic
              - Trash
              - Wifi/Internet
              - Cable/TV
              - Electricity
              - Gas
              - HOA
              - Lawn Care
              - Pool Service
              - Pest Control
          description: Utilities included in rent
          example:
            - Lawn Care
            - Trash
        parking_type:
          type: array
          items:
            type: string
            example: Assigned Spots
            enum:
              - Street
              - Carport
              - Assigned Spots
              - Driveway
              - Shared Garage
              - Private Garage
              - Paid Parking
          description: Type of parking available
          example:
            - Assigned Spots
        storm_protection:
          type: string
          description: Storm protection features
          example: None
        status:
          type: string
          description: Current status of the unit
          example: Leased
        send_showing_notifications:
          type: boolean
          description: Whether to send showing notifications
          example: true
        send_leasing_update_email:
          type: boolean
          description: Whether to send leasing update emails
          example: true
        extracted_from:
          type: string
          description: >-
            Source of the unit data. Can be a any string. Essentially the same
            as an external_id. Uniqueness is not enforced.
          example: f123abc
        marketing_description:
          type: string
          description: Marketing description of the unit
          example: >-
            **AVAILABLE NOW** 3 Bedroom 2 Bathroom Townhome For Rent in Meadow
            Woods!
        marketing_photos:
          type: array
          items:
            type: object
            properties:
              path:
                type: string
                description: >-
                  Either the original image URL or the file path in the
                  RentEngine storage. When updating, provide the external image
                  url.
                examples:
                  - images/92fdf304-9f60-45ff-b44a-e5b2d16b5257.jpg
                  - >-
                    https://images.cdn.appfolio.com/allegiant/images/8eb1431e-d325-4a43-9fbc-cea487e609f1/large.jpeg
              hidden:
                type: boolean
                example: false
              original:
                description: >-
                  The external image URL from where the image was imported to
                  RentEngine. Not required as it will be set/overwritten by
                  RentEngine when setting the path field.
                type:
                  - string
                  - 'null'
                example: >-
                  https://images.cdn.appfolio.com/allegiant/images/8eb1431e-d325-4a43-9fbc-cea487e609f1/large.jpeg
          description: Photos of the unit
        commission_amount:
          type: string
          description: Commission amount
          example: '1'
        commission_type:
          type: string
          description: Type of commission
          enum:
            - percent
            - fixed
            - none
            - contact_mls_agent
          example: none
        imported_by:
          type:
            - string
            - 'null'
          description: Who/what imported the unit
          example: Rentvine Sync
        floor_number:
          type: integer
          description: >-
            Floor number of the unit. Best to use the floor of the entrance door
            if the unit spans multiple floors.
          example: 1
        has_elevator:
          type:
            - boolean
            - 'null'
          description: Whether the building has an elevator
          example: false
        hoa_details:
          type: object
          properties:
            isInHOA:
              type: boolean
              example: true
            hoaAmenities:
              type: array
              items:
                type: string
                example: Clubhouse
              example:
                - Clubhouse
                - Pool
          description: Details about the HOA
        account_id:
          type: string
          format: uuid
          description: >-
            ID of the account that owns the unit. Must be a valid account for
            which the api key has access.
          example: 269bf205-d876-42f5-988d-6f40891df58a
        owner_emails:
          type: array
          items:
            type: string
            example: rick@amgrents.com
          description: >-
            (DEPRECATED) - Use property_owner_id instead. Email addresses of the
            owners.
          deprecated: true
          example:
            - rick@amgrents.com
        block_syndication_to_ils:
          type: boolean
          description: >-
            Whether to block syndication of this unit to ILS (Internet Listing
            Services)
          example: false
        accepts_vouchers:
          type:
            - boolean
            - 'null'
          description: Whether the unit accepts housing vouchers.
          example: true
        internal_notes:
          type:
            - string
            - 'null'
          description: Internal notes about the unit.
          example: Garage work scheduled for Monday.
        amenities:
          type: array
          items:
            type: string
            example: Dishwasher
          description: All amenities of the unit
          example:
            - Dishwasher
            - Stove
            - Range Oven
            - Refrigerator
        monthly_fees:
          type:
            - array
            - 'null'
          items:
            type: object
            properties:
              name:
                type: string
                example: Resident Benefit Package
              amount:
                type: number
                example: 55.5
                description: >-
                  Depending on the type field, this can represet either $55.50
                  of 55.5% of 1 month's rent.
              type:
                enum:
                  - percent
                  - dollar
                type: string
                description: >-
                  Determines if  amount is calculated as an absolute dollar
                  value or as a percent of 1 month's rent.
                example: dollar
          description: Monthly recurring fees
        move_in_fees:
          type:
            - array
            - 'null'
          items:
            type: object
            properties:
              name:
                type: string
                example: Admin Fee
              amount:
                type: number
                example: 55.5
                description: >-
                  Depending on the type field, this can represet either $55.50
                  of 55.5% of 1 month's rent.
              type:
                enum:
                  - percent
                  - dollar
                type: string
                description: >-
                  Determines if  amount is calculated as an absolute dollar
                  value or as a percent of 1 month's rent.
                example: dollar
          description: Fees required at move-in
        multifamily_property_id:
          type:
            - string
            - 'null'
          format: uuid
          description: ID of the multifamily property
          example: 421e4567-e89b-12d3-a456-426614174000
        showing_method:
          type:
            - string
            - 'null'
          description: Method for showing the unit
          example: Remote Guided
          enum:
            - Accompanied
            - Remote Guided
            - Remote Guided with Gated Access
            - Self Guided
        floorplans_id:
          type:
            - string
            - 'null'
          format: uuid
          description: ID of the floorplan
          example: 451e4567-e89b-12d3-a456-426614174000
        video_url:
          type:
            - string
            - 'null'
          format: url
          description: >-
            URL of video tour (such as YouTube, Vimeo, Zillow Tour, Matterport,
            Ricoh360, or zInspector tour)
          example: https://www.youtube.com/watch?v=1234567890
        subteam_id:
          type:
            - string
            - 'null'
          format: uuid
          description: ID of the subteam managing the unit
          example: 123e4567-e89b-12d3-a456-426614174000
        prescreen_template_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            ID of the prescreening template to use for this unit, if it is null
            the default template will be used.
          example: 123e4567-e89b-12d3-a456-426614174000
        structured_access_instructions:
          type: object
          description: >
            Structured access instructions that vary based on showing_method:

            - For "Self Guided" showing method: Use the self-guided showing
            instructions object

            - For "Remote Guided" or "Remote Guided with Gated Access" showing
            methods: Use the self-guided showing instructions object

            - For "Accompanied" showing method: Use either the legacy
            accompanied or accompanied showing instructions object


            When updating structured_access_instructions, the showing_method
            field must also be set.
          oneOf:
            - type: object
              description: >-
                Self-guided showing instructions (for "Self Guided", "Remote
                Guided", or "Remote Guided with Gated Access" showing methods)
              title: Self Guided/Remote Showing Instructions
              properties:
                lockbox_location:
                  type: string
                  example: Front Door
                  description: Location of the lockbox
                lockbox_door_code:
                  type: string
                  example: '1234'
                  description: Code for the lockbox
                require_pm_approval_for_showing:
                  type: boolean
                  example: false
                  description: Whether PM approval is required for showings
                private_gate_code:
                  type: string
                  example: '5678'
                  description: Code for private gate access
                community_gate_code:
                  type: string
                  example: '9012'
                  description: Code for community gate access
                anything_else:
                  type: string
                  example: Please close the gate behind you
                  description: Additional instructions
            - type: object
              description: >-
                Accompanied showing instructions (for "Accompanied" showing
                method)
              title: Accompanied Showing Instructions
              properties:
                require_pm_approval_for_showing:
                  type: boolean
                  example: false
                  description: Whether PM approval is required for showings
                assigned_user_ids:
                  type: array
                  items:
                    type: string
                    example: cd702dbe-bf32-41cc-83a2-efe00f495f04
                  example:
                    - cd702dbe-bf32-41cc-83a2-efe00f495f04
                    - 98702dbe-bf32-41cc-83a2-efe00f495f04
                  description: IDs of users assigned to conduct the showing
                pmPhones:
                  type: array
                  items:
                    type: string
                    example: '+15551234567'
                  example:
                    - '+15551234567'
                    - +1 555-987-6543
                  description: Property manager contact phone numbers
                meeting_location:
                  type: string
                  example: Leasing office
                  description: Where to meet for the showing
                internal_notes:
                  type: string
                  example: Current tenant works from home
                  description: Notes for internal use
                current_tenant_phone:
                  type: string
                  example: 555-111-2222
                  deprecated: true
                  description: >-
                    (DEPRECATED) - Use current_tenant_phones instead. Current
                    tenant's contact phone
                current_tenant_phones:
                  type: array
                  items:
                    type: string
                    example: 555-111-2222
                    description: Current tenant's contact phone
                current_tenant_name:
                  type: string
                  example: Jane Doe
                  description: Current tenant's name
                min_notice_period_hours:
                  type: number
                  example: 24
                  description: Minimum notice required before showing (in hours)
                assign_to_best_agent:
                  type: boolean
                  example: false
                  description: Whether to automatically assign to the best available agent
                piggyback_maximum:
                  type: number
                  minimum: 0
                  maximum: 10
                  description: >-
                    Maximum number of additional prospects that can piggyback
                    onto a showing. Set to 0 to disable piggybacking. Null means
                    use account default.
                  example: 3
                multifamily_piggyback_maximum:
                  type:
                    - integer
                    - 'null'
                  minimum: 0
                  maximum: 10
                  description: >-
                    Maximum number of adjacent showings allowed at different
                    units in the same multifamily property. 0 disables
                    multifamily piggybacking. Null means use account default.
                  example: 1
                override_showing_duration_minutes:
                  type: number
                  minimum: 0
                  maximum: 100
                  description: Override the default showing duration in minutes
                  example: 30
              required:
                - assigned_user_ids
        enable_send_report:
          type: boolean
          description: Whether to enable sending reports
          example: true
        earliest_showing_date:
          type: string
          format: date
          description: Earliest date the unit can be shown
          example: '2024-10-12'
        security_deposit_amount:
          type:
            - number
            - 'null'
          description: Amount of security deposit in dollars. 1000 means $1000.21
          example: 1000.21
        require_last_month_rent:
          type:
            - boolean
            - 'null'
          description: Whether last month's rent is required upfront
          example: true
        requires_voucher:
          type:
            - boolean
            - 'null'
          description: Whether a voucher is required
          example: false
        custom_application_url:
          type: string
          description: URL for custom application
          example: >-
            https://app.findigs.com/apply/unitid=70f51c4c-d708-402e-9a5f-bb6fd60b6cf2
        include_feedback_leasing_report:
          type: boolean
          description: Whether to include feedback in leasing reports
          example: true
        year_built:
          type:
            - number
            - 'null'
          description: Year the property was built
          example: 2020
          minimum: 1800
        application_fee:
          type:
            - number
            - 'null'
          description: Application fee amount in dollars
          example: 50
          minimum: 0
      required:
        - id
        - created_at
        - updated_at
        - address
        - enable_send_report
        - showing_method
    UpsertUnitRequest:
      type: object
      properties:
        id:
          type: number
          description: >-
            Unit ID. If provided, the unit will be updated; if not, a new unit
            will be created.
          example: 3318
        address:
          type: object
          description: Unit address. All fields must be provided together when updating.
          properties:
            street_number:
              type: string
              description: Street number
              example: '123'
            street_name:
              type: string
              description: Street name
              example: Main St
            unit:
              type: string
              description: Unit/apartment number
              example: 4B
            zip_code:
              type: string
              description: ZIP code
              example: '12345'
            state:
              type: string
              description: State (two-letter code)
              example: CA
            country:
              type: string
              enum:
                - United States
              default: United States
              description: Country
              example: United States
            city:
              type: string
              description: City
              example: San Francisco
          required:
            - street_number
            - street_name
            - zip_code
            - state
            - city
        property_type:
          type: string
          enum:
            - SINGLE FAMILY RESIDENCE
            - DUPLEX
            - TRIPLEX
            - MULTI-FAMILY
            - CONDO
            - TOWNHOUSE
            - ROOM
            - ADU
            - GARAGE
          description: Type of property
          example: TOWNHOUSE
        bedrooms:
          type: number
          description: Number of bedrooms
          example: 3
        bathrooms:
          type: number
          description: Number of bathrooms
          example: 2
        sqft:
          type: number
          description: Square footage of the unit
          example: 1378
        furnished:
          type: boolean
          description: Whether the unit is furnished
          example: false
        renovated:
          type: string
          description: Whether the unit has been renovated
          example: 'No'
        num_parking_spots:
          type: number
          description: Number of parking spots
          example: 2
        laundry:
          type: string
          enum:
            - In Unit
            - Shared
            - Coin-op
            - Hookups but no machines
            - Machines In Unit - Tenant Responsible
            - None
          description: Laundry options
          example: In Unit
        target_rental_rate:
          type: number
          description: Target rental rate in dollars per month
          example: 1925
        is_occupied:
          type: boolean
          description: Whether the unit is currently occupied
          example: false
        earliest_move_in_date:
          type: string
          format: date
          description: Earliest date the unit is available for move-in
          example: '2024-10-12'
        allow_cooperating_brokers:
          type: boolean
          description: Whether cooperating brokers are allowed
          example: true
        desired_lease_duration_months:
          type: array
          items:
            type: number
            example: 12
          description: Desired lease duration in months
          example:
            - 12
        pets_allowed:
          type: string
          enum:
            - 'Yes'
            - Yes with pet fee
            - 'No'
            - Dogs only
            - Dogs only with pet fee
            - Cats only
            - Cats only with pet fee
          description: Pet policy
          example: Yes with pet fee
        pet_restrictions:
          type: string
          description: Restrictions on pets (breed/weight/size limits, not fees)
          example: Max 2 pets. Dogs must be under 50 lbs. No aggressive breeds.
        pet_fees:
          type:
            - array
            - 'null'
          items:
            type: object
            properties:
              fee_name:
                type: string
                description: Name of the pet fee
                example: Pet Deposit
              amount:
                type: number
                minimum: 0
                description: Fee amount (dollar value or percentage of rent)
                example: 500
              type:
                enum:
                  - dollar
                  - percent
                type: string
                description: Whether amount is a flat dollar value or percentage of rent
                example: dollar
              per_pet:
                type: boolean
                description: Whether the fee is charged per pet
                example: false
              required:
                type: boolean
                description: Whether the fee is mandatory
                example: true
              applies_to_esas:
                type: boolean
                description: Whether this fee applies to emotional support animals
                example: false
              fee_timing:
                enum:
                  - move_in
                  - monthly
                  - move_out
                  - annually
                type: string
                description: When the fee is charged
                example: move_in
              fee_refundable:
                enum:
                  - refundable
                  - nonRefundable
                  - partiallyRefundable
                type: string
                description: Refundability of the fee
                example: refundable
              depends_on_pet_screening_results:
                type: boolean
                description: Whether the fee amount may vary based on pet screening
                example: false
            required:
              - fee_name
              - amount
              - type
              - per_pet
              - required
              - applies_to_esas
              - fee_timing
              - fee_refundable
              - depends_on_pet_screening_results
          description: Structured pet fees for the unit
        hoa_details:
          type: object
          properties:
            isInHOA:
              type: boolean
              description: Whether the unit is in an HOA
              example: true
            hoaAppRequired:
              type: boolean
              description: Whether HOA application is required
              example: true
            hoaAppFee:
              type: number
              minimum: 0
              description: HOA application fee in dollars
              example: 100
            hoaApplicationUrl:
              type: string
              format: uri
              description: URL for HOA application
              example: https://example.com/application
            hoaApprovalTimeframe:
              type: string
              description: Timeframe for HOA approval
              example: 2 weeks
            hoaAmenities:
              type: array
              items:
                type: string
                example: Pool
              description: HOA amenities
              example:
                - Pool
                - Gym
                - Clubhouse
        key_access:
          type: string
          description: Key access information
          example: Digital door lock with code
          enum:
            - Digital Lockbox Connected to RentEngine
            - Single code lockbox with key
            - Digital door lock with code
            - I will add this later
            - Accompanied Showing
        structured_access_instructions:
          type: object
          description: >
            Structured access instructions that vary based on showing_method.

            When providing structured_access_instructions, showing_method must
            also be set.
          oneOf:
            - type: object
              description: Self-guided showing instructions
              title: Self-guided/Remote showing instructions
              properties:
                lockbox_location:
                  type: string
                  description: Location of the lockbox
                  example: Front Door
                lockbox_code:
                  type: string
                  description: Code for the lockbox
                  example: '1234'
                require_pm_approval_for_showing:
                  type: boolean
                  description: Whether PM approval is required for showings
                  example: false
                private_gate:
                  type: string
                  description: Private gate information
                  example: 'Gate code: 5678'
                community_gate:
                  type: string
                  description: Community gate information
                  example: 'Gate code: 9012'
                anything_else:
                  type: string
                  description: Additional instructions
                  example: Please close the gate behind you
            - type: object
              description: Accompanied showing instructions
              title: Accompanied Showing Instructions
              properties:
                require_pm_approval_for_showing:
                  type: boolean
                  description: Whether PM approval is required for showings
                  example: false
                assigned_user_ids:
                  type: array
                  items:
                    type: string
                    example: user-123
                  description: IDs of users assigned to conduct the showing
                  example:
                    - user-123
                    - user-456
                pmPhones:
                  type: array
                  items:
                    type: string
                    examples:
                      - 555-123-4567
                      - 555-987-6543
                    description: Property manager contact phone numbers
                meeting_location:
                  type: string
                  description: Where to meet for the showing
                  example: Leasing office
                internal_notes:
                  type: string
                  description: Notes for internal use
                  example: Current tenant works from home
                current_tenant_phone:
                  type: string
                  description: >-
                    (DEPRECATED) - Use current_tenant_phones instead. Current
                    tenant's contact phone
                  example: 555-111-2222
                  deprecated: true
                current_tenant_phones:
                  type: array
                  items:
                    type: string
                    example: 555-111-2222
                    description: Current tenant's contact phone
                current_tenant_name:
                  type: string
                  description: Current tenant's name
                  example: Jane Doe
                min_notice_period_hours:
                  type: number
                  description: Minimum notice required before showing (in hours)
                  example: 24
                assign_to_best_agent:
                  type: boolean
                  description: Whether to automatically assign to the best available agent
                  example: false
                piggyback_maximum:
                  type: number
                  minimum: 0
                  maximum: 10
                  description: >-
                    Maximum number of additional prospects that can piggyback
                    onto a showing. Set to 0 to disable piggybacking. Null means
                    use account default.
                  example: 3
                multifamily_piggyback_maximum:
                  type:
                    - integer
                    - 'null'
                  minimum: 0
                  maximum: 10
                  description: >-
                    Maximum number of adjacent showings allowed at different
                    units in the same multifamily property. 0 disables
                    multifamily piggybacking. Null means use account default.
                  example: 1
                override_showing_duration_minutes:
                  type: number
                  minimum: 0
                  maximum: 100
                  description: Override the default showing duration in minutes
                  example: 30
        earliest_showing_date:
          type: string
          format: date
          description: Earliest date the unit can be shown
          example: '2024-10-12'
        additional_info:
          type: string
          description: Additional information about the unit
          example: Newly renovated kitchen
        min_resident_qualifications:
          type: string
          description: Minimum qualifications for residents
          example: Credit score 650+, income 3x rent
        utilities_included:
          type: array
          items:
            type: string
            example: Lawn Care
            enum:
              - Water
              - Sewer/Septic
              - Trash
              - Wifi/Internet
              - Cable/TV
              - Electricity
              - Gas
              - HOA
              - Lawn Care
              - Pool Service
              - Pest Control
          description: Utilities included in rent
          example:
            - Lawn Care
            - Trash
        parking_type:
          type: array
          items:
            type: string
            example: Assigned Spots
            enum:
              - Street
              - Carport
              - Assigned Spots
              - Driveway
              - Shared Garage
              - Private Garage
              - Paid Parking
              - Parking Lot
          description: Type of parking available
          example:
            - Assigned Spots
        status:
          type: string
          enum:
            - Incomplete
            - Available
            - On Hold
            - Leased
            - Archived
            - Withdrawn
            - Withdrawal Requested
          description: Current status of the unit
          example: Available
        extracted_from:
          type: string
          description: >-
            Source of the unit data. Can be a any string. Essentially the same
            as an external_id. Uniqueness is not enforced. Values that
            RentEngine's own PMS sync owns are reserved, because the sync uses
            this field to match a unit to its listing - sending a different
            value for a unit imported from a connected PMS returns 400, as does
            claiming a key another unit in the account already holds. Your own
            external IDs are unaffected.
          example: f123abc
        marketing_description:
          type: string
          description: Marketing description of the unit
          example: '**AVAILABLE NOW** 3 Bedroom 2 Bathroom Townhome For Rent!'
        marketing_photos:
          type: array
          items:
            type: object
            properties:
              path:
                type: string
                description: >-
                  Either the original image URL or the file path in the
                  RentEngine storage
                example: https://example.com/images/unit123.jpg
              hidden:
                type: boolean
                description: Whether the photo is hidden
                example: false
              original:
                type: string
                description: The external image URL from where the image was imported
                example: https://example.com/images/unit123_original.jpg
            required:
              - path
              - hidden
        commission_amount:
          type: number
          description: Commission amount
          example: 1
        commission_type:
          type: string
          enum:
            - percent
            - fixed
            - none
            - contact_mls_agent
          description: Type of commission
          example: percent
        imported_by:
          type: string
          description: Who/what imported the unit
          example: API Import
        floor_number:
          type: number
          minimum: 0
          maximum: 150
          description: Floor number of the unit
          example: 1
        has_elevator:
          type: boolean
          description: Whether the building has an elevator
          example: false
        account_id:
          type: string
          description: ID of the account that owns the unit
          example: 269bf205-d876-42f5-988d-6f40891df58a
        accepts_vouchers:
          type: boolean
          description: Whether the unit accepts housing vouchers
          example: true
        showing_method:
          type: string
          enum:
            - Accompanied
            - Remote Guided
            - Remote Guided with Gated Access
            - Self Guided
          description: Method for showing the unit
          example: Self Guided
        internal_notes:
          type: string
          description: Internal notes about the unit
          example: Garage work scheduled for Monday
        move_in_fees:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
                enum:
                  - percent
                  - dollar
                description: Type of fee calculation
                example: dollar
              amount:
                type: number
                minimum: 0
                description: Fee amount
                example: 150
              name:
                type: string
                description: Name of the fee
                example: Admin Fee
            required:
              - type
              - amount
              - name
        monthly_fees:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
                enum:
                  - percent
                  - dollar
                description: Type of fee calculation
                example: dollar
              amount:
                type: number
                minimum: 0
                description: Fee amount
                example: 50
              name:
                type: string
                description: Name of the fee
                example: Pet Fee
            required:
              - type
              - amount
              - name
        multifamily_property_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            ID of the multifamily property. Pass string 'null' to clear this
            field.
          example: 421e4567-e89b-12d3-a456-426614174000
        floorplans_id:
          type:
            - string
            - 'null'
          format: uuid
          description: ID of the floorplan. Pass string 'null' to clear this field.
          example: 451e4567-e89b-12d3-a456-426614174000
        video_url:
          type: string
          description: >-
            URL of video tour (such as YouTube, Vimeo, Zillow Tour, Matterport,
            Ricoh360, or zInspector tour)
          example: https://www.youtube.com/watch?v=1234567890
        subteam_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            ID of the subteam managing the unit. Pass string 'null' to clear
            this field.
          example: 123e4567-e89b-12d3-a456-426614174000
        prescreen_template_id:
          type: string
          format: uuid
          description: ID of the prescreening template to use for this unit
          example: 123e4567-e89b-12d3-a456-426614174000
        enable_send_report:
          type: boolean
          description: Whether to enable sending reports
          example: true
        security_deposit_amount:
          type: number
          description: Amount of security deposit in dollars
          example: 1000
        require_last_month_rent:
          type: boolean
          description: Whether last month's rent is required upfront
          example: true
        requires_voucher:
          type: boolean
          description: Whether a voucher is required
          example: false
        include_feedback_leasing_report:
          type: boolean
          description: Whether to include feedback in leasing reports
          example: true
        year_built:
          type: number
          description: Year the property was built
          example: 2020
          minimum: 1800
        after_upsert_action:
          type: object
          description: Actions to perform after updating the unit
          properties:
            action:
              type: string
              enum:
                - cancel_scheduled_bookings
                - notify_all_prospects
              description: The action to perform after updating the unit
              example: cancel_scheduled_bookings
            should_cancel_scheduled_bookings:
              type: boolean
              description: >-
                Whether to cancel any scheduled/confirmed bookings when updating
                the unit (only applies to cancel_scheduled_bookings action)
              example: true
            custom_sms_message:
              type: string
              description: Custom SMS message to send to prospects (applies to all actions)
              example: >-
                Hi, the unit is available for showing. Please contact us at
                (555) 123-4567 with any questions.
          required:
            - action
        application_fee:
          type: number
          description: Application fee amount in dollars
          example: 50
          minimum: 0
      oneOf:
        - required:
            - id
          title: Update Unit
        - required:
            - address
            - property_type
            - target_rental_rate
            - account_id
          title: Create New Unit
    WebhookPayload:
      type: object
      description: Generic structure of webhook payloads
      oneOf:
        - $ref: '#/components/schemas/InsertPayload'
        - $ref: '#/components/schemas/UpdatePayload'
        - $ref: '#/components/schemas/DeletePayload'
    InsertPayload:
      type: object
      properties:
        type:
          type: string
          enum:
            - INSERT
          description: Type of event
          example: INSERT
        table:
          type: string
          description: Name of the table where the event occurred
          example: lockbox_events
        record:
          type: object
          description: The newly created record
          example:
            id: 123e4567-e89b-12d3-a456-426614174000
            lockbox_id: 123e4567-e89b-12d3-a456-426614174001
            event_type: Install
            unit_id: '12345'
            created_at: '2023-01-15T12:30:00Z'
            data: null
        old_record:
          type: 'null'
          description: Always null for INSERT events
          example: null
      required:
        - type
        - table
        - record
        - old_record
    UpdatePayload:
      type: object
      properties:
        type:
          type: string
          enum:
            - UPDATE
          description: Type of event
          example: UPDATE
        table:
          type: string
          description: Name of the table where the event occurred
          example: units
        record:
          type: object
          description: The updated record with new values
          example:
            id: 3318
            address: 957
            property_type: TOWNHOUSE
            target_rental_rate: '2000'
            updated_at: '2024-10-05T18:53:03.406168Z'
        old_record:
          type: object
          description: The record before the update
          example:
            id: 3318
            address: 957
            property_type: TOWNHOUSE
            target_rental_rate: '1925'
            updated_at: '2024-09-05T18:53:03.406168Z'
      required:
        - type
        - table
        - record
        - old_record
    DeletePayload:
      type: object
      properties:
        type:
          type: string
          enum:
            - DELETE
          description: Type of event
          example: DELETE
        table:
          type: string
          description: Name of the table where the event occurred
          example: lockboxes
        record:
          type: 'null'
          description: Always null for DELETE events
          example: null
        old_record:
          type: object
          description: The record that was deleted
          example:
            id: 123e4567-e89b-12d3-a456-426614174000
            lockbox_type: Sentrilock
            serial_number: '1234567'
            account_id: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
      required:
        - type
        - table
        - record
        - old_record
    MultifamilyProperty:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Unique identifier for the multifamily property
          example: 123e4567-e89b-12d3-a456-426614174000
        community_name:
          type: string
          description: Name of the multifamily community
          example: Sunset Towers
        building_count:
          type: integer
          description: Number of buildings in the property
          example: 3
          minimum: 1
          maximum: 100
        unit_count:
          type: integer
          description: Total number of units in the property
          example: 75
          minimum: 1
          maximum: 10000
        description:
          type: string
          description: Description of the property
          example: Luxury apartment community with amenities
        structure_type:
          type: string
          enum:
            - Mid Rise
            - High Rise
            - Garden Style
          description: Type of building structure
          example: Mid Rise
        year_built:
          type: integer
          description: Year the property was built
          example: 2008
          minimum: 1800
          maximum: 2025
        photos:
          type: array
          items:
            type: object
            properties:
              path:
                type: string
                description: URL or path to the property photo
                example: https://example.com/images/sunset-towers.jpg
              hidden:
                type: boolean
                description: Whether the photo is hidden
                example: false
            required:
              - path
              - hidden
          description: Photos of the property
        external_ids:
          type: object
          description: External identifiers for the property
          example:
            mls_id: MLS12345
            yardi_id: Y7890
        text_address:
          type: string
          description: Full text address of the property
          example: 123 Main St, San Francisco, CA 94111
        account_id:
          type: string
          format: uuid
          description: ID of the account that owns the property
          example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        created_at:
          type: string
          format: date-time
          description: Timestamp when the property was created
          example: '2023-01-15T12:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: Timestamp when the property was last updated
          example: '2023-01-16T14:30:00Z'
      required:
        - id
        - community_name
        - text_address
        - account_id
        - created_at
        - updated_at
    UpsertMultifamilyPropertyRequest:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: >-
            Unique identifier for the multifamily property. If provided, the
            property will be updated; if not, a new property will be created.
          example: 123e4567-e89b-12d3-a456-426614174000
        community_name:
          type: string
          description: Name of the multifamily community
          example: Sunset Towers
        building_count:
          type: integer
          description: Number of buildings in the property
          example: 3
          minimum: 1
          maximum: 100
        unit_count:
          type: integer
          description: Total number of units in the property
          example: 75
          minimum: 1
          maximum: 10000
        description:
          type: string
          description: Description of the property
          example: Luxury apartment community with amenities
        structure_type:
          type: string
          enum:
            - Mid Rise
            - High Rise
            - Garden Style
          description: Type of building structure
          example: Mid Rise
        year_built:
          type: integer
          description: Year the property was built
          example: 2008
          minimum: 1800
        photos:
          type: array
          items:
            type: object
            properties:
              path:
                type: string
                description: URL or path to the property photo
                example: https://example.com/images/sunset-towers.jpg
              hidden:
                type: boolean
                description: Whether the photo is hidden
                example: false
            required:
              - path
              - hidden
          description: Photos of the property
        external_ids:
          type: object
          description: External identifiers for the property
          example:
            mls_id: MLS12345
            yardi_id: Y7890
        text_address:
          type: string
          description: Full text address of the property
          example: 123 Main St, San Francisco, CA 94111
        account_id:
          type: string
          format: uuid
          description: >-
            ID of the account that owns the property. Must be a valid account ID
            that the API key has access to.
          example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        deleted:
          type: boolean
          description: Whether the property is deleted
          example: false
          default: false
      required:
        - community_name
        - text_address
        - account_id
        - structure_type
        - year_built
        - building_count
        - unit_count
        - photos
      additionalProperties: false
    Floorplan:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Unique identifier for the floorplan
          example: 123e4567-e89b-12d3-a456-426614174000
        multifamily_property_id:
          type: string
          format: uuid
          description: ID of the multifamily property this floorplan belongs to
          example: 123e4567-e89b-12d3-a456-426614174000
        name:
          type: string
          description: Name of the floorplan
          example: The Willow
        bedroom_count:
          type: integer
          description: Number of bedrooms
          example: 2
          minimum: 0
          maximum: 100
        bathroom_count:
          type: number
          description: Number of bathrooms
          example: 2.5
          minimum: 0
          maximum: 100
        unit_count:
          type: integer
          description: Total number of units with this floorplan
          example: 15
          minimum: 0
          maximum: 10000
        units_available:
          type: integer
          description: Number of units currently available with this floorplan
          example: 3
          minimum: 0
          maximum: 10000
        market_rent:
          type: number
          description: Market rent for this floorplan
          example: 1850
          minimum: 0
        min_sqft:
          type: integer
          description: Minimum square footage for this floorplan
          example: 950
          minimum: 0
          maximum: 1000000
        max_sqft:
          type: integer
          description: Maximum square footage for this floorplan
          example: 1100
          minimum: 0
          maximum: 1000000
        photos:
          type: array
          items:
            type: object
            properties:
              path:
                type: string
                description: URL or path to the floorplan photo
                example: https://example.com/images/willow-floorplan.jpg
              hidden:
                type: boolean
                description: Whether the photo is hidden
                example: false
            required:
              - path
          description: Photos of the floorplan
        created_at:
          type: string
          format: date-time
          description: Timestamp when the floorplan was created
          example: '2023-01-15T12:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: Timestamp when the floorplan was last updated
          example: '2023-01-16T14:30:00Z'
        deleted:
          type: boolean
          description: Whether the floorplan is deleted
          example: false
          default: false
        description:
          type: string
          description: Description of the floorplan
          example: Spacious 2-bedroom layout with modern finishes
      required:
        - id
        - multifamily_property_id
        - created_at
        - updated_at
        - deleted
    UpsertFloorplanRequest:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: >-
            Unique identifier for the floorplan. If provided, the floorplan will
            be updated; if not, a new floorplan will be created.
          example: 123e4567-e89b-12d3-a456-426614174000
        multifamily_property_id:
          type: string
          format: uuid
          description: ID of the multifamily property this floorplan belongs to
          example: 123e4567-e89b-12d3-a456-426614174000
        name:
          type: string
          description: Name of the floorplan
          example: The Willow
        bedroom_count:
          type: integer
          description: Number of bedrooms
          example: 2
          minimum: 0
        bathroom_count:
          type: number
          description: Number of bathrooms
          example: 2.5
          minimum: 0
        unit_count:
          type: integer
          description: Total number of units with this floorplan
          example: 15
          minimum: 0
        units_available:
          type: integer
          description: Number of units currently available with this floorplan
          example: 3
          minimum: 0
        market_rent:
          type: number
          description: Market rent for this floorplan
          example: 1850
          minimum: 0
        min_sqft:
          type: integer
          description: Minimum square footage for this floorplan
          example: 950
          minimum: 0
        max_sqft:
          type: integer
          description: Maximum square footage for this floorplan
          example: 1100
          minimum: 0
        photos:
          type: array
          items:
            type: object
            properties:
              path:
                type: string
                description: URL or path to the floorplan photo
                example: https://example.com/images/willow-floorplan.jpg
              hidden:
                type: boolean
                description: Whether the photo is hidden
                example: false
            required:
              - path
              - hidden
          description: Photos of the floorplan
        deleted:
          type: boolean
          description: Whether the floorplan is deleted
          example: false
          default: false
        description:
          type: string
          description: Description of the floorplan
          example: Spacious 2-bedroom layout with modern finishes
      required:
        - multifamily_property_id
      additionalProperties: false
    Prospect:
      type: object
      properties:
        id:
          type: number
          description: Unique identifier for the prospect
          example: 123
        name:
          type:
            - string
            - 'null'
          description: Prospect's name
          example: John Doe
        email:
          type:
            - string
            - 'null'
          description: Prospect's email address
          example: john@example.com
        phone:
          type:
            - string
            - 'null'
          description: Prospect's phone number
          example: '+15551234567'
        status:
          type: string
          description: Current status of the prospect
          example: Showing Scheduled
        source:
          type:
            - string
            - 'null'
          description: Where the prospect came from
          example: Zillow
        unit_of_interest:
          type:
            - number
            - 'null'
          description: >-
            ID of the unit the prospect is interested in. `null` for building,
            floorplan, or account-level leads.
          example: 123
        account_id:
          type:
            - string
            - 'null'
          format: uuid
          description: Account that owns this prospect.
          example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        floorplan_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            Floorplan this prospect is interested in. `null` when the lead is
            unit-bound or account-only.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
        multifamily_property_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            Multifamily building this prospect is interested in. `null` when the
            lead is unit-bound or account-only.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
        notes:
          type:
            - string
            - 'null'
          description: Notes about the prospect
          example: Interested in 2BR units
        prescreened:
          type:
            - boolean
            - 'null'
          description: Whether the prospect has been prescreened
          example: true
        voucher_holder:
          type:
            - boolean
            - 'null'
          description: Whether the prospect holds a housing voucher
          example: false
        normalized_phone_number_generated:
          type:
            - string
            - 'null'
          description: Normalized phone number if normalizable. Else null.
          example: '+15551234567'
        license_number:
          type:
            - string
            - 'null'
          description: License number if applicable
          example: ABC123
        prospect_type:
          type: string
          description: Type of prospect
          enum:
            - Self
            - Agent
          example: Self
        created_at:
          type: string
          format: date-time
          description: When the prospect was created
          example: '2023-01-15T12:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: When the prospect was last updated
          example: '2023-01-16T14:30:00Z'
    PostProspectsRequest:
      type: object
      additionalProperties: false
      required:
        - source
        - name
      oneOf:
        - required:
            - unit_id
          title: By Unit ID
        - required:
            - unit_address
            - account_id
          title: By Unit Address
        - required:
            - floorplan_id
          title: By Floorplan
        - required:
            - multifamily_property_id
          title: By Building
        - required:
            - account_id
          title: Account only
          description: |
            Account-level lead with no unit, floorplan, or building. Do not
            also send unit_id, unit_address, floorplan_id, or
            multifamily_property_id.
          not:
            anyOf:
              - required:
                  - unit_id
              - required:
                  - unit_address
              - required:
                  - floorplan_id
              - required:
                  - multifamily_property_id
      dependentRequired:
        unit_address:
          - account_id
      properties:
        source:
          type: string
          minLength: 1
          description: |
            Where the prospect came from. Accepts the standard ProspectSource
            values (e.g. "Zillow", "Apartments.com", "Realtor.com", "MLS Agent",
            "Showing Smart", "Referral", "Company Website") as well as custom
            UTM-style values for your own integrations.
          example: Zillow
        name:
          type: string
          minLength: 1
          description: Prospect's full name.
          example: Jane Doe
        email:
          type:
            - string
            - 'null'
          format: email
          description: |
            Prospect's email address. Optional — when omitted, no
            acknowledgement email is sent and the prospect is stored
            without an email address.
          example: jane@example.com
        phone:
          type: string
          minLength: 1
          description: |
            Prospect's phone number. Accepts US-style formats (e.g.
            "+12155551234", "215-555-1234"); 400 is returned if the value
            cannot be normalized. Required whenever `sms.send` is `true` (the
            default) or `ai_enabled` is `false`.
          example: '+12155551234'
        account_id:
          type: string
          format: uuid
          description: >
            RentEngine account ID. Required when using `unit_address` to scope
            the

            fuzzy address search, and when creating an account-level lead (no

            unit / floorplan / building). Optional when using `unit_id`,

            `floorplan_id`, or `multifamily_property_id` (the account is derived

            from that property).
          example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        unit_id:
          type: number
          description: |
            RentEngine unit ID. Provide this, `unit_address`, `floorplan_id`,
            `multifamily_property_id`, or `account_id` alone.
            Access is scoped to the authenticated user's account; an unknown
            or inaccessible unit results in `404`.
          example: 12345
        unit_address:
          type: string
          minLength: 1
          description: |
            Free-text address that will be fuzzy-matched against units in the
            given `account_id`. Provide this, `unit_id`, `floorplan_id`,
            `multifamily_property_id`, or `account_id` alone.
            Returns `404` if no unit matches.
          example: 2516 Cecil Ave, Philadelphia PA
        floorplan_id:
          type: string
          format: uuid
          description: >
            Multifamily floorplan ID. Creates a floorplan-level lead rather than

            binding to a specific unit. Access is scoped to the authenticated

            user's account; an unknown or inaccessible floorplan results in
            `404`.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
        multifamily_property_id:
          type: string
          format: uuid
          description: |
            Multifamily building/community ID. Creates a building-level lead.
            Access is scoped to the authenticated user's account; an unknown
            or inaccessible property results in `404`.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
        notes:
          type: string
          description: Optional notes saved on the prospect record.
          example: Came in via partner site
        prospect_type:
          type: string
          enum:
            - Self
            - Agent
          description: |
            Optional. Whether the prospect is applying for themselves
            (`Self`) or is a real-estate agent representing a client (`Agent`).
            When omitted, the system infers a default from the source for
            agent-style sources (e.g. "MLS Agent", "Showing Smart").
          example: Self
        ai_enabled:
          type: boolean
          default: true
          description: |
            Whether RentEngine's AI may respond to messages from this prospect.
            Defaults to `true`. Set to `false` to opt this prospect out of
            AI replies (applied for their phone number within the account).
          example: true
        sms:
          type: object
          additionalProperties: false
          description: >-
            SMS controls. When omitted, the acknowledgement SMS is sent using
            the account's templates.
          properties:
            send:
              type: boolean
              default: true
              description: |
                Whether to send the acknowledgement SMS to the prospect.
                Defaults to `true`. Set to `false` to skip SMS entirely —
                no template is rendered and no message is dispatched.
              example: true
    CreateProspectResponse:
      type: object
      description: Result of a successful `POST /prospects` call.
      properties:
        prospect_id:
          type: number
          description: |
            ID of the prospect that was created — or, on re-engagement, the
            existing prospect that was reused.
          example: 98765
        unit_id:
          type:
            - number
            - 'null'
          description: >-
            ID of the resolved unit. `null` for floorplan, building, or
            account-level leads.
          example: 12345
        floorplan_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            Floorplan the prospect was created against. `null` when not a
            floorplan-level lead.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
        multifamily_property_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            Building the prospect was created against. `null` when not a
            building- or floorplan-level lead.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
        account_id:
          type:
            - string
            - 'null'
          format: uuid
          description: Account that owns the resolved property (or the account-level lead).
          example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        re_engaged:
          type: boolean
          description: |
            `true` when an existing prospect was reused (status 200);
            `false` when a brand-new prospect row was created (status 201).
          example: false
        sms_sent:
          type: boolean
          description: |
            `true` when the acknowledgement SMS was dispatched (or scheduled),
            `false` when SMS was skipped via `sms.send = false`.
          example: true
        ai_enabled:
          type: boolean
          description: Effective AI setting applied for this prospect.
          example: true
        message:
          type:
            - string
            - 'null'
          description: Human-readable workflow summary, useful for debugging.
          example: 'Workflow completed successfully - Prospect ID: 98765'
      required:
        - prospect_id
        - unit_id
        - re_engaged
        - sms_sent
        - ai_enabled
    PostGenerateLockboxCodeRequest:
      type: object
      properties:
        lockbox_id:
          type: string
          format: uuid
          description: >-
            ID of the lockbox. Either this, serial_number, or unit_id must be
            provided.
          example: 123e4567-e89b-12d3-a456-426614174000
        serial_number:
          type: string
          description: >-
            Serial number of the lockbox. Either this, lockbox_id, or unit_id
            must be provided.
          example: '1234567'
        unit_id:
          type: number
          description: >-
            ID of the unit where the lockbox is installed. Either this,
            lockbox_id, or serial_number must be provided.
          example: 12345
        date:
          type: string
          format: date
          description: Date for which the code should be valid (YYYY-MM-DD format)
          example: '2024-03-15'
        created_for:
          type: string
          description: >-
            Optional name or identifierof the person the code is being created
            for
          example: John Doe
        code_type:
          type: string
          description: >-
            Type of code to generate. Only relevant for Sentrilock lockboxes.
            All other boxes can only generate ACCESS codes.
          example: ACCESS
          default: ACCESS
          enum:
            - ACCESS
            - SHACKLE
      required:
        - date
      oneOf:
        - required:
            - lockbox_id
          title: By Lockbox ID
          description: Generate a code for a specific lockbox by providing the lockbox ID.
        - required:
            - serial_number
          title: By Serial Number
          description: >-
            Generate a code for a specific lockbox by providing the serial
            number.
        - required:
            - unit_id
          title: By Unit ID
          description: >-
            Generate a code for a specific unit by providing the unit ID that
            the box is installed on.
      additionalProperties: false
    Subteam:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Unique identifier for the subteam
          example: 123e4567-e89b-12d3-a456-426614174000
        name:
          type: string
          description: Name of the subteam
          example: Marketing Team
        account_id:
          type: string
          format: uuid
          description: ID of the account to associate with the subteam
          example: cd702dbe-bf32-41cc-83a2-efe00f495f04
      required:
        - id
        - name
    PrescreeningTemplate:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Unique identifier for the prescreening template
          example: 123e4567-e89b-12d3-a456-426614174000
        name:
          type: string
          description: Name of the prescreening template
          example: Default Template
        rules:
          type: object
          description: Rules for prescreening
          properties:
            minimumCreditScore:
              type: number
              description: Minimum credit score required
              example: 600
            minimumIncomeRentMultiplier:
              type: number
              description: Minimum income as multiple of rent
              example: 2.5
            enableVoIPPhoneVerification:
              type: boolean
              description: Whether to enable VoIP phone verification
              example: true
            enableIDVerification:
              type: boolean
              description: Whether to enable ID verification
              example: true
            enableSelfieVerification:
              type: boolean
              description: Whether to enable selfie verification
              example: true
            allowIDWithoutExpiryDate:
              type: boolean
              description: Whether to allow IDs without expiry date
              example: false
            allowIDExpiredInDays:
              type: number
              description: Number of days an expired ID is still acceptable
              example: 30
            minimumAge:
              type: number
              description: Minimum age required
              example: 18
            enableShowingLocationVerification:
              type: boolean
              description: Whether to enable showing location verification
              example: true
        questions:
          type: array
          items:
            type: object
            properties:
              fixedQuestionType:
                type: string
                description: Fixed question type (if any)
                example: housing_voucher
              question:
                type: string
                description: Question text
                example: Do you have a housing voucher (e.g. Section 8)?
              type:
                type: string
                description: Question type
                example: yes_no
              rejectAnswers:
                type: array
                items:
                  type: string
                  example: 'Yes'
                description: Answers that cause rejection
                example:
                  - 'Yes'
          description: List of prescreening questions
          example:
            - fixedQuestionType: housing_voucher
              question: Do you have a housing voucher (e.g. Section 8)?
              type: yes_no
              rejectAnswers: []
            - question: Have you been convicted of a felony?
              type: yes_no
              rejectAnswers:
                - 'Yes'
        isDefault:
          type: boolean
          description: Whether this is the default template
          example: true
        accountId:
          type: string
          description: ID of the account that owns the template
          example: 4b88ff32-8ba0-4bbf-8e60-c789909ac176
        createdAt:
          type: string
          format: date-time
          description: Timestamp when the template was created
          example: '2023-01-15T12:00:00Z'
        updatedAt:
          type: string
          format: date-time
          description: Timestamp when the template was last updated
          example: '2023-01-16T14:30:00Z'
      required:
        - id
        - name
        - rules
        - questions
        - isDefault
        - accountId
        - createdAt
        - updatedAt
    PostLeasingEventsRequest:
      type: object
      properties:
        events:
          type: array
          minItems: 1
          maxItems: 1
          description: >-
            List of leasing events to create. Only 1 event is supported at a
            time.
          items:
            oneOf:
              - $ref: '#/components/schemas/AssignToUserEvent'
              - $ref: '#/components/schemas/ApplicationReceivedEvent'
            discriminator:
              propertyName: event_type
              mapping:
                Assign to User: '#/components/schemas/AssignToUserEvent'
                Application Received: '#/components/schemas/ApplicationReceivedEvent'
      required:
        - events
    LeasingEventBase:
      type: object
      description: Fields common to every leasing event submitted via this endpoint.
      properties:
        prospect_id:
          type: number
          description: ID of the prospect associated with the event
          example: 12345
        source:
          type: string
          description: Source of the leasing event
          enum:
            - Phone Call
            - Text Message
            - Email
            - Facebook Message
            - WhatsApp
            - Other
            - Automation
          example: Other
        planned_date_time:
          type: string
          format: date-time
          description: Planned date/time for the event.
          example: '2026-04-30T18:00:00Z'
        next_follow_up:
          type: string
          format: date-time
          description: When to follow up next on this prospect.
          example: '2026-05-01T18:00:00Z'
        notes:
          type: string
          description: Optional notes for the event
          example: Assigning to primary agent
      required:
        - prospect_id
    AssignToUserEvent:
      allOf:
        - $ref: '#/components/schemas/LeasingEventBase'
        - type: object
          properties:
            event_type:
              type: string
              enum:
                - Assign to User
              example: Assign to User
              description: Discriminator value.
            context:
              $ref: '#/components/schemas/AssignToUserContext'
          required:
            - event_type
            - context
    ApplicationReceivedEvent:
      allOf:
        - $ref: '#/components/schemas/LeasingEventBase'
        - type: object
          properties:
            event_type:
              type: string
              enum:
                - Application Received
              example: Application Received
              description: Discriminator value.
            context:
              description: |
                Optional metadata about the externally-submitted application.
                May be omitted, `null`, or match `ApplicationReceivedContext`.
              oneOf:
                - $ref: '#/components/schemas/ApplicationReceivedContext'
                - type: 'null'
          required:
            - event_type
    AssignToUserContext:
      type: object
      additionalProperties: false
      required:
        - assignedToUserIds
      properties:
        assignedToUserIds:
          type: array
          minItems: 1
          items:
            type: string
            example: 1259ef6e-61ee-42cb-b6bd-7fe547569d7c
            format: uuid
          description: User IDs to assign to the prospect.
          example:
            - 1259ef6e-61ee-42cb-b6bd-7fe547569d7c
        applyActionInBulk:
          type: boolean
          description: >
            Apply the assignment to all prospects sharing the same phone number.

            Useful for assigning every unit a prospect is interested in to a
            single agent in one request.
          example: false
    ApplicationReceivedContext:
      type: object
      additionalProperties: false
      description: |
        Optional metadata about an externally-submitted application.
        All fields are optional, but unrecognized keys are rejected.
      properties:
        externalApplicationId:
          type: string
          maxLength: 255
          description: >-
            Caller's stable identifier for the application in their source
            system, useful for cross-referencing.
          example: app_abc_123
        externalSystem:
          type: string
          maxLength: 100
          description: >-
            Human-readable name of the source system (e.g. "Buildium",
            "AppFolio", "Custom CRM").
          example: Acme PMS
        applicantName:
          type: string
          maxLength: 255
          description: Full name of the applicant as known to the external system.
          example: Jane Doe
        applicantEmail:
          type: string
          format: email
          description: Applicant's email address.
          example: jane@example.com
        applicantPhone:
          type: string
          maxLength: 50
          description: >-
            Applicant's phone in any human-readable format. Not normalized
            server-side.
          example: +1 415 555 0100
        applicationUrl:
          type: string
          format: uri
          description: Deep link back to the application record in the external system.
          example: https://acme-pms.example.com/applications/app_abc_123
        applicationSubmittedAt:
          type: string
          format: date-time
          description: >-
            When the applicant submitted in the source system. Distinct from
            `planned_date_time`.
          example: '2026-04-30T15:04:05Z'
    SafeLeasingEventContext:
      type: object
      additionalProperties: false
      description: >
        Non-sensitive subset of a leasing event's `context`.

        Every field is optional; any key not listed here is stripped
        server-side.
      properties:
        created_from_bulk_update:
          type: boolean
          description: The event was created as part of a bulk action.
          example: false
        new_prospect:
          type: boolean
          description: A new prospect record was created by this event.
          example: true
        via_ai:
          type: boolean
          description: The event was created by RentEngine's AI agent.
          example: true
        next_event:
          type: string
          description: >-
            The chosen next step after a completed showing. One of the
            `event_type` values.
          example: Application Pending
        pm_escalations:
          type: string
          description: >-
            Free-text escalation note recorded for the property manager during a
            showing.
          example: Owner wants a higher deposit
        prospect_liked:
          type: string
          description: Showing feedback — what the prospect liked.
          example: Loved the natural light
        prospect_disliked:
          type: string
          description: Showing feedback — what the prospect did not like.
          example: Closet felt small
        maintenance_issues:
          type: string
          description: Showing feedback — maintenance issues noticed during the showing.
          example: Leaky kitchen faucet
        other_notes:
          type: string
          description: Showing feedback — other notes from the showing.
          example: Wants to apply this week
        apply_today_requirements:
          type: string
          description: Conditions under which the prospect said they would apply today.
          example: If rent drops by $50
        attached_photos:
          type: array
          description: URLs of photos attached to showing feedback.
          items:
            type: string
            example: https://cdn.example.com/showing/abc.jpg
            format: uri
          example:
            - https://cdn.example.com/showing/abc.jpg
        reason:
          type: string
          description: >
            Reason text. For failed/missed showings this is the showing-failure
            reason;

            for prescreen-rejected events it is the rejection reason.
          example: Prospect did not show up
        reschedule_for:
          type: string
          description: Requested reschedule time for a failed/missed showing.
          example: '2026-06-01T17:00:00Z'
        sub_reason:
          type: string
          description: Additional detail accompanying a prescreen rejection reason.
          example: Carrier flagged the number
        approval_method:
          type: string
          enum:
            - pm_bypass
          description: How a prescreen approval was granted, when not via the normal flow.
          example: pm_bypass
        zillow_tour_id:
          type: string
          description: Zillow's external tour identifier for a Zillow Instant Tour.
          example: ztour_123
        anti_fraud_disclaimer_acknowledged_at:
          type: string
          format: date-time
          description: When the anti-fraud disclaimer was acknowledged at showing start.
          example: '2026-05-27T10:00:00Z'
        agent_cancellation_reason:
          type: string
          description: Reason an agent gave for cancelling a showing.
          example: Unit no longer available
        tenant_cancellation_reason:
          type: string
          description: Reason a current tenant gave for cancelling a showing.
          example: Changed my mind
        created_by_user_role:
          type: string
          description: >-
            Role label of whoever / whatever created the event (e.g. "Property
            Manager", "AI Response").
          example: Property Manager
        rejection_method:
          type: string
          description: >-
            How a showing rejection or cancel was performed (parallels
            `approval_method`).
          example: pm_ui
        unit_address:
          type: string
          description: Address of the unit on an `Application Received` event payload.
          example: '1701 Prospect Ave #5i'
        stars:
          type: number
          description: Numeric showing rating (e.g. 1–5).
          example: 5
        agent_rating:
          type: number
          description: Numeric agent rating.
          example: 4
    TimeInterval:
      type: object
      properties:
        start:
          type: string
          format: date-time
          description: Start time of the showing window
          example: '2024-03-15T10:00:00Z'
        end:
          type: string
          format: date-time
          description: End time of the showing window
          example: '2024-03-15T10:30:00Z'
        invitedUserIdsArray:
          type: array
          items:
            type: string
            example: 1259ef6e-61ee-42cb-b6bd-7fe547569d7c
            format: uuid
          description: >-
            Array of user IDs invited for this showing window (for accompanied
            showings)
          example:
            - 1259ef6e-61ee-42cb-b6bd-7fe547569d7c
        showingMethodsAvailable:
          type: array
          items:
            type: string
            example: Accompanied
            enum:
              - Accompanied
              - Remote Guided
              - Remote Guided with Gated Access
              - Self Guided
          description: Available showing methods for this time slot
          example:
            - Accompanied
            - Self Guided
      required:
        - start
        - end
    UnitShowingAvailability:
      type: object
      properties:
        unitId:
          type: number
          description: ID of the unit
          example: 12345
        preferredShowingWindows:
          type: array
          items:
            $ref: '#/components/schemas/TimeInterval'
          description: Preferred showing windows (e.g., with stacking opportunities)
        availableShowingWindows:
          type: array
          items:
            $ref: '#/components/schemas/TimeInterval'
          description: Available showing windows
        showingMethod:
          type: string
          enum:
            - Accompanied
            - Remote Guided
            - Remote Guided with Gated Access
            - Self Guided
          description: The showing method configured for this unit
          example: Accompanied
        timezoneName:
          type: string
          description: Timezone name for the unit
          example: America/Chicago
        timezoneAbbreviation:
          type: string
          description: Timezone abbreviation
          example: CST
        unitStatus:
          type:
            - string
            - 'null'
          enum:
            - Available
            - Leased
            - On Hold
            - Archived
            - Withdrawn
            - Withdrawal Requested
            - Incomplete
            - Under Review
            - Expired
            - Price Analysis
          description: Current status of the unit
          example: Available
      required:
        - unitId
        - preferredShowingWindows
        - availableShowingWindows
        - showingMethod
        - timezoneName
        - timezoneAbbreviation
    PrescreenQuestionAnswer:
      type: object
      properties:
        question:
          type: string
          description: The question text
          example: Do you have a housing voucher (e.g. Section 8)?
        fixedQuestionType:
          type: string
          description: Fixed question type identifier
          example: housing_voucher
        type:
          type: string
          description: Question type
          example: yes_no
        answer:
          type: boolean
          description: The prospect's answer to the question
          example: false
      required:
        - question
        - type
        - answer
    ProspectData:
      type: object
      properties:
        firstName:
          type: string
          description: Prospect's first name
          example: John
        lastName:
          type: string
          description: Prospect's last name
          example: Doe
        email:
          type: string
          description: Prospect's email address
          example: john.doe@example.com
        phone:
          type: string
          description: Prospect's phone number (10 digits)
          example: '5551234567'
        creditScore:
          type: string
          description: Prospect's credit score range
          example: 700+
        income:
          type: string
          description: Prospect's household monthly income range
          example: $5000-$6000/month
        questionAnswers:
          type: array
          items:
            $ref: '#/components/schemas/PrescreenQuestionAnswer'
          description: Answers to prescreening questions
        prospectType:
          type: string
          enum:
            - Self
            - Agent
          description: Type of prospect
          example: Self
        voucherHolder:
          type: boolean
          description: Whether the prospect holds a housing voucher
          example: false
        licenseNumber:
          type: string
          description: License number (for agent prospects)
          example: ABC123
        notes:
          type: string
          description: Additional notes about the prospect
          example: Interested in 2BR units
      required:
        - firstName
        - lastName
        - email
        - phone
        - creditScore
        - income
        - questionAnswers
        - prospectType
    CreateShowingRequest:
      type: object
      properties:
        unitId:
          type: number
          description: ID of the unit to schedule the showing for
          example: 12345
        plannedForTime:
          type: string
          format: date-time
          description: Planned date and time for the showing (ISO 8601 format)
          example: '2024-03-15T10:00:00Z'
        prospectData:
          $ref: '#/components/schemas/ProspectData'
          description: Prospect information and prescreening data
        agentTk:
          type: string
          description: Agent token (required for agent prospects, must be 6 characters)
          example: ABC123
        desiredShowingMethod:
          type: string
          enum:
            - Accompanied
            - Self Guided
            - Remote Guided
            - Remote Guided with Gated Access
          description: Preferred showing method
          example: Accompanied
        files:
          type: array
          items:
            type: string
            example: documents/id-verification.pdf
          description: Array of file paths for uploaded documents
          example:
            - documents/id-verification.pdf
        livenessResult:
          type: object
          description: Liveness verification result from ID verification
        rescheduleEvent:
          type:
            - string
            - number
          description: ID of the event to reschedule (if rescheduling an existing showing)
          example: 67890
      required:
        - unitId
        - plannedForTime
        - prospectData
    CreateShowingResponse:
      type: object
      properties:
        statusText:
          type: string
          description: Success status message
          example: success
      required:
        - statusText
    RentalApplicationStatus:
      type: string
      description: Status of a rental application group or applicant
      enum:
        - Incomplete
        - Partially Submitted
        - Submitted
        - Awaiting Additional Info
        - Conditional Approval
        - Approved
        - Rejected
        - Payment Pending
        - Archived
        - Refunded
        - Moved In
      example: Submitted
    ReportStatus:
      type: string
      description: Status of an individual screening report (credit, criminal, eviction)
      enum:
        - ReportNotRequested
        - ReportRequested
        - ReportCompleted
        - ReportFailed
        - ReportPendingRetry
        - ReportExpired
      example: ReportCompleted
    RentalApplicationScreeningStatus:
      type: object
      description: Screening report state for an applicant (from TransUnion)
      properties:
        credit_status:
          oneOf:
            - $ref: '#/components/schemas/ReportStatus'
            - type: 'null'
        criminal_status:
          oneOf:
            - $ref: '#/components/schemas/ReportStatus'
            - type: 'null'
        eviction_status:
          oneOf:
            - $ref: '#/components/schemas/ReportStatus'
            - type: 'null'
        credit_updated_at:
          type:
            - string
            - 'null'
          format: date-time
          description: When the credit report was last updated
          example: '2024-06-15T14:30:00Z'
        criminal_updated_at:
          type:
            - string
            - 'null'
          format: date-time
          description: When the criminal report was last updated
          example: '2024-06-15T14:35:00Z'
        eviction_updated_at:
          type:
            - string
            - 'null'
          format: date-time
          description: When the eviction report was last updated
          example: '2024-06-15T14:40:00Z'
    RentalApplicantSummary:
      type: object
      description: >-
        Non-PII summary of an applicant, returned when listing or fetching a
        group
      properties:
        id:
          type: string
          format: uuid
          description: Rental application ID
          example: a1111111-1111-1111-1111-111111111111
        user_id:
          type:
            - string
            - 'null'
          format: uuid
          description: RentEngine user ID for the applicant
          example: b2222222-2222-2222-2222-222222222222
        status:
          $ref: '#/components/schemas/RentalApplicationStatus'
        progress:
          type:
            - string
            - 'null'
          description: Application completion progress marker
          example: income_details
        created_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-06-01T10:00:00Z'
        updated_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-06-10T15:30:00Z'
        screening:
          oneOf:
            - $ref: '#/components/schemas/RentalApplicationScreeningStatus'
            - type: 'null'
      required:
        - id
        - status
    RentalApplicationGroup:
      type: object
      description: >-
        A rental application group — one party applying to one unit, bundling 1+
        applicants
      properties:
        id:
          type: string
          format: uuid
          example: 123e4567-e89b-12d3-a456-426614174000
        unit_id:
          type:
            - integer
            - 'null'
          description: ID of the unit the group is applying to
          example: 12345
        account_id:
          type:
            - string
            - 'null'
          format: uuid
          description: RentEngine account that owns the unit
          example: c3333333-3333-3333-3333-333333333333
        subteam_id:
          type:
            - string
            - 'null'
          format: uuid
          example: d4444444-4444-4444-4444-444444444444
        status:
          $ref: '#/components/schemas/RentalApplicationStatus'
        submitted_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-06-05T09:00:00Z'
        move_in_date:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-08-01T00:00:00Z'
        primary_application_id:
          type:
            - string
            - 'null'
          format: uuid
          description: ID of the primary applicant's rental_applications row
          example: a1111111-1111-1111-1111-111111111111
        created_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-06-01T10:00:00Z'
        updated_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-06-10T15:30:00Z'
        applicants:
          type: array
          items:
            $ref: '#/components/schemas/RentalApplicantSummary'
      required:
        - id
        - status
        - applicants
    RentalApplicationDecisionEvent:
      type: object
      description: >-
        A decision recorded against the application group (approved, rejected,
        conditional, info request, etc.)
      properties:
        decision:
          type:
            - string
            - 'null'
          description: The decision recorded on the group
          example: Conditional Approval
        decided_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-06-20T16:00:00Z'
        context:
          type:
            - object
            - 'null'
          properties:
            info_required:
              type:
                - string
                - 'null'
              description: Populated when `decision` is `Awaiting Additional Info`
              example: Please provide proof of income
            approval_condition:
              type:
                - string
                - 'null'
              description: Populated when `decision` is `Conditional Approval`
              example: Requires additional security deposit
    RentalApplicationGroupDetail:
      allOf:
        - $ref: '#/components/schemas/RentalApplicationGroup'
        - type: object
          properties:
            decision_history:
              type: array
              description: Chronological decision history for the group, most recent first
              items:
                $ref: '#/components/schemas/RentalApplicationDecisionEvent'
          required:
            - decision_history
    PaginatedRentalApplicationGroups:
      type: object
      description: Paginated envelope for rental application groups
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/RentalApplicationGroup'
        page:
          type: object
          properties:
            limit:
              type: integer
              example: 50
            page_number:
              type: integer
              example: 0
            has_more:
              type: boolean
              example: true
            next_page_number:
              type:
                - integer
                - 'null'
              example: 1
          required:
            - limit
            - page_number
            - has_more
      required:
        - data
        - page
    PersonalDetails:
      type: object
      description: Personal details PII for an applicant
      properties:
        firstName:
          type: string
          example: Jane
        middleName:
          type: string
          example: Marie
        lastName:
          type: string
          example: Doe
        dob:
          type: string
          description: >-
            Date of birth (YYYY-MM-DD). After 180 days of inactivity only the
            birth year is returned (e.g. "1990").
          example: '1990-05-15'
        ssn:
          type: string
          description: Social security number. Omitted after 180 days of inactivity.
          example: 123-45-6789
        email:
          type: string
          format: email
          example: jane.doe@example.com
        housingVoucher:
          type: boolean
          example: false
        applicantDoesNotHaveSsn:
          type: boolean
          example: false
        fullName:
          type: string
          deprecated: true
          example: Jane Marie Doe
          description: Deprecated. Kept for backward compatibility.
    IncomeDetails:
      type: object
      description: A single income source for an applicant
      properties:
        incomeType:
          type: string
          example: Employment
        employerName:
          type: string
          example: Acme Corp
        monthlyIncome:
          type: string
          example: '5000'
        positionTitle:
          type: string
          example: Software Engineer
        supervisorName:
          type: string
          example: John Smith
        supervisorPhone:
          type: string
          example: '+15551234567'
        supervisorEmail:
          type: string
          example: john.smith@acme.com
        permitEmployerContact:
          type: string
          example: 'yes'
        address:
          type: string
          example: 123 Business Ave, Suite 100
        paymentMethod:
          type: string
          example: Direct Deposit
        startDate:
          type: string
          example: '2022-03-01'
        sourceName:
          type: string
          example: Freelance Consulting
        universityName:
          type: string
          example: State University
        benefitSource:
          type: string
          example: Social Security
        gradDate:
          type: string
          example: '2024-05-15'
        referenceCheckId:
          type: string
          example: ref-001
    AddressHistoryEntry:
      type: object
      description: A prior residence for an applicant
      properties:
        address:
          type: string
          example: 456 Oak Street, Apt 2B
        city:
          type: string
          example: Springfield
        state:
          type: string
          example: IL
        zipCode:
          type: string
          example: '62704'
        ownRent:
          type: string
          example: Rent
        moveInDate:
          type: string
          example: '2021-01-15'
        landlordName:
          type: string
          example: Robert Johnson
        landlordPhone:
          type: string
          example: '+15559876543'
        landlordEmail:
          type: string
          example: rjohnson@properties.com
        monthlyPayment:
          oneOf:
            - type: string
              example: '1500'
            - type: number
              example: 1500
        reasonForMoving:
          type: string
          example: Relocating for work
        permitLandlordContact:
          type: string
          example: 'yes'
        referenceCheckId:
          type: string
          example: ref-002
    CoApplicant:
      type: object
      properties:
        name:
          type: string
          example: Alex Doe
        type:
          type: string
          example: Co-signer
        phone:
          type: string
          example: '+15551112222'
    OtherOccupant:
      type: object
      properties:
        name:
          type: string
          example: Sam Doe
        dateOfBirth:
          type: string
          example: '2015-03-20'
    Pet:
      type: object
      properties:
        breed:
          type: string
          example: Golden Retriever
        name:
          type: string
          example: Buddy
        type:
          type: string
          example: Dog
        weight:
          type: string
          example: '65'
        isESA:
          type: boolean
          example: false
        esaDocumentation:
          type: array
          items:
            type: string
            example: esa-letter.pdf
    Vehicle:
      type: object
      properties:
        make:
          type: string
          example: Toyota
        model:
          type: string
          example: Camry
        year:
          type: string
          example: '2022'
        color:
          type: string
          example: Silver
        licensePlate:
          type: string
          example: ABC-1234
    CustomQuestion:
      type: object
      properties:
        question:
          type: string
          example: Do you have any pets?
        answer:
          oneOf:
            - type: string
              example: 'Yes'
            - type: array
              items:
                type: string
                example: 'Yes'
        question_type:
          type: string
          example: yes_no
        required:
          type: boolean
          example: true
        response_options:
          type: array
          items:
            type: string
            example: 'Yes'
    RentalApplicationDocument:
      type: object
      description: >-
        An entry in the documents listing on a rental application. Pass
        `document_id` to `GET /rental_applications/{id}/documents/{documentId}`
        to download the bytes.
      properties:
        document_id:
          type: string
          description: >
            Opaque identifier for the document. Treat as an opaque string —

            pass it back verbatim to `GET
            /rental_applications/{id}/documents/{documentId}`.


            The value is an AES-256-GCM encrypted token (not a JWT) minted

            fresh on every `GET /rental_applications/{id}` call, so the same

            underlying document produces a different `document_id` each time.

            Do **not** cache clients by this value or treat it as a stable

            key — it is safe to use once and should be re-fetched if needed

            again. Tokens remain valid as long as the underlying artifact

            exists and the server's signing key has not rotated.
          example: >-
            a9J7gI7Gc0Yo9CFhDg5-m9SpMKrUiNKDp5DbpgNiYdp9hzwoKDRwDArG57jwqrdJ9DTHll_M3fxAu_qKmcf66Odvt62turHgBRVGqW31ebJWIKsnrM3b-ys2B4ellJII
        kind:
          type: string
          enum:
            - app_doc
            - transunion_credit
            - transunion_criminal
            - transunion_eviction
            - id_front
            - id_back
            - id_selfie
          example: app_doc
          description: >
            Source + type of document.

            - `app_doc`: applicant-uploaded file (pay stub, bank statement,
            etc.)

            - `transunion_credit` / `transunion_criminal` /
            `transunion_eviction`: TransUnion screening report (PDF)

            - `id_front` / `id_back` / `id_selfie`: Stripe Identity verification
            artifacts (JPEG)
        doc_type:
          type: string
          description: >-
            Human-readable document category (e.g. "Pay Stub",
            "screening_report", "id_verification")
          example: screening_report
        filename:
          type:
            - string
            - 'null'
          description: Suggested filename for download
          example: transunion_credit_report.pdf
        status:
          type:
            - string
            - 'null'
          description: >-
            Status of the underlying artifact when applicable (e.g.
            ReportCompleted for screening reports)
          example: ReportCompleted
      required:
        - document_id
        - kind
        - doc_type
    RentalApplication:
      type: object
      description: Full rental application with PII and document listing
      properties:
        id:
          type: string
          format: uuid
          example: a1111111-1111-1111-1111-111111111111
        rental_application_group_id:
          type:
            - string
            - 'null'
          format: uuid
          example: 123e4567-e89b-12d3-a456-426614174000
        unit_id:
          type:
            - integer
            - 'null'
          example: 12345
        account_id:
          type:
            - string
            - 'null'
          format: uuid
          description: RentEngine account that owns the unit (denormalized from the unit)
          example: c3333333-3333-3333-3333-333333333333
        subteam_id:
          type:
            - string
            - 'null'
          format: uuid
          description: Subteam on the unit (denormalized from the unit)
          example: d4444444-4444-4444-4444-444444444444
        user_id:
          type:
            - string
            - 'null'
          format: uuid
          example: b2222222-2222-2222-2222-222222222222
        status:
          $ref: '#/components/schemas/RentalApplicationStatus'
        rental_application_group_status:
          oneOf:
            - $ref: '#/components/schemas/RentalApplicationStatus'
            - type: 'null'
          description: Denormalized copy of the parent group's status
        phone:
          type:
            - string
            - 'null'
          example: '+15551234567'
        move_in_date:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-08-01T00:00:00Z'
        progress:
          type:
            - string
            - 'null'
          example: income_details
        created_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-06-01T10:00:00Z'
        updated_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-06-10T15:30:00Z'
        personal_details:
          oneOf:
            - $ref: '#/components/schemas/PersonalDetails'
            - type: 'null'
        income_details:
          type: array
          items:
            $ref: '#/components/schemas/IncomeDetails'
        address_history:
          type: array
          items:
            $ref: '#/components/schemas/AddressHistoryEntry'
        co_applicants:
          type: array
          items:
            $ref: '#/components/schemas/CoApplicant'
        other_occupants:
          type: array
          items:
            $ref: '#/components/schemas/OtherOccupant'
        pets:
          type: array
          items:
            $ref: '#/components/schemas/Pet'
        vehicles:
          type: array
          items:
            $ref: '#/components/schemas/Vehicle'
        custom_questions:
          type: array
          items:
            $ref: '#/components/schemas/CustomQuestion'
        screening:
          oneOf:
            - $ref: '#/components/schemas/RentalApplicationScreeningStatus'
            - type: 'null'
        documents:
          type: array
          description: >-
            Documents available for this application — call the download
            endpoint with `document_id` to fetch the bytes
          items:
            $ref: '#/components/schemas/RentalApplicationDocument'
      required:
        - id
        - status
        - documents
    RentalApplicationGroupWebhookRecord:
      type: object
      description: Whitelisted columns emitted for rental_application_groups webhook events
      properties:
        id:
          type: string
          format: uuid
          example: 123e4567-e89b-12d3-a456-426614174000
        unit_id:
          type:
            - integer
            - 'null'
          example: 12345
        status:
          $ref: '#/components/schemas/RentalApplicationStatus'
        submitted_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-06-05T09:00:00Z'
        move_in_date:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-08-01T00:00:00Z'
        primary_application_id:
          type:
            - string
            - 'null'
          format: uuid
          example: a1111111-1111-1111-1111-111111111111
        created_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-06-01T10:00:00Z'
        updated_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-06-10T15:30:00Z'
    RentalApplicationGroupChanges:
      type: object
      description: >-
        Per-field diff included on UPDATE events. Each key is present only when
        that field changed.
      properties:
        status:
          type: object
          properties:
            from:
              oneOf:
                - $ref: '#/components/schemas/RentalApplicationStatus'
                - type: 'null'
            to:
              oneOf:
                - $ref: '#/components/schemas/RentalApplicationStatus'
                - type: 'null'
        unit_id:
          type: object
          properties:
            from:
              type:
                - integer
                - 'null'
              example: 12345
            to:
              type:
                - integer
                - 'null'
              example: 67890
        move_in_date:
          type: object
          properties:
            from:
              type:
                - string
                - 'null'
              format: date-time
              example: '2024-08-01T00:00:00Z'
            to:
              type:
                - string
                - 'null'
              format: date-time
              example: '2024-09-01T00:00:00Z'
        submitted_at:
          type: object
          properties:
            from:
              type:
                - string
                - 'null'
              format: date-time
              example: null
            to:
              type:
                - string
                - 'null'
              format: date-time
              example: '2024-06-05T09:00:00Z'
    RentalApplicationGroupWebhookPayload:
      type: object
      description: >
        Webhook payload for rental_application_groups events.


        The `event` field carries the *semantic* event name derived from the
        underlying change.

        When multiple fields change in a single UPDATE, `event` takes the
        highest-priority value

        (`group.state_changed` > `group.unit_changed` > `group.updated`) and
        `changes` contains

        the full diff so subscribers can detect compound transitions.
      properties:
        event:
          type: string
          enum:
            - group.created
            - group.state_changed
            - group.unit_changed
            - group.updated
          example: group.state_changed
          description: >
            Semantic event:

            - `group.created`: A new rental application group was created
            (INSERT)

            - `group.state_changed`: Status field transitioned (covers
            submitted, approved, rejected, etc.)

            - `group.unit_changed`: The unit assigned to the group changed

            - `group.updated`: Any other UPDATE without a semantic meaning
        event_id:
          type: string
          format: uuid
          description: >-
            Unique identifier for this delivery, suitable for subscriber-side
            idempotency
          example: e5555555-5555-5555-5555-555555555555
        occurred_at:
          type: string
          format: date-time
          example: '2024-06-15T14:30:00Z'
        type:
          type: string
          description: Underlying DB event. DELETE is never emitted for this table.
          enum:
            - INSERT
            - UPDATE
          example: UPDATE
        table:
          type: string
          enum:
            - rental_application_groups
          example: rental_application_groups
        record:
          oneOf:
            - $ref: '#/components/schemas/RentalApplicationGroupWebhookRecord'
            - type: 'null'
        old_record:
          oneOf:
            - $ref: '#/components/schemas/RentalApplicationGroupWebhookRecord'
            - type: 'null'
        changes:
          oneOf:
            - $ref: '#/components/schemas/RentalApplicationGroupChanges'
            - type: 'null'
      required:
        - event
        - event_id
        - occurred_at
        - type
        - table
    RentalApplicationWebhookRecord:
      type: object
      description: >-
        Whitelisted columns emitted for rental_applications webhook events (PII
        is never included in webhook payloads)
      properties:
        id:
          type: string
          format: uuid
          example: a1111111-1111-1111-1111-111111111111
        rental_application_group_id:
          type:
            - string
            - 'null'
          format: uuid
          example: 123e4567-e89b-12d3-a456-426614174000
        rental_application_group_status:
          oneOf:
            - $ref: '#/components/schemas/RentalApplicationStatus'
            - type: 'null'
        unit_id:
          type:
            - integer
            - 'null'
          example: 12345
        user_id:
          type:
            - string
            - 'null'
          format: uuid
          example: b2222222-2222-2222-2222-222222222222
        status:
          $ref: '#/components/schemas/RentalApplicationStatus'
        move_in_date:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-08-01T00:00:00Z'
        progress:
          type:
            - string
            - 'null'
          example: income_details
        created_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-06-01T10:00:00Z'
        updated_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-06-10T15:30:00Z'
    RentalApplicationChanges:
      type: object
      description: >-
        Per-field diff included on UPDATE events for rental_applications. Each
        key is present only when that field changed.
      properties:
        status:
          type: object
          properties:
            from:
              oneOf:
                - $ref: '#/components/schemas/RentalApplicationStatus'
                - type: 'null'
            to:
              oneOf:
                - $ref: '#/components/schemas/RentalApplicationStatus'
                - type: 'null'
        rental_application_group_status:
          type: object
          properties:
            from:
              oneOf:
                - $ref: '#/components/schemas/RentalApplicationStatus'
                - type: 'null'
            to:
              oneOf:
                - $ref: '#/components/schemas/RentalApplicationStatus'
                - type: 'null'
        progress:
          type: object
          properties:
            from:
              type:
                - string
                - 'null'
              example: personal_details
            to:
              type:
                - string
                - 'null'
              example: income_details
        unit_id:
          type: object
          properties:
            from:
              type:
                - integer
                - 'null'
              example: 12345
            to:
              type:
                - integer
                - 'null'
              example: 67890
    RentalApplicationWebhookPayload:
      type: object
      description: >
        Webhook payload for rental_applications events. PII is intentionally
        stripped —

        subscribers fetch `GET /rental_applications/{id}` to retrieve PII when
        needed.
      properties:
        event:
          type: string
          enum:
            - application.created
            - application.state_changed
            - application.updated
          example: application.state_changed
          description: >
            Semantic event:

            - `application.created`: A new applicant record was created on a
            group (INSERT).

            - `application.state_changed`: The applicant's status transitioned.

            - `application.updated`: Any other UPDATE.
        event_id:
          type: string
          format: uuid
          example: f6666666-6666-6666-6666-666666666666
        occurred_at:
          type: string
          format: date-time
          example: '2024-06-15T14:30:00Z'
        type:
          type: string
          description: Underlying DB event. DELETE is never emitted for this table.
          enum:
            - INSERT
            - UPDATE
          example: UPDATE
        table:
          type: string
          enum:
            - rental_applications
          example: rental_applications
        record:
          oneOf:
            - $ref: '#/components/schemas/RentalApplicationWebhookRecord'
            - type: 'null'
        old_record:
          oneOf:
            - $ref: '#/components/schemas/RentalApplicationWebhookRecord'
            - type: 'null'
        changes:
          oneOf:
            - $ref: '#/components/schemas/RentalApplicationChanges'
            - type: 'null'
      required:
        - event
        - event_id
        - occurred_at
        - type
        - table
    MarketToolLeadWebhookRecord:
      type: object
      description: Whitelisted columns emitted for Market Tool Widget lead webhook events.
      properties:
        id:
          type: string
          format: uuid
          example: 123e4567-e89b-12d3-a456-426614174000
        created_at:
          type: string
          format: date-time
          example: '2026-06-09T12:30:00Z'
        address:
          type: string
          example: 123 Main St, Austin, TX 78701
        zip_code:
          type:
            - string
            - 'null'
          example: '78701'
        beds:
          type:
            - number
            - 'null'
          example: 3
        baths:
          type:
            - number
            - 'null'
          example: 2.5
        property_type:
          type:
            - string
            - 'null'
          example: SINGLE_FAMILY
        sqft:
          type:
            - integer
            - 'null'
          example: 1800
        key_features:
          type:
            - string
            - 'null'
          example: Renovated kitchen, fenced yard
        lead_name:
          type: string
          example: Jane Doe
        lead_email:
          type: string
          format: email
          example: jane@example.com
        lead_phone:
          type:
            - string
            - 'null'
          example: '+15125551234'
        referrer_url:
          type:
            - string
            - 'null'
          example: https://example.com/listings/123
        utm_source:
          type:
            - string
            - 'null'
          example: google
        utm_medium:
          type:
            - string
            - 'null'
          example: cpc
        utm_campaign:
          type:
            - string
            - 'null'
          example: spring_2026
      required:
        - id
        - created_at
        - address
        - zip_code
        - beds
        - baths
        - property_type
        - sqft
        - key_features
        - lead_name
        - lead_email
        - lead_phone
        - referrer_url
        - utm_source
        - utm_medium
        - utm_campaign
    MarketToolLeadWebhookPayload:
      type: object
      description: |
        Webhook payload for Market Tool Widget lead events. INSERT-only — `type`
        is always `INSERT` and `old_record` is always null.
        The `record` contains a fixed set of listing and lead-contact fields.
      properties:
        type:
          type: string
          description: Underlying DB event. Only INSERT is emitted for this table.
          enum:
            - INSERT
          example: INSERT
        table:
          type: string
          enum:
            - pm_business_development_leads
          example: pm_business_development_leads
        record:
          $ref: '#/components/schemas/MarketToolLeadWebhookRecord'
        old_record:
          type: 'null'
          description: Always null — INSERT-only table.
          example: null
      required:
        - type
        - table
        - record
        - old_record
    ReportingPage:
      type: object
      description: Pagination metadata for intelligence reporting responses
      properties:
        limit:
          type: integer
          example: 100
        page_number:
          type: integer
          example: 0
        has_more:
          type: boolean
          example: true
        next_page_number:
          type:
            - integer
            - 'null'
          example: 1
      required:
        - limit
        - page_number
        - has_more
        - next_page_number
    ReportingProspectRow:
      type: object
      properties:
        prospect_id:
          type: integer
          example: 12
        property_address:
          type:
            - string
            - 'null'
          example: example
        created_at:
          type: string
          format: date-time
          example: '2024-01-15T09:30:00Z'
        status:
          type:
            - string
            - 'null'
          description: >-
            Prospect status. The internal "Ghosting" status is returned as
            "Unresponsive" to match the product UI.
          example: example
        name:
          type:
            - string
            - 'null'
          example: example
        phone_number:
          type:
            - string
            - 'null'
          example: example
        email:
          type:
            - string
            - 'null'
          example: example
        source:
          type:
            - string
            - 'null'
          example: example
        assigned_agents:
          type:
            - array
            - 'null'
          items:
            type: string
            example: Jane Smith
        showing_status:
          type:
            - string
            - 'null'
          example: example
        last_contacted_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-01-15T09:30:00Z'
        prospect_type:
          type:
            - string
            - 'null'
          example: example
    ReportingProspects:
      type: object
      description: Paginated envelope for prospect report rows
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ReportingProspectRow'
        page:
          $ref: '#/components/schemas/ReportingPage'
      required:
        - data
        - page
    ReportingUnitRow:
      type: object
      properties:
        unit_id:
          type: integer
          example: 12
        address:
          type:
            - string
            - 'null'
          example: example
        date_marked_available:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-01-15T09:30:00Z'
        status:
          type:
            - string
            - 'null'
          example: example
        earliest_move_in_date:
          type:
            - string
            - 'null'
          format: date
          example: '2024-01-15'
        earliest_showing_date:
          type:
            - string
            - 'null'
          format: date
          example: '2024-01-15'
        subteam_name:
          type:
            - string
            - 'null'
          example: example
        showing_method:
          type:
            - string
            - 'null'
          example: example
        showing_agents:
          type:
            - array
            - 'null'
          items:
            type: string
            example: Jane Smith
        lockbox_type:
          type:
            - string
            - 'null'
          example: example
        serial_number:
          type:
            - string
            - 'null'
          example: example
        deposit_amount:
          type:
            - number
            - 'null'
          example: 1500
        target_rental_rate:
          type:
            - number
            - 'null'
          example: 1500
        move_in_fees:
          type:
            - object
            - 'null'
        monthly_fees:
          type:
            - object
            - 'null'
        special_offer:
          type:
            - array
            - 'null'
          items:
            type: object
        bedrooms:
          type:
            - number
            - 'null'
          example: 1500
        bathrooms:
          type:
            - number
            - 'null'
          example: 1500
        prescreen_template_name:
          type:
            - string
            - 'null'
          example: example
        pet_policy:
          type:
            - string
            - 'null'
          example: example
        pet_terms:
          type:
            - string
            - 'null'
          example: example
        custom_app_link:
          type:
            - string
            - 'null'
          example: example
        included_utilities:
          type:
            - array
            - 'null'
          items:
            type: string
            example: Water
        property_owners:
          type:
            - array
            - 'null'
          items:
            type: object
        structured_access_instructions:
          type:
            - object
            - 'null'
        community_name:
          type:
            - string
            - 'null'
          example: example
        re_application_template_name:
          type:
            - string
            - 'null'
          example: example
    ReportingUnits:
      type: object
      description: Paginated envelope for unit report rows
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ReportingUnitRow'
        page:
          $ref: '#/components/schemas/ReportingPage'
      required:
        - data
        - page
    ProspectLeasingEventRow:
      type: object
      description: A single leasing event in a prospect's timeline.
      properties:
        id:
          type: integer
          format: int64
          example: 12345
        created_at:
          type: string
          format: date-time
          example: '2024-10-05T18:53:03.406168Z'
        event_type:
          type: string
          description: The type of leasing event (see the LeasingEvent `event_type` enum).
          example: Showing Complete
        source:
          type:
            - string
            - 'null'
          example: Showing Scheduler
        notes:
          type:
            - string
            - 'null'
          example: Prospect loved the unit
        planned_date_time:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-10-06T17:00:00Z'
        next_follow_up:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-10-08T17:00:00Z'
        created_by:
          type:
            - string
            - 'null'
          example: Public API
        prospect_id:
          type: integer
          format: int64
          description: ID of the prospect this event belongs to.
          example: 12345
        prospect_name:
          type:
            - string
            - 'null'
          description: The prospect's display name.
          example: Jane Doe
        phone_number:
          type:
            - string
            - 'null'
          description: The prospect's contact phone number.
          example: '+14155550100'
        email:
          type:
            - string
            - 'null'
          format: email
          description: The prospect's email.
          example: jane@example.com
        unit_of_interest:
          type:
            - integer
            - 'null'
          format: int64
          description: ID of the unit the prospect is interested in.
          example: 377
        property_address:
          type:
            - string
            - 'null'
          description: Formatted address of the unit the prospect is interested in.
          example: '1701 Prospect Ave #5i'
        floorplan_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            ID of the floorplan the prospect is interested in (multifamily
            leads). `null` for single-family leads.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
        multifamily_property_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            ID of the multifamily property the prospect is interested in. `null`
            for single-family leads.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
        context:
          description: Non-sensitive subset of the event's context, or `null`.
          oneOf:
            - $ref: '#/components/schemas/SafeLeasingEventContext'
            - type: 'null'
    ProspectLeasingEventList:
      type: object
      description: Paginated envelope for a prospect's leasing-event rows
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ProspectLeasingEventRow'
        page:
          $ref: '#/components/schemas/ReportingPage'
      required:
        - data
        - page
    ProspectCallRow:
      type: object
      description: A single call in a prospect's history.
      properties:
        created_at:
          type: string
          format: date-time
          example: '2024-10-05T18:53:03.406168Z'
        call_sid:
          type: string
          description: Twilio Call SID (unique identifier).
          example: CAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        prospect_id:
          type: integer
          format: int64
          description: ID of the prospect this call belongs to.
          example: 12345
        direction:
          type:
            - string
            - 'null'
          description: Call direction.
          enum:
            - inbound
            - outbound
            - outbound-dial
            - null
          example: inbound
        call_status:
          type:
            - string
            - 'null'
          description: |
            Call status (e.g. `queued`, `initiated`, `ringing`, `in-progress`,
            `completed`, `busy`, `no-answer`, `canceled`, `failed`,
            `missed-transfer`).
          example: completed
        call_duration:
          type:
            - integer
            - 'null'
          description: Duration of the call in seconds.
          example: 142
        from_number:
          type:
            - string
            - 'null'
          description: Caller's phone number (E.164).
          example: '+14155550100'
        to_number:
          type:
            - string
            - 'null'
          description: Called destination phone number (E.164).
          example: '+14155550199'
        prospect_name:
          type:
            - string
            - 'null'
          description: The prospect's display name.
          example: Jane Doe
        phone_number:
          type:
            - string
            - 'null'
          description: The prospect's contact phone number.
          example: '+14155550100'
        email:
          type:
            - string
            - 'null'
          format: email
          description: The prospect's email.
          example: jane@example.com
        unit_of_interest:
          type:
            - integer
            - 'null'
          format: int64
          description: ID of the unit the prospect is interested in.
          example: 377
        property_address:
          type:
            - string
            - 'null'
          description: Formatted address of the unit the prospect is interested in.
          example: '1701 Prospect Ave #5i'
        floorplan_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            ID of the floorplan the prospect is interested in (multifamily
            leads). `null` for single-family leads.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
        multifamily_property_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            ID of the multifamily property the prospect is interested in. `null`
            for single-family leads.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
    ProspectCallList:
      type: object
      description: Paginated envelope for a prospect's call rows
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ProspectCallRow'
        page:
          $ref: '#/components/schemas/ReportingPage'
      required:
        - data
        - page
    ProspectMessageRow:
      type: object
      description: A single SMS message in a prospect's history.
      properties:
        created_at:
          type: string
          format: date-time
          example: '2024-10-05T18:53:03.406168Z'
        message_sid:
          type: string
          description: Twilio Message SID (unique identifier).
          example: SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        prospect_id:
          type: integer
          format: int64
          description: ID of the prospect this message belongs to.
          example: 12345
        direction:
          type:
            - string
            - 'null'
          description: Message direction.
          enum:
            - inbound
            - outbound
            - null
          example: inbound
        body:
          type:
            - string
            - 'null'
          description: Message text content.
          example: Hi, I'm interested in your listing!
        status:
          type:
            - string
            - 'null'
          description: >-
            Delivery status (e.g. `queued`, `sent`, `delivered`, `failed`,
            `undelivered`).
          example: delivered
        from_number:
          type:
            - string
            - 'null'
          description: Sender's phone number (E.164).
          example: '+14155550100'
        to_number:
          type:
            - string
            - 'null'
          description: Recipient's phone number (E.164).
          example: '+14155550199'
        num_media:
          type:
            - integer
            - 'null'
          description: Number of media attachments on this message.
          example: 0
        media_content_types:
          type:
            - array
            - 'null'
          description: >-
            MIME types of any media attachments (URLs themselves are not
            exposed).
          items:
            type: string
            example: image/jpeg
          example:
            - image/jpeg
        prospect_name:
          type:
            - string
            - 'null'
          description: The prospect's display name.
          example: Jane Doe
        phone_number:
          type:
            - string
            - 'null'
          description: The prospect's contact phone number.
          example: '+14155550100'
        email:
          type:
            - string
            - 'null'
          format: email
          description: The prospect's email.
          example: jane@example.com
        unit_of_interest:
          type:
            - integer
            - 'null'
          format: int64
          description: ID of the unit the prospect is interested in.
          example: 377
        property_address:
          type:
            - string
            - 'null'
          description: Formatted address of the unit the prospect is interested in.
          example: '1701 Prospect Ave #5i'
        floorplan_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            ID of the floorplan the prospect is interested in (multifamily
            leads). `null` for single-family leads.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
        multifamily_property_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            ID of the multifamily property the prospect is interested in. `null`
            for single-family leads.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
    ProspectMessageList:
      type: object
      description: Paginated envelope for a prospect's message rows
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ProspectMessageRow'
        page:
          $ref: '#/components/schemas/ReportingPage'
      required:
        - data
        - page
    PostNoteRequest:
      type: object
      additionalProperties: false
      required:
        - prospect_id
        - note
      properties:
        prospect_id:
          type: integer
          format: int64
          minimum: 1
          description: ID of the prospect the note is being recorded on.
          example: 12345
        note:
          type: string
          minLength: 1
          maxLength: 4000
          description: Free-text note about the prospect / interaction.
          example: Spoke with prospect about renewal
        pinned:
          type: boolean
          default: false
          description: >-
            Whether to pin the note in the Command Center. Pinning un-pins the
            prospect's other notes — a prospect has at most one pinned note.
            Defaults to false. First notes are always pinned.
          example: false
    NoteRow:
      type: object
      description: A single note on a prospect.
      properties:
        id:
          type: string
          format: uuid
          example: 50326063-7628-49f5-ae52-687abc02ccec
        prospect_id:
          type:
            - integer
            - 'null'
          format: int64
          description: ID of the prospect the note is attached to, when known.
          example: 12345
        note:
          type:
            - string
            - 'null'
          description: Free-text note about the prospect.
          example: Spoke with prospect about renewal
        pinned:
          type: boolean
          description: >-
            Whether the note is pinned in the Command Center. Set on creation
            via the `pinned` request field (defaults to false). First notes are
            always pinned.
          example: false
        created_at:
          type: string
          format: date-time
          example: '2026-05-29T10:00:00Z'
        prospect_name:
          type:
            - string
            - 'null'
          description: The prospect's display name.
          example: Jane Doe
        phone_number:
          type:
            - string
            - 'null'
          description: The prospect's contact phone number.
          example: '+14155550100'
        email:
          type:
            - string
            - 'null'
          format: email
          description: The prospect's email.
          example: jane@example.com
        unit_of_interest:
          type:
            - integer
            - 'null'
          format: int64
          description: ID of the unit the prospect is interested in.
          example: 377
        property_address:
          type:
            - string
            - 'null'
          description: Formatted address of the unit the prospect is interested in.
          example: '1701 Prospect Ave #5i'
        floorplan_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            ID of the floorplan the prospect is interested in (multifamily
            leads). `null` for single-family leads.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
        multifamily_property_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            ID of the multifamily property the prospect is interested in. `null`
            for single-family leads.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
    NotesList:
      type: object
      description: Paginated envelope for note rows
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/NoteRow'
        page:
          $ref: '#/components/schemas/ReportingPage'
      required:
        - data
        - page
    PostFollowupRequest:
      type: object
      additionalProperties: false
      required:
        - prospect_id
        - note
      properties:
        prospect_id:
          type: integer
          format: int64
          minimum: 1
          example: 12345
        note:
          type: string
          minLength: 1
          maxLength: 4000
          description: Free-text note for the follow-up.
          example: Call about rent application
        remind_at:
          type:
            - string
            - 'null'
          format: date-time
          description: |
            Future timestamp at which a push-notification reminder should fire.
            Must be strictly in the future.
          example: '2026-06-01T17:00:00Z'
        channel:
          type:
            - string
            - 'null'
          enum:
            - SMS
            - PHONE
            - EMAIL
            - OTHER
            - null
          description: Optional channel hint for how the user plans to follow up.
          example: PHONE
    FollowupRow:
      type: object
      description: A single follow-up (scheduled reminder) on a prospect.
      properties:
        id:
          type: string
          format: uuid
          example: d801337c-cf9f-4ba8-b947-2bd131769ee7
        prospect_id:
          type:
            - integer
            - 'null'
          format: int64
          description: ID of the prospect the follow-up is attached to, when known.
          example: 12345
        note:
          type:
            - string
            - 'null'
          description: Free-text note for the follow-up.
          example: Call about rent application
        remind_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            Scheduled reminder timestamp, when set. `null` if no reminder is
            queued.
          example: '2026-06-01T17:00:00Z'
        channel:
          type:
            - string
            - 'null'
          description: Channel hint for how the user plans to follow up, when set.
          enum:
            - SMS
            - PHONE
            - EMAIL
            - OTHER
            - null
          example: PHONE
        created_at:
          type: string
          format: date-time
          example: '2026-05-29T10:00:00Z'
        prospect_name:
          type:
            - string
            - 'null'
          description: The prospect's display name.
          example: Jane Doe
        phone_number:
          type:
            - string
            - 'null'
          description: The prospect's contact phone number.
          example: '+14155550100'
        email:
          type:
            - string
            - 'null'
          format: email
          description: The prospect's email.
          example: jane@example.com
        unit_of_interest:
          type:
            - integer
            - 'null'
          format: int64
          description: ID of the unit the prospect is interested in.
          example: 377
        property_address:
          type:
            - string
            - 'null'
          description: Formatted address of the unit the prospect is interested in.
          example: '1701 Prospect Ave #5i'
        floorplan_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            ID of the floorplan the prospect is interested in (multifamily
            leads). `null` for single-family leads.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
        multifamily_property_id:
          type:
            - string
            - 'null'
          format: uuid
          description: >-
            ID of the multifamily property the prospect is interested in. `null`
            for single-family leads.
          example: 6eac2077-a67e-4888-846b-6ff15015c855
    FollowupsList:
      type: object
      description: Paginated envelope for follow-up rows
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/FollowupRow'
        page:
          $ref: '#/components/schemas/ReportingPage'
      required:
        - data
        - page
    ReportingShowingRow:
      type: object
      properties:
        showing_id:
          type: integer
          example: 12
        prospect_id:
          type:
            - integer
            - 'null'
          example: 12
        property_address:
          type:
            - string
            - 'null'
          example: example
        timezone:
          type:
            - string
            - 'null'
          example: example
        prospect_name:
          type:
            - string
            - 'null'
          example: example
        phone_number:
          type:
            - string
            - 'null'
          example: example
        email:
          type:
            - string
            - 'null'
          example: example
        status:
          type:
            - string
            - 'null'
          example: example
        feedback:
          type:
            - string
            - 'null'
          description: >-
            Showing feedback. Falls back to structured feedback context when no
            free-text note was recorded.
          example: example
        created_at:
          type: string
          format: date-time
          example: '2024-01-15T09:30:00Z'
        showing_agent:
          type:
            - string
            - 'null'
          example: example
        planned_date_time:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-01-15T09:30:00Z'
        prospect_type:
          type:
            - string
            - 'null'
          example: example
        is_rescheduled:
          type:
            - boolean
            - 'null'
          description: >-
            Whether a canceled showing was canceled as part of a reschedule.
            Null when the showing was not canceled.
          example: true
        is_auto_canceled:
          type:
            - boolean
            - 'null'
          description: >-
            Whether a canceled showing was auto-canceled by the system. Null
            when the showing was not canceled.
          example: true
        canceled_by:
          type:
            - string
            - 'null'
          description: >-
            Who canceled the showing ("Current tenant" for tenant-acceptance
            cancellations). Null when the showing was not canceled.
          example: example
        cancellation_reason:
          type:
            - string
            - 'null'
          description: Reason the showing was canceled. Null when not canceled.
          example: example
        prospect_current_status:
          type:
            - string
            - 'null'
          example: example
        updated_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-01-15T09:30:00Z'
    ReportingShowings:
      type: object
      description: Paginated envelope for showing report rows
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ReportingShowingRow'
        page:
          $ref: '#/components/schemas/ReportingPage'
      required:
        - data
        - page
    ReportingPrescreeningRow:
      type: object
      properties:
        prescreen_id:
          type: integer
          example: 12
        property_address:
          type:
            - string
            - 'null'
          example: example
        prospect_id:
          type:
            - integer
            - 'null'
          example: 12
        prospect_name:
          type:
            - string
            - 'null'
          example: example
        phone_number:
          type:
            - string
            - 'null'
          example: example
        email:
          type:
            - string
            - 'null'
          example: example
        created_at:
          type: string
          format: date-time
          example: '2024-01-15T09:30:00Z'
        prescreen_template_name:
          type:
            - string
            - 'null'
          example: example
        status:
          type:
            - string
            - 'null'
          example: example
        prescreen_answers:
          type:
            - object
            - 'null'
          description: Template-specific prescreen answers keyed by question.
    ReportingPrescreening:
      type: object
      description: Paginated envelope for prescreening report rows
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ReportingPrescreeningRow'
        page:
          $ref: '#/components/schemas/ReportingPage'
      required:
        - data
        - page
    ReportingCallRow:
      type: object
      properties:
        name:
          type:
            - string
            - 'null'
          example: example
        created_at:
          type: string
          format: date-time
          example: '2024-01-15T09:30:00Z'
        user_id:
          type:
            - string
            - 'null'
          example: example
        call_direction:
          type:
            - string
            - 'null'
          example: example
        status:
          type:
            - string
            - 'null'
          example: example
        call_sid:
          type:
            - string
            - 'null'
          example: example
        contact_number:
          type:
            - string
            - 'null'
          example: example
        call_duration:
          type:
            - integer
            - 'null'
          description: Call duration in seconds.
          example: 12
        prospect_name:
          type:
            - string
            - 'null'
          example: example
    ReportingCalls:
      type: object
      description: Paginated envelope for call report rows
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ReportingCallRow'
        page:
          $ref: '#/components/schemas/ReportingPage'
      required:
        - data
        - page
    ReportingMarketingSourceRow:
      type: object
      properties:
        source_key:
          type:
            - string
            - 'null'
          example: example
        source_display:
          type:
            - string
            - 'null'
          example: example
        leads:
          type: integer
          example: 12
        showings_scheduled:
          type: integer
          example: 12
        showings_completed:
          type: integer
          example: 12
        upcoming_showings:
          type: integer
          example: 12
        applications_requested:
          type: integer
          example: 12
        applications_submitted:
          type: integer
          example: 12
        apps_approved:
          type: integer
          example: 12
        rejected_prescreens:
          type: integer
          example: 12
    ReportingMarketingSources:
      type: object
      description: Paginated envelope for marketing-source report rows
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ReportingMarketingSourceRow'
        page:
          $ref: '#/components/schemas/ReportingPage'
      required:
        - data
        - page
    ReportingApplicationRow:
      type: object
      properties:
        application_group_id:
          type: string
          format: uuid
          example: 123e4567-e89b-12d3-a456-426614174000
        lead_applicant:
          type:
            - string
            - 'null'
          example: example
        address:
          type:
            - string
            - 'null'
          example: example
        status:
          type:
            - string
            - 'null'
          example: example
        refunded_amount:
          type:
            - number
            - 'null'
          example: 1500
        submitted_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-01-15T09:30:00Z'
        started_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-01-15T09:30:00Z'
        processed_at:
          type:
            - string
            - 'null'
          format: date-time
          example: '2024-01-15T09:30:00Z'
        processing_time_hours:
          type:
            - number
            - 'null'
          example: 1500
        subteam_name:
          type:
            - string
            - 'null'
          example: example
        agent_name:
          type:
            - string
            - 'null'
          example: example
        num_applicants:
          type:
            - integer
            - 'null'
          example: 12
        income_details:
          type:
            - object
            - 'null'
        current_workflow_step:
          type:
            - string
            - 'null'
          example: example
        current_workflow_owner:
          type:
            - string
            - 'null'
          example: example
    ReportingApplications:
      type: object
      description: Paginated envelope for application report rows
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ReportingApplicationRow'
        page:
          $ref: '#/components/schemas/ReportingPage'
      required:
        - data
        - page
    ReportingAgentPerformanceRow:
      type: object
      properties:
        agent_user_id:
          type:
            - string
            - 'null'
          format: uuid
          example: 123e4567-e89b-12d3-a456-426614174000
        agent_name:
          type:
            - string
            - 'null'
          example: example
        showings_scheduled:
          type: integer
          example: 12
        showings_completed:
          type: integer
          example: 12
        upcoming_showings:
          type: integer
          example: 12
        rescheduled_showings:
          type: integer
          example: 12
        auto_canceled_showings:
          type: integer
          example: 12
        prospect_canceled_showings:
          type: integer
          example: 12
        agent_canceled_showings:
          type: integer
          example: 12
        missed_showings:
          type: integer
          example: 12
        failed_showings:
          type: integer
          example: 12
        apps_requested:
          type: integer
          example: 12
        apps_submitted:
          type: integer
          example: 12
        apps_approved:
          type: integer
          example: 12
        calls_made:
          type: integer
          example: 12
        calls_answered:
          type: integer
          example: 12
        messages_sent:
          type: integer
          example: 12
        inbound_calls_missed:
          type: integer
          example: 12
        median_call_minutes:
          type:
            - number
            - 'null'
          example: 4.2
        median_hours_to_first_contact:
          type:
            - number
            - 'null'
          example: 2.3
        unanswered_prospects:
          type: integer
          example: 12
        showings_with_feedback_pct:
          type:
            - number
            - 'null'
          example: 69
        prospects_contacted:
          type: integer
          example: 12
    ReportingAgentPerformance:
      type: object
      description: Paginated envelope for agent-performance report rows
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ReportingAgentPerformanceRow'
        page:
          $ref: '#/components/schemas/ReportingPage'
      required:
        - data
        - page
  parameters:
    PaginationLimit:
      name: limit
      in: query
      description: Maximum number of items to return per page (default 50, max 100)
      schema:
        type: integer
        default: 50
        minimum: 1
        maximum: 100
        example: 25
    PaginationPage:
      name: page_number
      in: query
      description: Page number for pagination (0-indexed, default 0)
      schema:
        type: integer
        default: 0
        minimum: 0
        example: 1
    ReportingAccountIds:
      name: account_ids
      in: query
      required: true
      description: |
        Comma-separated account IDs to query. The token may only query accounts
        its user belongs to; requesting any other account yields 403.
      schema:
        type: array
        items:
          type: string
          example: 123e4567-e89b-12d3-a456-426614174000
          format: uuid
        minItems: 1
      style: form
      explode: false
    ReportingSubteamIds:
      name: subteam_ids
      in: query
      required: false
      description: Optional comma-separated subteam IDs to filter by.
      schema:
        type: array
        items:
          type: string
          example: 123e4567-e89b-12d3-a456-426614174000
          format: uuid
      style: form
      explode: false
    ReportingMultifamilyPropertyIds:
      name: multifamily_property_ids
      in: query
      required: false
      description: Optional comma-separated multifamily property IDs to filter by.
      schema:
        type: array
        items:
          type: string
          example: 123e4567-e89b-12d3-a456-426614174000
          format: uuid
      style: form
      explode: false
    ReportingStart:
      name: start
      in: query
      required: true
      description: >-
        Start of the reporting period (ISO 8601, with timezone offset). The span
        between `start` and `end` must not exceed 32 days.
      schema:
        type: string
        format: date-time
        example: '2024-01-01T00:00:00Z'
    ReportingEnd:
      name: end
      in: query
      required: true
      description: >-
        End of the reporting period (ISO 8601, with timezone offset). Must be on
        or after `start`, and within 32 days of it.
      schema:
        type: string
        format: date-time
        example: '2024-01-31T23:59:59Z'
    ReportingLimit:
      name: limit
      in: query
      description: Maximum number of rows to return per page (default 100, max 2000).
      schema:
        type: integer
        default: 100
        minimum: 1
        maximum: 2000
        example: 100
    ReportingPageNumber:
      name: page_number
      in: query
      description: Page number for pagination (0-indexed, default 0).
      schema:
        type: integer
        default: 0
        minimum: 0
        example: 0
  responses:
    BadRequest:
      description: Bad request - invalid input parameters or request body
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Invalid request parameters
            details:
              - keyword: required
                dataPath: ''
                schemaPath: '#/required'
                params:
                  missingProperty: account_id
                message: should have required property 'account_id'
    NotFound:
      description: Not found.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Unauthorized - missing or invalid Bearer token
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Unauthorized - Missing or invalid Authorization header
            details:
              - message: Bearer token is required
    Forbidden:
      description: Forbidden - the token cannot access one or more requested accounts
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: One or more account_ids are not accessible to this token
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Internal server error
            details:
              - message: An unexpected error occurred
    ServiceUnavailable:
      description: >-
        Service temporarily unavailable - the underlying query exceeded its time
        budget (Postgres statement timeout). Safe to retry after a short
        backoff.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Service temporarily unavailable. Please try again later.
    TooManyRequests:
      description: Rate limit exceeded - too many requests in the current time window
      headers:
        X-RateLimit-Limit:
          description: Maximum requests allowed in the current window
          schema:
            type: integer
            example: 100
        X-RateLimit-Remaining:
          description: Number of requests remaining in the current window
          schema:
            type: integer
            example: 0
        X-RateLimit-Reset:
          description: Unix timestamp (milliseconds) when the rate limit resets
          schema:
            type: integer
            example: 1706745600000
        Retry-After:
          description: Number of seconds to wait before retrying
          schema:
            type: integer
            example: 45
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: Too Many Requests
              message:
                type: string
                example: Rate limit exceeded. Please try again later.
              retryAfter:
                type: integer
                description: Seconds until rate limit resets
                example: 45
          example:
            error: Too Many Requests
            message: Rate limit exceeded. Please try again later.
            retryAfter: 45
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        JWT Bearer token authentication. Use format 'Bearer {token}' in the
        Authorization header.
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: >-
        API key authentication for webhooks. The key is defined when setting up
        the webhook in the [developer
        portal](https://app.rentengine.io/developer/portal) and is delivered in
        the `X-API-Key` header on every webhook request.
tags:
  - name: Reporting
    description: Operations for retrieving leasing performance reports and analytics
  - name: Lockboxes
    description: Operations for managing lockboxes
  - name: Lockbox Events
    description: Operations for tracking and creating lockbox events
  - name: Lockbox Installations
    description: Operations for retrieving lockbox installations
  - name: Units
    description: Operations for managing rental units
  - name: Market Tool
    description: >-
      Normalized, provider-free rental market comparables. Metered — each
      successful call incurs a per-call charge (see Rate Limiting).
  - name: Prospects
    description: Events related to prospective tenants
  - name: Multifamily Properties
    description: >-
      Operations for managing multifamily properties. Multifamily properties are
      used to syndicate large properties with paid advertising contracts to the
      paid rental feeds. For example, paid adverising contracts are required for
      the Zillow network if the building has more than 24 units, and for the
      Apartments.com if the building has more than 4 units. Other ILSs have
      different thresholds.
  - name: Floorplans
    description: >-
      Operations for managing floorplans associated with multifamily properties.
      Floorplans are used to syndicate units to the paid rental feeds for paid
      advertising contracts. They must be used in conjunction with a multifamily
      property.
  - name: Leasing Events
    description: Events related to leasing events
  - name: Calls
    description: Operations for retrieving a prospect's call history
  - name: Messages
    description: Operations for retrieving a prospect's SMS history
  - name: Subteams
    description: Operations for managing subteams
  - name: Prescreening Templates
    description: >-
      Operations for managing prescreening templates used for prospect
      qualification
  - name: Showings
    description: Operations for managing showing availability and scheduling
  - name: Marketing
    description: >-
      Operations for retrieving marketing listings for external display and
      embedding on websites
  - name: Rental Applications
    description: >-
      Operations for rental application groups, applicant records (with PII),
      and application documents.
  - name: Notes & Follow-ups
    description: >-
      Operations for reading and creating a prospect's notes and follow-up
      reminders.
webhooks:
  LeasingEvents:
    post:
      summary: Leasing events
      description: |
        Webhook for leasing events (creates, updates, deletes).
        Leasing events of the following types are supported:
        - "New"
        - "Contacted, Awaiting Information"
        - "Showing Desired"
        - "Showing Scheduled"
        - "Showing Complete"
        - "Missed Showing"
        - "Ghosting"
        - "Application Sent to Prospect"
        - "Application Received"
        - "Application Pending"
        - "Application in Owner Review"
        - "Application Approved"
        - "Withdrawn"
        - "Application Rejected"
        - "Prescreen Submitted"
        - "Prescreen Rejected - Self reported credit"
        - "Prescreen Rejected - Self reported income"
        - "Prescreen Rejected - ID Verification"
        - "Prescreen Approved"
        - "Looking too early"
        - "Lease out for signing"
        - "Lease Signed"
        - "Deposit Received"
        - "Move-in Scheduled"
        - "Moved In"
        - "Unit of Interest Unavailable"
        - "Not Interested"
        - "Duplicate Lead"
        - "Still Deciding"
        - "HOA Application Sent To Prospect"
        - "HOA Application Submitted"
        - "HOA Application Approved"
        - "HOA Application Rejected"
        - "Showing Failed"
        - "Showing Canceled"
        - "Showing Confirmed"
        - "Arrived for Showing"
        - "Showing Started"
        - "Log Note"
        - "Assign to User"
        - "Blocklist Prospect"
        - "Unblock Prospect"
        - "Reassign Showing"
      operationId: receive-leasing-events
      tags:
        - Leasing Events
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookPayload'
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
  LockboxEvents:
    post:
      summary: Lockbox events
      operationId: receive-lockbox-events
      tags:
        - Lockbox Events
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookPayload'
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
  ProspectsEvents:
    post:
      summary: Prospects
      operationId: receive-prospects-updates
      tags:
        - Prospects
      description: |
        Webhook for prospect changes (creates, updates, deletes).
        Only the below fields are included in the record and old_record objects.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/WebhookPayload'
                - type: object
                  properties:
                    record:
                      type: object
                      properties:
                        id:
                          type: string
                          format: uuid
                          description: Unique identifier for the prospect
                          example: 123e4567-e89b-12d3-a456-426614174000
                        created_at:
                          type: string
                          format: date-time
                          description: When the prospect was created
                          example: '2023-01-15T12:00:00Z'
                        name:
                          type: string
                          description: Prospect's name
                          example: John Doe
                        phone:
                          type: string
                          description: Prospect's phone number
                          example: '+15551234567'
                        email:
                          type: string
                          description: Prospect's email address
                          example: test@gmail.com
                        unit_of_interest:
                          type: string
                          description: Unit the prospect is interested in
                          example: '123'
                        status:
                          type: string
                          description: Current status of the prospect
                          example: Showing Scheduled
                        source:
                          type: string
                          description: Where the prospect came from
                          example: Zillow
                        notes:
                          type: string
                          description: Notes about the prospect
                          example: Interested in 2BR units
                        prescreened:
                          type: boolean
                          description: Whether the prospect has been prescreened
                          example: true
                        voucher_holder:
                          type: boolean
                          description: Whether the prospect holds a housing voucher
                          example: false
                        normalized_phone_number_generated:
                          type: string
                          description: Normalized phone number if normalizable. Else null.
                          example: '+15551234567'
                        license_number:
                          type: string
                          description: License number if applicable
                          example: ABC123
                        prospect_type:
                          type: string
                          description: Type of prospect
                          enum:
                            - Self
                            - Agent
                          example: Agent
                        updated_at:
                          type: string
                          format: date-time
                          description: When the prospect was last updated
                          example: '2023-01-16T14:30:00Z'
                        assigned_to_user_ids:
                          type: array
                          items:
                            type: string
                            example: 123e4567-e89b-12d3-a456-426614174001
                            format: uuid
                          description: IDs of users assigned to this prospect
                          example:
                            - 123e4567-e89b-12d3-a456-426614174001
                    old_record:
                      type: object
                      properties:
                        id:
                          type: string
                          format: uuid
                          description: Unique identifier for the prospect
                          example: 123e4567-e89b-12d3-a456-426614174000
                        created_at:
                          type: string
                          format: date-time
                          description: When the prospect was created
                          example: '2023-01-15T12:00:00Z'
                        name:
                          type: string
                          description: Prospect's name
                          example: John Doe
                        phone:
                          type: string
                          description: Prospect's phone number
                          example: '+15551234567'
                        email:
                          type: string
                          description: Prospect's email address
                          example: john.doe@example.com
                        unit_of_interest:
                          type: string
                          description: Unit the prospect is interested in
                          example: '123'
                        status:
                          type: string
                          description: Current status of the prospect
                          example: Not Interested
                        source:
                          type: string
                          description: Where the prospect came from
                          example: RentEngine
                        notes:
                          type: string
                          description: Notes about the prospect
                          example: Interested in 2BR units
                        prescreened:
                          type: boolean
                          description: Whether the prospect has been prescreened
                          example: false
                        voucher_holder:
                          type: boolean
                          description: Whether the prospect holds a housing voucher
                          example: false
                        normalized_phone_number_generated:
                          type: string
                          description: Normalized phone number if normalizable. Else null.
                          example: '+15551234567'
                        license_number:
                          type: string
                          description: License number if applicable
                          example: 'null'
                        prospect_type:
                          type: string
                          description: Type of prospect
                          enum:
                            - Self
                            - Agent
                          example: Self
                        updated_at:
                          type: string
                          format: date-time
                          description: When the prospect was last updated
                          example: '2023-01-15T12:00:00Z'
                        assigned_to_user_ids:
                          type: array
                          items:
                            type: string
                            example: 123e4567-e89b-12d3-a456-426614174001
                            format: uuid
                          description: IDs of users assigned to this prospect
                          example:
                            - 123e4567-e89b-12d3-a456-426614174001
            example:
              type: UPDATE
              table: prospects
              record:
                id: 123e4567-e89b-12d3-a456-426614174000
                created_at: '2023-01-15T12:00:00Z'
                name: John Doe
                phone: '+15551234567'
                email: john.doe@example.com
                unit_of_interest: '123'
                status: Not Interested
                source: Zillow
                notes: Interested in 2BR units
                prescreened: true
                voucher_holder: false
                normalized_phone_number_generated: '+15551234567'
                license_number: ABC123
                prospect_type: Agent
                updated_at: '2023-01-16T14:30:00Z'
                assigned_to_user_ids:
                  - 123e4567-e89b-12d3-a456-426614174001
              old_record:
                id: 123e4567-e89b-12d3-a456-426614174000
                created_at: '2023-01-15T12:00:00Z'
                name: John Doe
                phone: '+15551234567'
                email: john.doe@example.com
                unit_of_interest: '123'
                status: Showing SCheduled
                source: RentEngine
                notes: Interested in 2BR units
                prescreened: false
                voucher_holder: false
                normalized_phone_number_generated: '+15551234567'
                license_number: 'null'
                updated_at: '2023-01-15T12:00:00Z'
                prospect_type: Self
                assigned_to_user_ids: []
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
  UnitsEvents:
    post:
      summary: Units
      operationId: receive-units-updates
      tags:
        - Units
      description: |
        Webhook for unit changes (creates, updates, deletes).
        Only the below fields are included in the record and old_record objects.
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/WebhookPayload'
                - type: object
                  properties:
                    record:
                      type: object
                      properties:
                        id:
                          type: integer
                          description: Unique identifier for the unit
                          example: 3318
                        property_type:
                          type: string
                          description: Type of property
                          example: TOWNHOUSE
                        highlighted_amenities:
                          type: array
                          items:
                            type: string
                            example: Pool
                          description: Highlighted amenities
                        bedrooms:
                          type: string
                          description: Number of bedrooms
                          example: '3'
                        bathrooms:
                          type: string
                          description: Number of bathrooms
                          example: '2'
                        sqft:
                          type: string
                          description: Square footage of the unit
                          example: '1378'
                        furnished:
                          type: boolean
                          description: Whether the unit is furnished
                          example: false
                        renovated:
                          type: string
                          description: Whether the unit has been renovated
                          example: 'No'
                        num_parking_spots:
                          type: string
                          description: Number of parking spots
                          example: '2'
                        laundry:
                          type: string
                          description: Laundry options
                          example: In Unit
                        target_rental_rate:
                          type: string
                          description: Target rental rate for the unit in dollars per month
                          example: '1925'
                        is_occupied:
                          type: boolean
                          description: Whether the unit is currently occupied
                          example: false
                        earliest_move_in_date:
                          type: string
                          format: date
                          description: Earliest date the unit is available for move-in
                          example: '2024-10-12'
                        allow_cooperating_brokers:
                          type:
                            - boolean
                            - 'null'
                          description: Whether cooperating brokers are allowed
                          example: true
                        desired_lease_duration_months:
                          type: array
                          items:
                            type: integer
                            example: 12
                          description: Desired lease duration in months
                          example:
                            - 12
                        pets_allowed:
                          type:
                            - string
                            - 'null'
                          description: Pet policy
                          example: Yes with pet fee
                        pet_restrictions:
                          type: string
                          description: >-
                            Restrictions on pets (breed/weight/size limits, not
                            fees)
                          example: >-
                            Max 2 pets. Dogs must be under 50 lbs. No aggressive
                            breeds.
                        pet_fees:
                          type:
                            - array
                            - 'null'
                          items:
                            type: object
                            properties:
                              fee_name:
                                type: string
                                description: Name of the pet fee
                                example: Pet Deposit
                              amount:
                                type: number
                                description: >-
                                  Fee amount (dollar value or percentage of
                                  rent)
                                example: 500
                              type:
                                enum:
                                  - dollar
                                  - percent
                                type: string
                                description: >-
                                  Whether amount is a flat dollar value or
                                  percentage of rent
                                example: dollar
                              per_pet:
                                type: boolean
                                description: Whether the fee is charged per pet
                                example: false
                              required:
                                type: boolean
                                description: Whether the fee is mandatory
                                example: true
                              applies_to_esas:
                                type: boolean
                                description: >-
                                  Whether this fee applies to emotional support
                                  animals
                                example: false
                              fee_timing:
                                enum:
                                  - move_in
                                  - monthly
                                  - move_out
                                  - annually
                                type: string
                                description: When the fee is charged
                                example: move_in
                              fee_refundable:
                                enum:
                                  - refundable
                                  - nonRefundable
                                  - partiallyRefundable
                                type: string
                                description: Refundability of the fee
                                example: refundable
                              depends_on_pet_screening_results:
                                type: boolean
                                description: >-
                                  Whether the fee amount may vary based on pet
                                  screening
                                example: false
                            required:
                              - fee_name
                              - amount
                              - type
                              - fee_timing
                              - fee_refundable
                          description: Structured pet fees for the unit
                        hoa_app_required:
                          type:
                            - boolean
                            - 'null'
                          description: Whether HOA application is required
                          example: true
                        hoa_app_fee:
                          type:
                            - number
                            - 'null'
                          description: HOA application fee in dollars
                          example: 100
                        hoa_application_url:
                          type:
                            - string
                            - 'null'
                          description: URL for HOA application
                          example: https://example.com/application
                        key_access:
                          type: string
                          description: Key access information
                          example: I will add this later
                        structured_access_instructions:
                          type: object
                          description: Structured access instructions
                        earliest_showing_date:
                          type: string
                          format: date
                          description: Earliest date the unit can be shown
                          example: '2024-10-12'
                        min_resident_qualifications:
                          type: string
                          description: Minimum qualifications for residents
                          example: ''
                        utilities_included:
                          type: array
                          items:
                            type: string
                            example: Lawn Care
                          description: Utilities included in rent
                          example:
                            - Lawn Care
                            - Trash
                        parking_type:
                          type: array
                          items:
                            type: string
                            example: Assigned Spots
                          description: Type of parking available
                          example:
                            - Assigned Spots
                        status:
                          type: string
                          description: Current status of the unit
                          example: Leased
                        extracted_from:
                          type: string
                          description: Source of the unit data
                          example: f123abc
                        marketing_description:
                          type: string
                          description: Marketing description of the unit
                          example: >-
                            **AVAILABLE NOW** 3 Bedroom 2 Bathroom Townhome For
                            Rent in Meadow Woods!
                        marketing_photos:
                          type: array
                          items:
                            type: object
                            properties:
                              path:
                                type: string
                                example: https://example.com/images/unit123.jpg
                              hidden:
                                type: boolean
                                example: false
                              original:
                                type:
                                  - string
                                  - 'null'
                                example: https://example.com/images/unit123.jpg
                          description: Photos of the unit
                        commission_amount:
                          type: string
                          description: Commission amount
                          example: '1'
                        commission_type:
                          type: string
                          description: Type of commission
                          example: none
                        imported_by:
                          type:
                            - string
                            - 'null'
                          description: Who/what imported the unit
                          example: Rentvine Sync
                        floor_number:
                          type: integer
                          description: Floor number of the unit
                          example: 1
                        has_elevator:
                          type:
                            - boolean
                            - 'null'
                          description: Whether the building has an elevator
                          example: false
                        hoa_details:
                          type: object
                          description: Details about the HOA
                        account_id:
                          type: string
                          description: ID of the account that owns the unit
                          example: 269bf205-d876-42f5-988d-6f40891df58a
                        owner_emails:
                          type: array
                          items:
                            type: string
                            example: rick@amgrents.com
                          description: >-
                            (DEPRECATED) - Use property_owner_id instead. Email
                            addresses of the owners.
                          example:
                            - rick@amgrents.com
                          deprecated: true
                        block_syndication_to_ils:
                          type: boolean
                          description: >-
                            Whether to block syndication of this unit to ILS
                            (Internet Listing Services)
                          example: false
                        accepts_vouchers:
                          type:
                            - boolean
                            - 'null'
                          description: Whether the unit accepts housing vouchers.
                          example: true
                        showing_method:
                          type:
                            - string
                            - 'null'
                          description: Method for showing the unit
                          example: Remote Guided
                        amenities:
                          type: array
                          items:
                            type: string
                            example: Dishwasher
                          description: All amenities of the unit
                          example:
                            - Dishwasher
                            - Stove
                            - Range Oven
                            - Refrigerator
                        internal_notes:
                          type:
                            - string
                            - 'null'
                          description: Internal notes about the unit.
                          example: Garage work scheduled for Monday.
                        move_in_fees:
                          type:
                            - array
                            - 'null'
                          items:
                            type: object
                          description: Fees required at move-in
                        monthly_fees:
                          type:
                            - array
                            - 'null'
                          items:
                            type: object
                          description: Monthly recurring fees
                        multifamily_property_id:
                          type:
                            - string
                            - 'null'
                          description: ID of the multifamily property
                          example: 421e4567-e89b-12d3-a456-426614174000
                        floorplans_id:
                          type:
                            - string
                            - 'null'
                          description: ID of the floorplan
                          example: 451e4567-e89b-12d3-a456-426614174000
                        video_url:
                          type:
                            - string
                            - 'null'
                          description: URL of video tour
                          example: https://www.youtube.com/watch?v=1234567890
                        subteam_id:
                          type:
                            - string
                            - 'null'
                          description: ID of the subteam managing the unit
                          example: 123e4567-e89b-12d3-a456-426614174000
                        prescreen_template_id:
                          type:
                            - string
                            - 'null'
                          description: ID of the prescreening template to use for this unit
                          example: 123e4567-e89b-12d3-a456-426614174000
                        enable_send_report:
                          type: boolean
                          description: Whether to enable sending reports
                          example: true
                        security_deposit_amount:
                          type:
                            - number
                            - 'null'
                          description: Amount of security deposit in dollars
                          example: 1000.21
                        require_last_month_rent:
                          type:
                            - boolean
                            - 'null'
                          description: Whether last month's rent is required upfront
                          example: true
                        requires_voucher:
                          type:
                            - boolean
                            - 'null'
                          description: Whether a voucher is required
                          example: false
                        custom_application_url:
                          type: string
                          description: URL for custom application
                          example: >-
                            https://app.findigs.com/apply/unitid=70f51c4c-d708-402e-9a5f-bb6fd60b6cf2
                        include_feedback_leasing_report:
                          type: boolean
                          description: Whether to include feedback in leasing reports
                          example: true
                        year_built:
                          type:
                            - number
                            - 'null'
                          description: Year the property was built
                          example: 2020
                        application_fee:
                          type:
                            - number
                            - 'null'
                          description: Application fee amount in dollars
                          example: 50
                        created_at:
                          type: string
                          format: date-time
                          description: Timestamp when the unit was created
                          example: '2024-10-05T18:53:03.406168Z'
                        updated_at:
                          type: string
                          format: date-time
                          description: Timestamp when the unit was last updated
                          example: '2024-10-05T18:53:03.406168Z'
                    old_record:
                      type: object
                      properties:
                        id:
                          type: integer
                          description: Unique identifier for the unit
                          example: 3318
                        property_type:
                          type: string
                          description: Type of property
                          example: TOWNHOUSE
                        highlighted_amenities:
                          type: array
                          items:
                            type: string
                            example: Pool
                          description: Highlighted amenities
                        bedrooms:
                          type: string
                          description: Number of bedrooms
                          example: '3'
                        bathrooms:
                          type: string
                          description: Number of bathrooms
                          example: '2'
                        sqft:
                          type: string
                          description: Square footage of the unit
                          example: '1378'
                        furnished:
                          type: boolean
                          description: Whether the unit is furnished
                          example: false
                        renovated:
                          type: string
                          description: Whether the unit has been renovated
                          example: 'No'
                        num_parking_spots:
                          type: string
                          description: Number of parking spots
                          example: '2'
                        laundry:
                          type: string
                          description: Laundry options
                          example: In Unit
                        target_rental_rate:
                          type: string
                          description: Target rental rate for the unit in dollars per month
                          example: '1925'
                        is_occupied:
                          type: boolean
                          description: Whether the unit is currently occupied
                          example: false
                        earliest_move_in_date:
                          type: string
                          format: date
                          description: Earliest date the unit is available for move-in
                          example: '2024-10-12'
                        allow_cooperating_brokers:
                          type:
                            - boolean
                            - 'null'
                          description: Whether cooperating brokers are allowed
                          example: true
                        desired_lease_duration_months:
                          type: array
                          items:
                            type: integer
                            example: 12
                          description: Desired lease duration in months
                          example:
                            - 12
                        pets_allowed:
                          type:
                            - string
                            - 'null'
                          description: Pet policy
                          example: Yes with pet fee
                        pet_restrictions:
                          type: string
                          description: >-
                            Restrictions on pets (breed/weight/size limits, not
                            fees)
                          example: >-
                            Max 2 pets. Dogs must be under 50 lbs. No aggressive
                            breeds.
                        pet_fees:
                          type:
                            - array
                            - 'null'
                          items:
                            type: object
                            properties:
                              fee_name:
                                type: string
                                description: Name of the pet fee
                                example: Pet Deposit
                              amount:
                                type: number
                                description: >-
                                  Fee amount (dollar value or percentage of
                                  rent)
                                example: 500
                              type:
                                enum:
                                  - dollar
                                  - percent
                                type: string
                                description: >-
                                  Whether amount is a flat dollar value or
                                  percentage of rent
                                example: dollar
                              per_pet:
                                type: boolean
                                description: Whether the fee is charged per pet
                                example: false
                              required:
                                type: boolean
                                description: Whether the fee is mandatory
                                example: true
                              applies_to_esas:
                                type: boolean
                                description: >-
                                  Whether this fee applies to emotional support
                                  animals
                                example: false
                              fee_timing:
                                enum:
                                  - move_in
                                  - monthly
                                  - move_out
                                  - annually
                                type: string
                                description: When the fee is charged
                                example: move_in
                              fee_refundable:
                                enum:
                                  - refundable
                                  - nonRefundable
                                  - partiallyRefundable
                                type: string
                                description: Refundability of the fee
                                example: refundable
                              depends_on_pet_screening_results:
                                type: boolean
                                description: >-
                                  Whether the fee amount may vary based on pet
                                  screening
                                example: false
                            required:
                              - fee_name
                              - amount
                              - type
                              - fee_timing
                              - fee_refundable
                          description: Structured pet fees for the unit
                        hoa_app_required:
                          type:
                            - boolean
                            - 'null'
                          description: Whether HOA application is required
                          example: true
                        hoa_app_fee:
                          type:
                            - number
                            - 'null'
                          description: HOA application fee in dollars
                          example: 100
                        hoa_application_url:
                          type:
                            - string
                            - 'null'
                          description: URL for HOA application
                          example: https://example.com/application
                        key_access:
                          type: string
                          description: Key access information
                          example: I will add this later
                        structured_access_instructions:
                          type: object
                          description: Structured access instructions
                        earliest_showing_date:
                          type: string
                          format: date
                          description: Earliest date the unit can be shown
                          example: '2024-10-12'
                        min_resident_qualifications:
                          type: string
                          description: Minimum qualifications for residents
                          example: ''
                        utilities_included:
                          type: array
                          items:
                            type: string
                            example: Lawn Care
                          description: Utilities included in rent
                          example:
                            - Lawn Care
                            - Trash
                        parking_type:
                          type: array
                          items:
                            type: string
                            example: Assigned Spots
                          description: Type of parking available
                          example:
                            - Assigned Spots
                        status:
                          type: string
                          description: Current status of the unit
                          example: Leased
                        extracted_from:
                          type: string
                          description: Source of the unit data
                          example: f123abc
                        marketing_description:
                          type: string
                          description: Marketing description of the unit
                          example: >-
                            **AVAILABLE NOW** 3 Bedroom 2 Bathroom Townhome For
                            Rent in Meadow Woods!
                        marketing_photos:
                          type: array
                          items:
                            type: object
                            properties:
                              path:
                                type: string
                                example: https://example.com/images/unit123.jpg
                              hidden:
                                type: boolean
                                example: false
                              original:
                                type:
                                  - string
                                  - 'null'
                                example: https://example.com/images/unit123.jpg
                          description: Photos of the unit
                        commission_amount:
                          type: string
                          description: Commission amount
                          example: '1'
                        commission_type:
                          type: string
                          description: Type of commission
                          example: none
                        imported_by:
                          type:
                            - string
                            - 'null'
                          description: Who/what imported the unit
                          example: Rentvine Sync
                        floor_number:
                          type: integer
                          description: Floor number of the unit
                          example: 1
                        has_elevator:
                          type:
                            - boolean
                            - 'null'
                          description: Whether the building has an elevator
                          example: false
                        hoa_details:
                          type: object
                          description: Details about the HOA
                        account_id:
                          type: string
                          description: ID of the account that owns the unit
                          example: 269bf205-d876-42f5-988d-6f40891df58a
                        owner_emails:
                          type: array
                          items:
                            type: string
                            example: rick@amgrents.com
                          description: >-
                            (DEPRECATED) - Use property_owner_id instead. Email
                            addresses of the owners.
                          example:
                            - rick@amgrents.com
                          deprecated: true
                        block_syndication_to_ils:
                          type: boolean
                          description: >-
                            Whether to block syndication of this unit to ILS
                            (Internet Listing Services)
                          example: false
                        accepts_vouchers:
                          type:
                            - boolean
                            - 'null'
                          description: Whether the unit accepts housing vouchers.
                          example: true
                        showing_method:
                          type:
                            - string
                            - 'null'
                          description: Method for showing the unit
                          example: Remote Guided
                        amenities:
                          type: array
                          items:
                            type: string
                            example: Dishwasher
                          description: All amenities of the unit
                          example:
                            - Dishwasher
                            - Stove
                            - Range Oven
                            - Refrigerator
                        internal_notes:
                          type:
                            - string
                            - 'null'
                          description: Internal notes about the unit.
                          example: Garage work scheduled for Monday.
                        move_in_fees:
                          type:
                            - array
                            - 'null'
                          items:
                            type: object
                          description: Fees required at move-in
                        monthly_fees:
                          type:
                            - array
                            - 'null'
                          items:
                            type: object
                          description: Monthly recurring fees
                        multifamily_property_id:
                          type:
                            - string
                            - 'null'
                          description: ID of the multifamily property
                          example: 421e4567-e89b-12d3-a456-426614174000
                        floorplans_id:
                          type:
                            - string
                            - 'null'
                          description: ID of the floorplan
                          example: 451e4567-e89b-12d3-a456-426614174000
                        video_url:
                          type:
                            - string
                            - 'null'
                          description: URL of video tour
                          example: https://www.youtube.com/watch?v=1234567890
                        subteam_id:
                          type:
                            - string
                            - 'null'
                          description: ID of the subteam managing the unit
                          example: 123e4567-e89b-12d3-a456-426614174000
                        prescreen_template_id:
                          type:
                            - string
                            - 'null'
                          description: ID of the prescreening template to use for this unit
                          example: 123e4567-e89b-12d3-a456-426614174000
                        enable_send_report:
                          type: boolean
                          description: Whether to enable sending reports
                          example: true
                        security_deposit_amount:
                          type:
                            - number
                            - 'null'
                          description: Amount of security deposit in dollars
                          example: 1000.21
                        require_last_month_rent:
                          type:
                            - boolean
                            - 'null'
                          description: Whether last month's rent is required upfront
                          example: true
                        requires_voucher:
                          type:
                            - boolean
                            - 'null'
                          description: Whether a voucher is required
                          example: false
                        custom_application_url:
                          type: string
                          description: URL for custom application
                          example: >-
                            https://app.findigs.com/apply/unitid=70f51c4c-d708-402e-9a5f-bb6fd60b6cf2
                        include_feedback_leasing_report:
                          type: boolean
                          description: Whether to include feedback in leasing reports
                          example: true
                        year_built:
                          type:
                            - number
                            - 'null'
                          description: Year the property was built
                          example: 2020
                        application_fee:
                          type:
                            - number
                            - 'null'
                          description: Application fee amount in dollars
                          example: 50
                        created_at:
                          type: string
                          format: date-time
                          description: Timestamp when the unit was created
                          example: '2024-10-05T18:53:03.406168Z'
                        updated_at:
                          type: string
                          format: date-time
                          description: Timestamp when the unit was last updated
                          example: '2024-10-05T18:53:03.406168Z'
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
  RentalApplicationGroups:
    post:
      summary: Rental application groups
      operationId: receive-rental-application-group-updates
      tags:
        - Rental Applications
      description: >
        Webhook for rental application group changes. Emits the following
        semantic events:

        - `group.created` when a new application group is created (INSERT).

        - `group.state_changed` when the group's `status` transitions (for
        example, `Submitted` → `Approved`). The `changes.status` object
        describes the transition.

        - `group.unit_changed` when the group's `unit_id` changes without a
        status change. The `changes.unit_id` object describes the transition.

        - `group.updated` fallback for other meaningful UPDATE events.


        When a single UPDATE contains multiple changes (for example, a status
        change and a unit change at the same time), the most specific event is
        emitted — `group.state_changed` wins over `group.unit_changed`, which
        wins over `group.updated`. All detected transitions are always included
        in the `changes` object, so subscribers that want granular detection can
        inspect `changes` regardless of the top-level `event`.


        The `record` and `old_record` objects are whitelisted and do not include
        applicant PII. Fetch the group detail endpoint (`GET
        /rental_application_groups/{id}`) to retrieve non-PII group state and
        the applicant list, or `GET /rental_applications/{id}` for the full
        applicant record including PII.
      security:
        - ApiKeyAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RentalApplicationGroupWebhookPayload'
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
  RentalApplications:
    post:
      summary: Rental applications
      operationId: receive-rental-application-updates
      tags:
        - Rental Applications
      description: >
        Webhook for individual rental application changes. Emits the following
        semantic events:

        - `application.created` when a new applicant record is created (INSERT).

        - `application.state_changed` when the applicant's `status` transitions
        (for example, `Incomplete` → `Submitted`). The `changes.status` object
        describes the transition.

        - `application.updated` fallback for other meaningful UPDATE events (for
        example, `progress` changes, `move_in_date` changes).


        The `record` and `old_record` objects are whitelisted and do not include
        PII — fields such as `personal_details`, `income_details`,
        `application_documents`, `address_history`, and `co_applicants` are
        intentionally omitted. Fetch the rental application endpoint (`GET
        /rental_applications/{id}`) with a Bearer token to retrieve full PII
        after receiving a webhook.
      security:
        - ApiKeyAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RentalApplicationWebhookPayload'
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
  MarketToolLeads:
    post:
      summary: Market tool leads
      operationId: receive-market-tool-lead-events
      tags:
        - Market Tool
      description: |
        Webhook for new business-development leads captured by the Market Tool
        Widget. Fires once per new lead (INSERT only) — no update or delete
        events. The `record` contains a fixed set of listing and lead-contact
        fields.
      security:
        - ApiKeyAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MarketToolLeadWebhookPayload'
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
security:
  - ApiKeyAuth: []
