Rent Roll API

API de extracción de rent roll con verificación integrada

Documentación

Un solo endpoint hace todo el trabajo: sube un rent roll, obtén datos estructurados con un informe de verificación determinista. Sin trabajos asíncronos, sin sondeos: una única llamada HTTP.

Especificación legible por máquina: OpenAPI 3.0 (openapi.json) — impórtala en Postman, Insomnia o tu herramienta de generación de código.

Autenticación

Pasa tu clave de API en el encabezado X-Api-Key (o como token bearer). Obtén una clave en la página de precios; adminístrala en tu cuenta.

X-Api-Key: rr_live_your_key_here
# or
Authorization: Bearer rr_live_your_key_here

¿Sin clave? La aplicación web permite 3 extracciones gratuitas por día y por IP para evaluación.

POST/v1/extract

Extrae datos estructurados de un documento. Envía multipart/form-data con un campo file.

Entradas admitidas

  • PDF — digital o escaneado (OCR manejado automáticamente), hasta 25 MB
  • Excel — .xlsx, .xlsm
  • CSV, HTML

Parámetros de consulta

ParámetroValoresPredeterminadoDescripción
formatjson · csv · xlsxjsonFormato de respuesta. csv / xlsx devuelven un archivo descargable.

Ejemplo

curl -X POST "https://rentrollapi.com/v1/extract?format=json" \
  -H "X-Api-Key: rr_live_your_key_here" \
  -F "file=@rent-roll.pdf"

SDK .NET

Cliente oficial en NuGet: RentRollAPI.Client (netstandard2.0 / net8.0).

dotnet add package RentRollAPI.Client
using RentRollApi.Client;

using var client = new RentRollClient("rr_live_your_key_here");
var result = await client.ExtractAsync("rent-roll.pdf");

Console.WriteLine($"{result.Units.Count} units, confidence {result.Verification.DocumentConfidence:P0}");
foreach (var check in result.Verification.Checks)
    Console.WriteLine($"[{check.Result}] {check.Name}: {check.Detail}");

// Or get Excel / CSV directly:
byte[] xlsx = await client.ExtractToXlsxAsync(stream, "rent-roll.pdf");

Respuesta (JSON)

Cada campo lleva un valor, estado (Extracted / Missing / Flagged) y confianza. El bloque de verificación se calcula de forma determinista: los totales se vuelven a sumar y se concilian contra lo que declara el documento, para que sepas cuándo confiar en la salida.

{
  "propertyName": { "value": "Maplewood Commerce Center", "status": "Extracted", "confidence": 0.9 },
  "asOfDate":     { "value": "2026-06-30", "status": "Extracted", "confidence": 0.9 },
  "units": [
    {
      "unitNumber":  { "value": "101", "status": "Extracted", "confidence": 0.9 },
      "tenantName":  { "value": "Cedar Point Dental", "status": "Extracted", "confidence": 0.9 },
      "squareFeet":  { "value": 1850, "status": "Extracted", "confidence": 0.9 },
      "monthlyRent": { "value": 4625.0, "status": "Extracted", "confidence": 0.9 },
      "leaseStart":  { "status": "Missing" },
      "leaseEnd":    { "value": "2028-03-31", "status": "Extracted", "confidence": 0.9 },
      "occupancy":   { "value": "Occupied", "status": "Extracted", "confidence": 0.9 }
    }
  ],
  "totals": { "unitCount": 8, "monthlyRent": 28155.0, "squareFeet": 13750 },
  "verification": {
    "documentConfidence": 0.9,
    "flaggedFieldCount": 0,
    "allChecksPassed": true,
    "checks": [
      { "name": "UnitCountReconciliation",       "result": "Pass", "detail": "Extracted 8 units; document states 8." },
      { "name": "TotalMonthlyRentReconciliation", "result": "Pass", "detail": "Computed 28,155.00 vs stated 28,155.00 (within tolerance)." },
      { "name": "TotalSquareFeetReconciliation",  "result": "Pass", "detail": "Computed 13,750.00 vs stated 13,750.00 (within tolerance)." },
      { "name": "DuplicateUnits",                 "result": "Pass", "detail": "No duplicate unit numbers." },
      { "name": "LeaseDateOrder",                 "result": "Pass", "detail": "All lease end dates follow start dates." },
      { "name": "NonNegativeRents",               "result": "Pass", "detail": "No negative rents." }
    ]
  }
}

Errores

EstadoSignificado
400Campo file faltante o vacío, archivo de más de 25 MB o format desconocido
401Clave de API inválida o revocada
422Documento no admitido o ilegible
429Cuota mensual superada y sin créditos prepagados restantes (o límite de demostración alcanzado)

Todos los errores devuelven {"error": "human-readable message"}.

POST/v1/extract/operating-statement

Extrae un T12 / estado de operación (informe de ingresos y gastos de los últimos doce meses) en partidas estructuradas. Mismas entradas, autenticación, medición y opciones de format que /v1/extract — una extracción cuenta como un documento contra tu cuota.

Ejemplo

curl -X POST "https://rentrollapi.com/v1/extract/operating-statement" \
  -H "X-Api-Key: rr_live_your_key_here" \
  -F "file=@t12.pdf"

Respuesta (JSON)

{
  "propertyName": { "value": "Maplewood Apartments", "status": "extracted", "confidence": 0.95 },
  "basis": { "value": "Accrual", "status": "extracted", "confidence": 0.9 },
  "months": ["2025-08", "2025-09", "...", "2026-07"],
  "lineItems": [
    {
      "label": { "value": "Gross Potential Rent", "status": "extracted", "confidence": 0.95 },
      "kind": "Income",
      "category": "GrossPotentialRent",
      "monthlyValues": [ { "value": 52000, "status": "extracted", "confidence": 0.9 }, "..." ],
      "total": { "value": 631200, "status": "extracted", "confidence": 0.95 }
    }
  ],
  "verification": {
    "documentConfidence": 0.9,
    "allChecksPassed": true,
    "checks": [
      { "name": "RowTotalReconciliation", "result": "pass", "detail": "All 15 row totals reconcile with their monthly values." },
      { "name": "NoiReconciliation", "result": "pass", "detail": "EGI − OpEx matches stated NOI (within tolerance)." }
    ]
  }
}

Comprobaciones deterministas: totales de fila vs valores mensuales, EGI = suma de ingresos, OpEx total = suma de gastos, NOI = EGI − OpEx, gastos no negativos y continuidad de meses consecutivos. El kind de la partida es Income, Expense, Subtotal o Other; category normaliza las etiquetas en ~23 categorías estándar (RealEstateTaxes, Insurance, Utilities, RepairsMaintenance, Payroll, ManagementFee,...). Las filas de contra-ingresos como vacancia y concesiones son de tipo Ingreso con valores negativos.

Servidor MCP (asistentes de IA)

RentRollAPI también es un servidor Model Context Protocol. Apunta cualquier cliente compatible con MCP (Claude, ChatGPT, Copilot, Cursor...) al endpoint HTTP transmisible y obtendrá herramientas de extract_rent_roll y extract_operating_statement:

{
  "mcpServers": {
    "rentrollapi": {
      "type": "http",
      "url": "https://rentrollapi.com/mcp",
      "headers": { "X-Api-Key": "rr_live_your_key_here" }
    }
  }
}

Omite el encabezado para usar la asignación gratuita de demostración de 3 documentos/día. La medición es idéntica a la API REST.

Endpoints de cuenta

Todos autenticados con el mismo encabezado X-Api-Key.

EndpointDescripción
GET /api/accountPlan, uso mensual, cuota restante, créditos prepagados
POST /api/account/rotateEmite una nueva clave, revoca inmediatamente la actual (los créditos se transfieren)
POST /api/portalDevuelve una URL del Customer Portal de Stripe — mejora, degrada, cancela, facturas
POST /api/credits/checkoutDevuelve una URL de Stripe Checkout para un recargo de 25 créditos aplicado a esta clave

Cuotas y facturación

  • Suscripciones (Starter 50/mes, Pro 300/mes): la cuota se restablece el día 1 (UTC). El exceso se descuenta de los créditos prepagados cuando los tengas.
  • Pago por uso: cada extracción consume un crédito prepagado.
  • Los créditos nunca caducan y sobreviven a la rotación de claves y a la cancelación de la suscripción.

Manejo de datos

Los documentos se procesan en memoria y nunca se almacenan después de que tu extracción se complete. Consulta la política de privacidad.