API Comparison: Two Paths for Document Processing
Home Insight AI provides two different API paths for document analysis, each designed for specific use cases. Understanding which one to use is critical for optimal performance and user experience.
Quick Decision Guide
┌─────────────────────────────────────────┐
│ Need to upload 1 document? │
│ Building a B2B API integration? │
│ Want manual control over processing? │
└─────────────────┬───────────────────────┘
↓ YES
Use /v1/analyses (Low-Level API)
┌─────────────────────────────────────────┐
│ Need to upload 5-50 documents? │
│ Building a portal/UI for end users? │
│ Want automatic smart categorization? │
└─────────────────┬───────────────────────┘
↓ YES
Use /v1/properties/{id}/upload (High-Level API)
Path 1: Analyses API (Low-Level / B2B)
Endpoint: POST /v1/analyses
Use Cases
- SDK/API Integrations: External developers embedding via API
- Single-file uploads: One document at a time
- Manual processing control: Trigger processing explicitly
- Custom workflows: Full control over each step
Characteristics
- ✅ Single file per request
- ✅ Synchronous or manual processing trigger
- ✅ Simple, straightforward workflow
- ✅ Direct control over analysis timing
- ❌ No automatic categorization
- ❌ Slower for bulk uploads (sequential)
- ❌ More API calls required
Summary Storage
Location: analyses.metadata.summary
{
"metadata": {
"summary": "This is a home inspection report for...",
"key_points": ["Finding 1", "Finding 2"],
"issues": [...],
"document_type": "inspection_report"
}
}
Example Workflow
# Step 1: Upload single document
curl -X POST https://api.homeinsightai.com/v1/analyses \
-H "Authorization: Bearer hi_live_YOUR_API_KEY" \
-F "file=@inspection.pdf" \
-F "property_address=123 Main St"
# Response
{
"analysis_id": "ana_abc123",
"page_count": 25,
"total_bytes": 2458923,
"message": "Successfully processed 25 pages"
}
# Step 2: Get results (summary in metadata)
curl https://api.homeinsightai.com/v1/analyses/ana_abc123 \
-H "Authorization: Bearer hi_live_YOUR_API_KEY"
# Response
{
"analysis_id": "ana_abc123",
"status": "completed",
"summary": "This is a home inspection...", # Also in metadata.summary
"total_issues": 12,
"severity": "critical"
}
# Step 3: Get structured issues
curl https://api.homeinsightai.com/v1/analyses/ana_abc123/issues \
-H "Authorization: Bearer hi_live_YOUR_API_KEY"
When to use:
- Building SDKs or API wrappers
- Single-document processing
- Need full control over timing
- Simple integrations
Path 2: Properties API (High-Level / Portal)
Endpoint: POST /v1/properties/{property_id}/upload
Use Cases
- Portal/UI Applications: End-user facing applications
- Bulk document uploads: 5-50 documents at once
- CRM integrations: Real estate platforms, MLS systems
- Automatic workflows: Let the system handle everything
Characteristics
- ✅ Multi-file batch upload (up to 50 PDFs)
- ✅ Automatic smart categorization (critical/important/optional/noise)
- ✅ Background parallel processing
- ✅ 6-9x faster than sequential uploads
- ✅ 74% fewer API calls
- ✅ Property-based organization
- ❌ More complex response structure
- ❌ Requires property creation first
Summary Storage
Location: analyses.summary (top-level column)
{
"id": "ana_abc123",
"summary": "This is a home inspection report for...", # Top-level column
"document_type": "inspection_report",
"metadata": {
"filename": "inspection.pdf",
"page_count": 25,
"key_points": ["Finding 1", "Finding 2"]
}
}
Example Workflow
# Step 1: Create property (one-time)
curl -X POST https://api.homeinsightai.com/v1/properties \
-H "Authorization: Bearer hi_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"external_id": "listing_12345",
"address": "123 Main St, San Francisco, CA 94102"
}'
# Response
{
"id": "prop_abc123",
"external_id": "listing_12345",
"address": "123 Main St",
"city": "San Francisco",
"state": "CA",
"zip_code": "94102",
"country": "US",
"document_count": 0,
"created_at": "2025-12-03T...",
"updated_at": "2025-12-03T..."
}
# Step 2: Upload all documents in one batch
curl -X POST "https://api.homeinsightai.com/v1/properties/prop_abc123/upload" \
-H "Authorization: Bearer hi_live_YOUR_API_KEY" \
-F "files=@Home_Inspection_Report.pdf" \
-F "files=@Loan_Estimate.pdf" \
-F "files=@Seller_Disclosure.pdf" \
-F "files=@Purchase_Agreement.pdf" \
-F "files=@Receipt_Earnest.pdf"
# Response (instant - processing happens in background)
{
"property_id": "prop_abc123",
"documents_uploaded": 5,
"documents_categorized": 5,
"queued_for_analysis": 3, # Only critical/important
"documents": [
{
"id": "ana_1a2b3c",
"filename": "Home_Inspection_Report.pdf",
"category": "critical", # Auto-detected
"is_analyzed": false,
"confidence": 0.95
},
{
"id": "ana_2b3c4d",
"filename": "Loan_Estimate.pdf",
"category": "important", # Auto-detected
"is_analyzed": false,
"confidence": 0.90
},
{
"id": "ana_3c4d5e",
"filename": "Seller_Disclosure.pdf",
"category": "critical", # Auto-detected
"is_analyzed": false,
"confidence": 0.95
},
{
"id": "ana_4d5e6f",
"filename": "Purchase_Agreement.pdf",
"category": "optional", # Will analyze on-demand
"is_analyzed": false,
"confidence": 0.80
},
{
"id": "ana_5e6f7g",
"filename": "Receipt_Earnest.pdf",
"category": "noise", # Skipped
"is_analyzed": false,
"confidence": 0.92
}
]
}
# Step 3: Poll document status (check every 5-10 seconds)
curl https://api.homeinsightai.com/v1/properties/prop_abc123/documents \
-H "Authorization: Bearer hi_live_YOUR_API_KEY"
# Response
{
"property_id": "prop_abc123",
"documents": [
{
"id": "ana_1a2b3c",
"status": "completed", # Analysis finished
"filename": "Home_Inspection_Report.pdf"
},
{
"id": "ana_2b3c4d",
"status": "processing", # Still analyzing
"filename": "Loan_Estimate.pdf"
}
],
"total": 5
}
# Step 4: Get combined summary (all documents)
curl https://api.homeinsightai.com/v1/properties/prop_abc123/summary \
-H "Authorization: Bearer hi_live_YOUR_API_KEY"
# Step 5: Get issues with page numbers
curl https://api.homeinsightai.com/v1/analyses/ana_1a2b3c/issues \
-H "Authorization: Bearer hi_live_YOUR_API_KEY"
When to use:
- Building end-user portals
- Real estate platforms
- Bulk document processing
- CRM integrations
- Need automatic categorization
Side-by-Side Comparison
| Feature | Analyses API | Properties API |
|---|---|---|
| Endpoint | POST /v1/analyses | POST /v1/properties/{id}/upload |
| Files per request | 1 PDF | 1-50 PDFs |
| Processing | Synchronous or manual trigger | Automatic background |
| Categorization | None (manual) | Automatic (60+ patterns) |
| Analysis timing | Immediate | Smart (critical/important only) |
| Response time | 15-30s (blocking) | 2-5s (instant, bg processing) |
| Summary location | metadata.summary | summary (top-level) |
| Use case | B2B API integrations | Portal/UI applications |
| Speed (50 docs) | 1500-3000s (sequential) | 150-300s (parallel) |
| API efficiency | 500 calls | 130 calls (74% reduction) |
Key Differences Explained
1. Summary Data Location
This is the most confusing difference:
Analyses API:
{
"id": "ana_abc123",
"metadata": {
"summary": "Home inspection report identifying 12 issues...",
"issues": [...]
}
}
Properties API:
{
"id": "ana_abc123",
"summary": "Home inspection report identifying 12 issues...", // Top-level
"metadata": {
"filename": "inspection.pdf",
"page_count": 25
}
}
Why the difference?
- Analyses API evolved from single-document design
- Properties API standardized on top-level
summaryfor consistency - Both work correctly, just different schema
Accessing summary in code:
// Analyses API
const summary = analysis.metadata?.summary || analysis.summary;
// Properties API
const summary = analysis.summary; // Always top-level
2. Processing Model
Analyses API (Blocking):
Upload → Process → Return results (15-30s)
Properties API (Non-blocking):
Upload → Return immediately (2s)
↓
Background: Categorize → Queue critical/important → Process (15-30s each)
3. Categorization
Analyses API:
- No categorization
- All documents analyzed immediately
- User decides what to upload
Properties API:
- Automatic categorization based on 60+ filename patterns
- Only critical/important analyzed automatically
- Optional documents analyzed on-demand
- Noise documents skipped
Categories:
critical: Inspection reports, disclosures (must analyze)important: Loan docs, appraisals (should analyze)optional: Purchase agreements (analyze if asked)noise: Receipts, HOA rules (skip analysis)
Migration Guide
Upgrading from Analyses to Properties API
If you're currently using the Analyses API and want bulk upload:
Before (Sequential):
// Upload 10 documents one-by-one (slow)
for (const file of files) {
await fetch('/v1/analyses', {
method: 'POST',
body: createFormData(file)
});
}
// Total time: 150-300 seconds
// API calls: 10
After (Parallel):
// Upload all documents at once (fast)
const formData = new FormData();
files.forEach(f => formData.append('files', f));
await fetch(`/v1/properties/${propertyId}/upload`, {
method: 'POST',
body: formData
});
// Total time: 2-5 seconds (instant)
// API calls: 1
// Background processing: 15-30 seconds per critical doc
Migration checklist:
- ✅ Create property before uploading
- ✅ Update endpoint from
/v1/analysesto/v1/properties/{id}/upload - ✅ Support multiple file selection
- ✅ Handle
documentsarray in response - ✅ Poll
/v1/properties/{id}/documentsfor status - ✅ Adjust summary access (
summaryvsmetadata.summary) - ✅ Handle categorization results
Error Handling
Handling 409 Conflict - Property Already Exists
When creating a property with an external_id or address that already exists, the API returns a 409 Conflict error:
{
"detail": "Property with this external_id or address already exists"
}
Best practice: Check if the property exists before creating it:
// Check if property exists by external_id
const getPropertyByExternalId = async (externalId: string) => {
const response = await fetch(
`https://api.homeinsightai.com/v1/properties?external_id=${externalId}`,
{
headers: { 'Authorization': `Bearer ${API_KEY}` }
}
);
if (response.ok) {
const data = await response.json();
return data.properties[0]; // Returns existing property or undefined
}
return null;
};
// Recommended flow: Check before create
const analyzeDocuments = async (address: string, externalId: string, files: File[]) => {
let propertyId: string;
// Step 1: Check if property exists
const existingProperty = await getPropertyByExternalId(externalId);
if (existingProperty) {
propertyId = existingProperty.id; // Use .id NOT .property_id ✅
console.log('Using existing property:', propertyId);
} else {
// Step 2: Create new property
const newProperty = await fetch('https://api.homeinsightai.com/v1/properties', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
external_id: externalId,
address: address
})
}).then(r => r.json());
propertyId = newProperty.id; // Use .id NOT .property_id ✅
console.log('Created new property:', propertyId);
}
// Step 3: Upload documents
const formData = new FormData();
files.forEach(f => formData.append('files', f));
const uploadResult = await fetch(
`https://api.homeinsightai.com/v1/properties/${propertyId}/upload`,
{
method: 'POST',
headers: { 'Authorization': `Bearer ${API_KEY}` },
body: formData
}
).then(r => r.json());
console.log(`Uploaded ${uploadResult.documents_uploaded} documents`);
// Step 4: Poll for completion
// ... (see polling examples above)
};
Alternative: Handle 409 gracefully
const createOrGetProperty = async (externalId: string, address: string) => {
try {
// Try to create
const response = await fetch('https://api.homeinsightai.com/v1/properties', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ external_id: externalId, address })
});
if (response.ok) {
const property = await response.json();
return property.id; // ✅ Use .id field
}
// Handle 409 Conflict
if (response.status === 409) {
console.log('Property exists, fetching...');
const existing = await getPropertyByExternalId(externalId);
return existing.id; // ✅ Use .id field
}
throw new Error(`Failed to create property: ${response.status}`);
} catch (error) {
console.error('Error creating/getting property:', error);
throw error;
}
};
Complete Endpoint Reference
| Action | Endpoint | Description |
|--------|----------|-------------|
| List/Search | GET /v1/properties?external_id=xxx | Check if property exists |
| Get by ID | GET /v1/properties/{id} | Get property details |
| Create | POST /v1/properties | Create new property (returns id field) |
| Upload docs | POST /v1/properties/{id}/upload | Add documents (batch) |
| Get docs | GET /v1/properties/{id}/documents | Poll document status |
IMPORTANT: The property creation response returns id, NOT property_id:
// ❌ WRONG
const propertyId = propertyResponse.property_id; // undefined!
// ✅ CORRECT
const propertyId = propertyResponse.id; // Works!
FAQ
Q: Which API should I use for my app?
Use Analyses API if:
- Building an SDK or API wrapper
- Single-document uploads only
- Need immediate processing
- Simple, straightforward workflow
Use Properties API if:
- Building an end-user portal
- Uploading 5+ documents at once
- Want automatic categorization
- Need best performance
Q: Can I use both APIs together?
Yes! Common pattern:
- Use Properties API for bulk uploads
- Use Analyses API for single-file additions later
Q: Why is summary in different locations?
Historical reasons. The Analyses API originally stored everything in metadata. The Properties API standardized on top-level summary. Both work, just access differently.
Q: How do I handle the summary difference in my code?
Use a fallback:
const summary = analysis.summary || analysis.metadata?.summary;
Q: Which API is faster?
Properties API is 6-9x faster for bulk uploads due to:
- Parallel background processing
- Automatic categorization (no wasted analysis)
- Single HTTP request for multiple files
Q: Do both APIs cost the same?
Yes. Billing is property-based, not per-file. Each unique property counts once per month regardless of which API you use.
Next Steps
- Analyses API Reference - Low-level API details
- Multi-File Upload Guide - Properties API details
- Auto-Categorization Guide - How categorization works
- Integration Examples - Complete code examples
Need help deciding? Contact us at support@homeinsightai.com