CleanRoll API

The CleanRoll API allows you to programmatically parse rent roll files and extract standardized data.

Beta Notice
The API is currently in beta. Endpoints and response formats may change. We'll notify you of any breaking changes.

Features

  • Parse Excel (.xlsx, .xls), CSV, and PDF rent rolls
  • Automatic PM system format detection (Yardi, AppFolio, RealPage, etc.)
  • AI-powered column mapping suggestions
  • Batch processing for multiple files

Authentication

All API requests require authentication via an API key. Include your API key in the Authorization header:

Authorization: Bearer cr_live_your_api_key

API keys can be created and managed from the Developer Dashboard.

Scopes

API keys can optionally be restricted to specific scopes:

  
  
  
  

Keys without scopes have full access. Keys with scopes are limited to those specific operations.

Parse File

Upload and parse a single rent roll file.

POST/api/v1/parse

Request

Content-Type: multipart/form-data

    
    

Example Request

curl -X POST https://cleanroll.ai/api/v1/parse \
  -H "Authorization: Bearer cr_live_your_api_key" \
  -F "[email protected]"

Response

{
  "success": true,
  "data": {
    "headers": ["Unit", "Tenant", "SF", "Monthly Rent", "Lease End"],
    "rows": [
      {"Unit": "101", "Tenant": "Acme Corp", "SF": "2500", "Monthly Rent": "$5,000", "Lease End": "12/31/2025"},
      ...
    ],
    "sampleRows": [...],
    "totalRows": 24,
    "filename": "rent-roll.xlsx",
    "formatDetection": {
      "detectedSystem": "yardi",
      "confidence": 0.85,
      "displayName": "Yardi",
      "suggestedMappings": [
        {"source": "Unit", "target": "unit_id", "confidence": 0.95},
        {"source": "Tenant", "target": "tenant_name", "confidence": 0.98},
        ...
      ],
      "notes": "Detected Yardi format based on column headers"
    }
  },
  "usage": {
    "documentsUsed": 15,
    "documentsLimit": null,
    "documentsRemaining": null,
    "isUnlimited": true,
    "tier": "pro"
  }
}

Batch Parse

Upload and parse multiple rent roll files in a single request.

POST/api/v1/parse-batch

Request

Content-Type: multipart/form-data

    

Batch Limits by Plan

  
  
  

Example Request

curl -X POST https://cleanroll.ai/api/v1/parse-batch \
  -H "Authorization: Bearer cr_live_your_api_key" \
  -F "[email protected]" \
  -F "[email protected]" \
  -F "[email protected]"

Response

{
  "success": true,
  "batchId": "550e8400-e29b-41d4-a716-446655440000",
  "files": [
    {
      "filename": "property1.xlsx",
      "headers": [...],
      "rows": [...],
      "sampleRows": [...],
      "totalRows": 24,
      "formatDetection": {...}
    },
    {
      "filename": "property2.xlsx",
      "headers": [...],
      "rows": [...],
      "sampleRows": [...],
      "totalRows": 18,
      "formatDetection": {...}
    },
    {
      "filename": "property3.csv",
      "error": "Could not identify tabular data"
    }
  ],
  "totalFiles": 3,
  "successfulFiles": 2,
  "failedFiles": 1,
  "usage": {...}
}

Templates

List and use your saved column mapping templates via the API.

List Templates

GET/api/v1/templates
curl https://cleanroll.ai/api/v1/templates \
  -H "Authorization: Bearer cr_live_your_api_key"

Response

{
  "success": true,
  "templates": [
    {
      "id": "tmpl_abc123",
      "name": "Yardi Format",
      "description": "Standard Yardi export mapping",
      "mappings": [
        { "sourceColumn": "Unit", "targetField": "unit_id" },
        { "sourceColumn": "Tenant Name", "targetField": "tenant_name" },
        { "sourceColumn": "RSF", "targetField": "sqft" }
      ],
      "createdAt": "2025-01-15T10:30:00.000Z"
    }
  ]
}

Use Template with Parse

Pass a templateId when parsing to apply saved mappings:

curl -X POST https://cleanroll.ai/api/v1/parse \
  -H "Authorization: Bearer cr_live_your_api_key" \
  -F "[email protected]" \
  -F "templateId=tmpl_abc123"

Usage

Get your current API usage and subscription details.

GET/api/v1/usage

Example Request

curl https://cleanroll.ai/api/v1/usage \
  -H "Authorization: Bearer cr_live_your_api_key"

Response

{
  "success": true,
  "usage": {
    "documentsUsed": 45,
    "documentsLimit": null,
    "documentsRemaining": null,
    "periodStart": "2025-01-01T00:00:00.000Z",
    "periodEnd": "2025-01-31T23:59:59.999Z",
    "tier": "pro",
    "isUnlimited": true,
    "canUpload": true
  },
  "limits": {
    "batchUploadLimit": 10,
    "canSaveTemplates": true,
    "canBatchUpload": true
  },
  "plan": {
    "name": "Pro",
    "tier": "pro"
  }
}

Errors

The API uses standard HTTP status codes to indicate success or failure.

   
   
   
   
   

Error Response Format

{
  "statusCode": 401,
  "message": "Invalid or missing API key. Provide a valid key via Authorization header."
}

Rate Limits

API usage is limited by your subscription plan's monthly document quota, not by request rate.

   
   
   

Usage is counted per successfully parsed document. Failed parses are not counted against your quota.

SDKs & Libraries

Official and community SDKs make it easy to integrate CleanRoll into your applications.

Python SDK

Official Python client for the CleanRoll API

pip install cleanroll

JavaScript/Node.js

Official npm package for Node.js and browsers

npm install @cleanroll/sdk

Python Quick Start

from cleanroll import CleanRoll

client = CleanRoll(api_key="cr_live_your_api_key")

# Parse a rent roll
result = client.parse("rent-roll.xlsx")
print(f"Parsed {result.total_rows} rows")
print(f"Detected format: {result.format_detection.system}")

# List your templates
templates = client.templates.list()
for t in templates:
    print(f"Template: {t.name}")

# Parse with a template
result = client.parse("rent-roll.xlsx", template_id="tmpl_abc123")

JavaScript Quick Start

import { CleanRoll } from '@cleanroll/sdk';

const client = new CleanRoll({ apiKey: 'cr_live_your_api_key' });

// Parse a rent roll
const result = await client.parse('./rent-roll.xlsx');
console.log(`Parsed ${result.totalRows} rows`);
console.log(`Detected format: ${result.formatDetection.system}`);

// List your templates
const templates = await client.templates.list();
templates.forEach(t => console.log(`Template: ${t.name}`));

// Parse with a template
const result2 = await client.parse('./rent-roll.xlsx', {
  templateId: 'tmpl_abc123'
});
Coming Soon
Official SDKs are currently in development. In the meantime, use the REST API directly with any HTTP client.