# Property Management KPI & Alerts Connector (`constructive_junk/property-management-connector`) Actor

Sync Buildium, AppFolio, QuickBooks or CSV to auto-calculate cap rate, DSCR, occupancy & delinquency KPIs vs configurable benchmarks (any US state or Puerto Rico). Get instant alerts for late rent, vacancies & maintenance SLAs.

- **URL**: https://apify.com/constructive\_junk/property-management-connector.md
- **Developed by:** [Maria Correa-Resto](https://apify.com/constructive_junk) (community)
- **Categories:** Real estate, Automation, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $150.00 / 1,000 kpi report generateds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Property Management KPI & Alerts Connector

Turn Buildium, AppFolio, QuickBooks Online (or a plain CSV export) into a live, benchmark-driven command center for your rental portfolio — in Puerto Rico or any U.S. state.

### Who this is for

- Independent landlords and small multi-property owners who want investor-grade KPIs without hiring an analyst.
- Property management companies serving multiple clients who need one consistent KPI standard across every portfolio.
- Accountants, asset managers, and consultants who report on real estate performance for clients in the U.S. and Puerto Rico.

### What it does

1. **Connects** to your property management platform (Buildium, AppFolio, QuickBooks Online) using your own API credentials, or accepts a manual CSV for a zero-integration start.
2. **Normalizes** rent roll, occupancy, and maintenance data into one common schema, regardless of source platform.
3. **Calculates KPIs** — occupancy %, vacancy %, delinquency %, and portfolio health — and compares them against configurable benchmarks (Cap Rate, Cash-on-Cash, DSCR, GRM, vacancy budget, maintenance/CapEx reserves, management fee range).
4. **Selects your market**: choose Puerto Rico or any of the 50 U.S. states + D.C. Puerto Rico runs add jurisdiction-specific context (CRIM, OGPe, sucesiones, seller financing, Ley 47-2021, hurricane/flood insurance exposure); U.S. state runs add general landlord-tenant, security-deposit, and Fair Housing considerations.
5. **Sends alerts** the moment a tenant is late on rent, a unit sits vacant too long, or a maintenance SLA is at risk — via webhook, Slack, email, or WhatsApp.
6. **Outputs clean JSON** ready for dashboards, spreadsheets, or MCP-compatible AI assistants.

### Fully configurable benchmarks

Every threshold ships with sensible defaults but can be overridden per run — no hardcoded assumptions:

| Metric | Default |
|---|---|
| Cap Rate | ≥ 12% |
| Cash-on-Cash | ≥ 12% |
| DSCR | ≥ 1.25 |
| GRM | < 10 |
| Vacancy budget | 8–10% |
| Maintenance reserve | 5% of effective income |
| CapEx reserve | 5% of effective income |
| Management fee | 8–10% |

### Privacy by design

- **Bring your own credentials.** Your Buildium/AppFolio/QuickBooks keys stay in your input only — never shared with the developer.
- **PII controls.** Choose `minimal`, `maskSensitive`, or `full` handling; tenant names can be stripped automatically from the output.
- **Multi-tenant safe.** Each run is isolated by `clientId`, so agencies managing several clients keep every portfolio separate.

### Getting started

1. Pick your `platform` (start with `manualCsv` if you don't have API access yet).
2. Select your `market` (Puerto Rico or a U.S. state) to load the right benchmarks and legal context.
3. Adjust `thresholds` and `alertRules` if your investment criteria differ from the defaults.
4. Add a `webhookUrl` or `slackWebhookUrl` to receive real-time alerts.
5. Run the Actor on a schedule (e.g. daily at 6am) to keep your KPIs and alerts always current.

### Why teams choose this Actor

Most property-management software gives you raw data. This Actor gives you a decision: which units need attention today, and whether your portfolio still clears the investment bar you set for it.

# Actor input Schema

## `clientId` (type: `string`):

Identificador unico de tu cliente final. Sirve para separar datos si ofreces este actor como servicio a varias empresas o dueños de propiedades.
## `platform` (type: `string`):

Plataforma de origen de los datos: CSV manual (para probar sin credenciales), Buildium, AppFolio o QuickBooks Online.
## `credentials` (type: `object`):

Token del cliente final, nunca del desarrollador del actor. Se guarda cifrado por Apify. Dejar vacio si platform=manualCsv.
## `csvData` (type: `string`):

Pega aqui un CSV con columnas: propertyId,unitId,tenantName,rentAmount,rentStatus,daysLate,vacancyDays
## `propertiesToSync` (type: `array`):

Lista de IDs de propiedad. Vacio = sincronizar todo el portafolio disponible.
## `syncFrequencyCron` (type: `string`):

Expresion cron que define cada cuanto se debe correr la sincronizacion (usando Apify Schedules).
## `market` (type: `string`):

Activa el bloque de contexto legal/estructural correspondiente (ver src/marketContext.js). PR trae CRIM, OGPe, sucesiones, Ley 47-2021 y huracanes. Los estados de EE.UU. traen un bloque generico con recordatorio de verificar la ley local.
## `thresholds` (type: `object`):

Benchmarks usados para comparar el portafolio. Todos son editables, estos son solo valores por defecto sugeridos.
## `alertRules` (type: `object`):

Umbrales que determinan cuando se dispara una alerta: dias de mora, dias de vacancia, horas de SLA de mantenimiento.
## `alertChannels` (type: `object`):

Llena solo los canales que uses: webhookUrl, slackWebhookUrl, email, whatsappBusinessNumber.
## `piiHandling` (type: `string`):

Controla cuanta informacion personal del inquilino se incluye en la salida.

## Actor input object example

```json
{
  "platform": "manualCsv",
  "propertiesToSync": [],
  "syncFrequencyCron": "0 6 * * *",
  "market": "PR",
  "thresholds": {
    "capRateMinPct": 12,
    "cashOnCashMinPct": 12,
    "dscrMin": 1.25,
    "grmMax": 10,
    "vacancyBudgetMinPct": 8,
    "vacancyBudgetMaxPct": 10,
    "maintenanceReservePct": 5,
    "capexReservePct": 5,
    "managementFeeMinPct": 8,
    "managementFeeMaxPct": 10
  },
  "alertRules": {
    "rentOverdueDays": 5,
    "vacancyAlertDays": 30,
    "maintenanceSlaHours": 48
  },
  "alertChannels": {},
  "piiHandling": "minimal"
}
````

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("constructive_junk/property-management-connector").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("constructive_junk/property-management-connector").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call constructive_junk/property-management-connector --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=constructive_junk/property-management-connector",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Property Management KPI & Alerts Connector",
        "description": "Sync Buildium, AppFolio, QuickBooks or CSV to auto-calculate cap rate, DSCR, occupancy & delinquency KPIs vs configurable benchmarks (any US state or Puerto Rico). Get instant alerts for late rent, vacancies & maintenance SLAs.",
        "version": "0.0",
        "x-build-id": "ufAwwdxyj0A6aWtAN"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/constructive_junk~property-management-connector/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-constructive_junk-property-management-connector",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/constructive_junk~property-management-connector/runs": {
            "post": {
                "operationId": "runs-sync-constructive_junk-property-management-connector",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/constructive_junk~property-management-connector/run-sync": {
            "post": {
                "operationId": "run-sync-constructive_junk-property-management-connector",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "platform",
                    "market"
                ],
                "properties": {
                    "clientId": {
                        "title": "Client ID",
                        "type": "string",
                        "description": "Identificador unico de tu cliente final. Sirve para separar datos si ofreces este actor como servicio a varias empresas o dueños de propiedades."
                    },
                    "platform": {
                        "title": "Plataforma de origen",
                        "enum": [
                            "manualCsv",
                            "buildium",
                            "appfolio",
                            "quickbooks"
                        ],
                        "type": "string",
                        "description": "Plataforma de origen de los datos: CSV manual (para probar sin credenciales), Buildium, AppFolio o QuickBooks Online.",
                        "default": "manualCsv"
                    },
                    "credentials": {
                        "title": "Credenciales (API Key / Token OAuth del CLIENTE)",
                        "type": "object",
                        "description": "Token del cliente final, nunca del desarrollador del actor. Se guarda cifrado por Apify. Dejar vacio si platform=manualCsv."
                    },
                    "csvData": {
                        "title": "Datos CSV (si platform=manualCsv)",
                        "type": "string",
                        "description": "Pega aqui un CSV con columnas: propertyId,unitId,tenantName,rentAmount,rentStatus,daysLate,vacancyDays"
                    },
                    "propertiesToSync": {
                        "title": "Propiedades a sincronizar",
                        "type": "array",
                        "description": "Lista de IDs de propiedad. Vacio = sincronizar todo el portafolio disponible.",
                        "default": []
                    },
                    "syncFrequencyCron": {
                        "title": "Frecuencia de sincronizacion (cron)",
                        "type": "string",
                        "description": "Expresion cron que define cada cuanto se debe correr la sincronizacion (usando Apify Schedules).",
                        "default": "0 6 * * *"
                    },
                    "market": {
                        "title": "Mercado / jurisdiccion",
                        "enum": [
                            "PR",
                            "AL",
                            "AK",
                            "AZ",
                            "AR",
                            "CA",
                            "CO",
                            "CT",
                            "DE",
                            "FL",
                            "GA",
                            "HI",
                            "ID",
                            "IL",
                            "IN",
                            "IA",
                            "KS",
                            "KY",
                            "LA",
                            "ME",
                            "MD",
                            "MA",
                            "MI",
                            "MN",
                            "MS",
                            "MO",
                            "MT",
                            "NE",
                            "NV",
                            "NH",
                            "NJ",
                            "NM",
                            "NY",
                            "NC",
                            "ND",
                            "OH",
                            "OK",
                            "OR",
                            "PA",
                            "RI",
                            "SC",
                            "SD",
                            "TN",
                            "TX",
                            "UT",
                            "VT",
                            "VA",
                            "WA",
                            "WV",
                            "WI",
                            "WY",
                            "DC"
                        ],
                        "type": "string",
                        "description": "Activa el bloque de contexto legal/estructural correspondiente (ver src/marketContext.js). PR trae CRIM, OGPe, sucesiones, Ley 47-2021 y huracanes. Los estados de EE.UU. traen un bloque generico con recordatorio de verificar la ley local.",
                        "default": "PR"
                    },
                    "thresholds": {
                        "title": "Umbrales de analisis (editables)",
                        "type": "object",
                        "description": "Benchmarks usados para comparar el portafolio. Todos son editables, estos son solo valores por defecto sugeridos.",
                        "default": {
                            "capRateMinPct": 12,
                            "cashOnCashMinPct": 12,
                            "dscrMin": 1.25,
                            "grmMax": 10,
                            "vacancyBudgetMinPct": 8,
                            "vacancyBudgetMaxPct": 10,
                            "maintenanceReservePct": 5,
                            "capexReservePct": 5,
                            "managementFeeMinPct": 8,
                            "managementFeeMaxPct": 10
                        }
                    },
                    "alertRules": {
                        "title": "Reglas de alerta",
                        "type": "object",
                        "description": "Umbrales que determinan cuando se dispara una alerta: dias de mora, dias de vacancia, horas de SLA de mantenimiento.",
                        "default": {
                            "rentOverdueDays": 5,
                            "vacancyAlertDays": 30,
                            "maintenanceSlaHours": 48
                        }
                    },
                    "alertChannels": {
                        "title": "Canales de notificacion",
                        "type": "object",
                        "description": "Llena solo los canales que uses: webhookUrl, slackWebhookUrl, email, whatsappBusinessNumber.",
                        "default": {}
                    },
                    "piiHandling": {
                        "title": "Manejo de datos sensibles de inquilinos",
                        "enum": [
                            "minimal",
                            "full",
                            "maskSensitive"
                        ],
                        "type": "string",
                        "description": "Controla cuanta informacion personal del inquilino se incluye en la salida.",
                        "default": "minimal"
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
