Airbnb Data API Documentation

Welcome to the BNBCalc API. This documentation helps you integrate short-term rental property analysis into your application.

Use the BNBCalc Airbnb Data API to get property revenue, occupancy, ADR, active Airbnb comparable listings, percentiles, investment metrics, and hosted report URLs for apps, reports, underwriting, and management tools.


Getting Started

To start using the BNBCalc Airbnb Data API, you'll need to:

1. Create a BNBCalc account or sign in to your existing account

2. Navigate to your account settings to generate an API key

3. Include your API key in all API requests using the x-bnbcalc-api-key header

4. Start making requests to access property data and analysis

All API endpoints use HTTPS and return JSON responses. Keep API keys on your server, not in browser or mobile client code. External API routes are currently throttled at 100 requests per second and use standard HTTP response codes to indicate success or failure.


Authentication

All API requests require authentication using an API key. API keys are tied to your BNBCalc account, should be kept server-side, and should never be exposed in frontend code. Include your API key in the request header as shown below:

x-bnbcalc-api-key: YOUR_API_KEY

You can generate API keys self-serve from your account settings page. Include the x-bnbcalc-api-key header in every API request to authenticate.


POST/v1/external/analysis/create/buy

Create Buy Analysis

Create a buy analysis for a short-term rental acquisition. Send location, property details, and purchase price to return projected revenue, occupancy, comps, cash flow, and ROI metrics.

AI requests are slower than standard calls. Allow up to 90 seconds and set your client timeout to at least 300 seconds. AI work is time-bounded, so a request always returns a usable analysis rather than hanging.

AI-selected comparables are available for United States properties and require at least 8 usable listing photos for the address. Listing photos are gathered in the background when an analysis is created, so calling enhance shortly afterwards is faster than requesting comparables during creation.

When an AI step cannot complete, the response still returns 200 with the valid analysis and a warnings array explaining what was skipped. Check warnings rather than assuming AI results are always present.

Each AI function that completes adds $0.10 to the call. AI steps that fail or time out are never charged, and /enhance is billed only for the AI functions that completed — it carries no base call fee.

Location Parameters (Conditional)

Either provide both lat AND lng, OR provide fullAddress. At least one method is required.

latnumberconditional

Latitude coordinate (must be provided with lng if fullAddress is not used)(e.g., 27.7676)

lngnumberconditional

Longitude coordinate (must be provided with lat if fullAddress is not used)(e.g., -82.6403)

fullAddressstringconditional

Complete property address (can be used instead of lat/lng coordinates)(e.g., 4935 2nd Avenue North, St. Petersburg, FL 33703)

Required Parameters

purchasePriceUSDnumberrequired

Purchase price in USD(e.g., 350000)

bedroomsnumberrequired

Number of bedrooms(e.g., 3)

bathroomsnumberrequired

Number of bathrooms(e.g., 2)

accomodatesnumberrequired

Number of guests the property can accommodate(e.g., 6)

Optional Parameters

monthlyRentUSDnumberoptional

Expected monthly rent in USD for long-term rental(e.g., 2500)

interestRatePercentagenumberoptional

Interest rate percentage (0-15)(e.g., 5.1)

squareFeetnumberoptional

Property square footage(e.g., 1500)

statestringoptional

State name(e.g., Florida)

citystringoptional

City name(e.g., St. Petersburg)

countystringoptional

County name(e.g., Pinellas County)

postalCodestringoptional

Postal/ZIP code(e.g., 33703)

countrystringoptional

Country name(e.g., United States)

streetstringoptional

Street name(e.g., 2nd Avenue North)

streetNumberstringoptional

Street number(e.g., 4935)

unitstringoptional

Unit/apartment number if applicable

addAICompsbooleanoptional

Select comparables with AI and apply the resulting revenue benchmark. US properties only, and requires at least 8 usable listing photos for the address.(e.g., true)

addAIExpenseEstimatesbooleanoptional

Estimate operating expenses with AI instead of using category defaults(e.g., true)

Example Request

curl -X POST \ https://atlas.bnbcalc.com/v1/external/analysis/create/buy \ -H "x-bnbcalc-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "lat": 27.7676, "lng": -82.6403, "bedrooms": 3, "bathrooms": 2, "accomodates": 6, "purchasePriceUSD": 400000 }'

Example Response

{ "success": true, "data": { "_id": "000000000000000000000000", "url": "https://www.bnbcalc.com/analysis/example-property/000000000000000000000000", "currency": "USD", "ratePerNightUSD": 364.73770491803276, "occupancyRatePercentage": 48, "bedrooms": 4, "bathrooms": 4, "commonSpaces": 1, "accomodates": 12, "fullAddress": "4935 2nd Avenue North, St. Petersburg, FL 33703", "location": { "type": "Point", "coordinates": [ -82.6403, 27.7676 ] }, "revenue": { "p25": 48210, "p50": 58440, "p75": 63944.76398163934, "p90": 74280, "avg": 60310 }, "adr": { "p25": 214, "p50": 288, "p75": 364.73770491803276, "p90": 431, "avg": 318 }, "occupancy": { "p25": 0.38, "p50": 0.44, "p75": 0.48, "p90": 0.56, "avg": 0.46 }, "quartiles": { "25th_percentile": { "average_daily_rate": 214, "occupancy_rate": 38, "revenue": 48210 }, "50th_percentile": { "average_daily_rate": 288, "occupancy_rate": 44, "revenue": 58440 }, "75th_percentile": { "average_daily_rate": 364.73770491803276, "occupancy_rate": 48, "revenue": 63944.76398163934 }, "90th_percentile": { "average_daily_rate": 431, "occupancy_rate": 56, "revenue": 74280 } }, "comparables": [ { "airbnbId": "12345678", "name": "Modern 4BR near downtown", "listingUrl": "https://www.airbnb.com/rooms/12345678", "bedrooms": 4, "bathrooms": 3, "accommodates": 10, "annualRevenueUSD": 68420, "occupancyRatePercentage": 52, "averageDailyRateUSD": 361, "distanceMiles": 0.4, "photo_urls": [ "https://a0.muscache.com/im/pictures/example/cover.jpg", "https://a0.muscache.com/im/pictures/example/living-room.jpg", "https://a0.muscache.com/im/pictures/example/kitchen.jpg" ] } ], "downPaymentPercentage": 20, "mortgageLength": 30, "yearsRemainingOnMortgage": 30, "interestRatePercentage": 4, "propertyTaxPercentage": 0.75, "monthlyRevenueUSD": 5328.730331803278, "monthlyExpensesUSD": 1474.1603364983607, "monthlyTaxesUSD": 250, "yearOneRevenueUSD": 63944.76398163934, "yearOneOperatingIncomeUSD": 46254.83994365901, "yearOneMorgageAndTaxesUSD": 21324, "yearOneCashFlowUSD": 24930.83994365901, "yearOneCashOnCashPercentage": 24.86817214984141, "yearOneCapRatePercentage": 11.563709985914752, "yearOneReturnOnInvestmentPercentage": 63.78402823049849, "yearOnePrincipalPaydownUSD": 85635.31658640636, "yearOneAppreciationUSD": 12000, "totalCashInvestment": 100252, "ltrPerMonthUSD": 1500, "ltrMonthlyExpensesPercentage": 10 } }

POST/v1/external/analysis/create/arb

Create Arbitrage Analysis

Create a rental arbitrage analysis for a leased property. Send monthly rent, location, and property details to return projected Airbnb revenue, cash flow, and comparable listings.

AI requests are slower than standard calls. Allow up to 90 seconds and set your client timeout to at least 300 seconds. AI work is time-bounded, so a request always returns a usable analysis rather than hanging.

AI-selected comparables are available for United States properties and require at least 8 usable listing photos for the address. Listing photos are gathered in the background when an analysis is created, so calling enhance shortly afterwards is faster than requesting comparables during creation.

When an AI step cannot complete, the response still returns 200 with the valid analysis and a warnings array explaining what was skipped. Check warnings rather than assuming AI results are always present.

Each AI function that completes adds $0.10 to the call. AI steps that fail or time out are never charged, and /enhance is billed only for the AI functions that completed — it carries no base call fee.

Location Parameters (Conditional)

Either provide both lat AND lng, OR provide fullAddress. At least one method is required.

latnumberconditional

Latitude coordinate (must be provided with lng if fullAddress is not used)(e.g., 27.7676)

lngnumberconditional

Longitude coordinate (must be provided with lat if fullAddress is not used)(e.g., -82.6403)

fullAddressstringconditional

Complete property address (can be used instead of lat/lng coordinates)(e.g., 4935 2nd Avenue North, St. Petersburg, FL 33703)

Required Parameters

monthlyRentUSDnumberrequired

Expected monthly rent in USD for long-term rental(e.g., 2500)

bedroomsnumberrequired

Number of bedrooms(e.g., 3)

bathroomsnumberrequired

Number of bathrooms(e.g., 2)

accomodatesnumberrequired

Number of guests the property can accommodate(e.g., 6)

Optional Parameters

purchasePriceUSDnumberoptional

Purchase price in USD(e.g., 350000)

squareFeetnumberoptional

Property square footage(e.g., 1500)

statestringoptional

State name(e.g., Florida)

citystringoptional

City name(e.g., St. Petersburg)

countystringoptional

County name(e.g., Pinellas County)

postalCodestringoptional

Postal/ZIP code(e.g., 33703)

countrystringoptional

Country name(e.g., United States)

streetstringoptional

Street name(e.g., 2nd Avenue North)

streetNumberstringoptional

Street number(e.g., 4935)

unitstringoptional

Unit/apartment number if applicable

addAICompsbooleanoptional

Select comparables with AI and apply the resulting revenue benchmark. US properties only, and requires at least 8 usable listing photos for the address.(e.g., true)

addAIExpenseEstimatesbooleanoptional

Estimate operating expenses with AI instead of using category defaults(e.g., true)

Example Request

curl -X POST \ https://atlas.bnbcalc.com/v1/external/analysis/create/arb \ -H "x-bnbcalc-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "lat": 27.7676, "lng": -82.6403, "bedrooms": 3, "bathrooms": 2, "accomodates": 6, "monthlyRentUSD": 2000 }'

Example Response

{ "success": true, "data": { "_id": "000000000000000000000000", "url": "https://www.bnbcalc.com/analysis/example-property/000000000000000000000000", "currency": "USD", "ratePerNightUSD": 364.73770491803276, "occupancyRatePercentage": 48, "bedrooms": 4, "bathrooms": 4, "commonSpaces": 1, "accomodates": 12, "fullAddress": "4935 2nd Avenue North, St. Petersburg, FL 33703", "location": { "type": "Point", "coordinates": [ -82.6403, 27.7676 ] }, "revenue": { "p25": 48210, "p50": 58440, "p75": 63944.76398163934, "p90": 74280, "avg": 60310 }, "adr": { "p25": 214, "p50": 288, "p75": 364.73770491803276, "p90": 431, "avg": 318 }, "occupancy": { "p25": 0.38, "p50": 0.44, "p75": 0.48, "p90": 0.56, "avg": 0.46 }, "quartiles": { "25th_percentile": { "average_daily_rate": 214, "occupancy_rate": 38, "revenue": 48210 }, "50th_percentile": { "average_daily_rate": 288, "occupancy_rate": 44, "revenue": 58440 }, "75th_percentile": { "average_daily_rate": 364.73770491803276, "occupancy_rate": 48, "revenue": 63944.76398163934 }, "90th_percentile": { "average_daily_rate": 431, "occupancy_rate": 56, "revenue": 74280 } }, "comparables": [ { "airbnbId": "12345678", "name": "Modern 4BR near downtown", "listingUrl": "https://www.airbnb.com/rooms/12345678", "bedrooms": 4, "bathrooms": 3, "accommodates": 10, "annualRevenueUSD": 68420, "occupancyRatePercentage": 52, "averageDailyRateUSD": 361, "distanceMiles": 0.4, "photo_urls": [ "https://a0.muscache.com/im/pictures/example/cover.jpg", "https://a0.muscache.com/im/pictures/example/living-room.jpg", "https://a0.muscache.com/im/pictures/example/kitchen.jpg" ] } ], "monthlyRentUSD": 2000, "yearOneRentUSD": 24000, "monthlyRevenueUSD": 13432.825977452352, "monthlyExpensesUSD": 2263.6108575197586, "yearOneRevenueUSD": 161193.91172942822, "yearOneOperatingIncomeUSD": 134030.58143919113, "yearOneCashFlowUSD": 110030.58143919116, "yearOneCashOnCashPercentage": 1317.415965507557, "totalCashInvestment": 8352 } }

POST/v1/external/analysis/create/owned

Create Owned Analysis

Create an owned-property analysis for a property already in your portfolio. Include mortgage terms to return STR revenue, cash flow, principal paydown, appreciation, and ROI metrics.

AI requests are slower than standard calls. Allow up to 90 seconds and set your client timeout to at least 300 seconds. AI work is time-bounded, so a request always returns a usable analysis rather than hanging.

AI-selected comparables are available for United States properties and require at least 8 usable listing photos for the address. Listing photos are gathered in the background when an analysis is created, so calling enhance shortly afterwards is faster than requesting comparables during creation.

When an AI step cannot complete, the response still returns 200 with the valid analysis and a warnings array explaining what was skipped. Check warnings rather than assuming AI results are always present.

Each AI function that completes adds $0.10 to the call. AI steps that fail or time out are never charged, and /enhance is billed only for the AI functions that completed — it carries no base call fee.

Location Parameters (Conditional)

Either provide both lat AND lng, OR provide fullAddress. At least one method is required.

latnumberconditional

Latitude coordinate (must be provided with lng if fullAddress is not used)(e.g., 27.7676)

lngnumberconditional

Longitude coordinate (must be provided with lat if fullAddress is not used)(e.g., -82.6403)

fullAddressstringconditional

Complete property address (can be used instead of lat/lng coordinates)(e.g., 4935 2nd Avenue North, St. Petersburg, FL 33703)

Required Parameters

purchasePriceUSDnumberrequired

Purchase price in USD(e.g., 350000)

downPaymentPercentagenumberrequired

Down payment percentage (0-40)(e.g., 20)

interestRatePercentagenumberrequired

Interest rate percentage (0-15)(e.g., 5.1)

mortgageLengthnumberrequired

Mortgage length in years (0-30)(e.g., 30)

yearsRemainingOnMortgagenumberrequired

Years remaining on mortgage (Can't be higher than mortgage length)

bedroomsnumberrequired

Number of bedrooms(e.g., 3)

bathroomsnumberrequired

Number of bathrooms(e.g., 2)

accomodatesnumberrequired

Number of guests the property can accommodate(e.g., 6)

Optional Parameters

monthlyRentUSDnumberoptional

Expected monthly rent in USD for long-term rental(e.g., 2500)

squareFeetnumberoptional

Property square footage(e.g., 1500)

statestringoptional

State name(e.g., Florida)

citystringoptional

City name(e.g., St. Petersburg)

countystringoptional

County name(e.g., Pinellas County)

postalCodestringoptional

Postal/ZIP code(e.g., 33703)

countrystringoptional

Country name(e.g., United States)

streetstringoptional

Street name(e.g., 2nd Avenue North)

streetNumberstringoptional

Street number(e.g., 4935)

unitstringoptional

Unit/apartment number if applicable

addAICompsbooleanoptional

Select comparables with AI and apply the resulting revenue benchmark. US properties only, and requires at least 8 usable listing photos for the address.(e.g., true)

addAIExpenseEstimatesbooleanoptional

Estimate operating expenses with AI instead of using category defaults(e.g., true)

Example Request

curl -X POST \ https://atlas.bnbcalc.com/v1/external/analysis/create/owned \ -H "x-bnbcalc-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "lat": 27.7676, "lng": -82.6403, "bedrooms": 3, "bathrooms": 2, "accomodates": 6, "purchasePriceUSD": 350000, "downPaymentPercentage": 20, "interestRatePercentage": 5.1, "mortgageLength": 30, "yearsRemainingOnMortgage": 30 }'

Example Response

{ "success": true, "data": { "_id": "000000000000000000000000", "url": "https://www.bnbcalc.com/analysis/example-property/000000000000000000000000", "currency": "USD", "ratePerNightUSD": 364.73770491803276, "occupancyRatePercentage": 48, "bedrooms": 4, "bathrooms": 4, "commonSpaces": 1, "accomodates": 12, "fullAddress": "4935 2nd Avenue North, St. Petersburg, FL 33703", "location": { "type": "Point", "coordinates": [ -82.6403, 27.7676 ] }, "revenue": { "p25": 48210, "p50": 58440, "p75": 63944.76398163934, "p90": 74280, "avg": 60310 }, "adr": { "p25": 214, "p50": 288, "p75": 364.73770491803276, "p90": 431, "avg": 318 }, "occupancy": { "p25": 0.38, "p50": 0.44, "p75": 0.48, "p90": 0.56, "avg": 0.46 }, "quartiles": { "25th_percentile": { "average_daily_rate": 214, "occupancy_rate": 38, "revenue": 48210 }, "50th_percentile": { "average_daily_rate": 288, "occupancy_rate": 44, "revenue": 58440 }, "75th_percentile": { "average_daily_rate": 364.73770491803276, "occupancy_rate": 48, "revenue": 63944.76398163934 }, "90th_percentile": { "average_daily_rate": 431, "occupancy_rate": 56, "revenue": 74280 } }, "comparables": [ { "airbnbId": "12345678", "name": "Modern 4BR near downtown", "listingUrl": "https://www.airbnb.com/rooms/12345678", "bedrooms": 4, "bathrooms": 3, "accommodates": 10, "annualRevenueUSD": 68420, "occupancyRatePercentage": 52, "averageDailyRateUSD": 361, "distanceMiles": 0.4, "photo_urls": [ "https://a0.muscache.com/im/pictures/example/cover.jpg", "https://a0.muscache.com/im/pictures/example/living-room.jpg", "https://a0.muscache.com/im/pictures/example/kitchen.jpg" ] } ], "downPaymentPercentage": 20, "mortgageLength": 30, "yearsRemainingOnMortgage": 30, "interestRatePercentage": 5.1, "propertyTaxPercentage": 0.75, "monthlyRevenueUSD": 5328.730331803278, "monthlyExpensesUSD": 1474.1603364983607, "monthlyTaxesUSD": 250, "yearOneRevenueUSD": 63944.76398163934, "yearOneOperatingIncomeUSD": 46254.83994365901, "yearOneMorgageAndTaxesUSD": 21324, "yearOneCashFlowUSD": 24930.83994365901, "yearOneCashOnCashPercentage": 24.86817214984141, "yearOneCapRatePercentage": 11.563709985914752, "yearOneReturnOnInvestmentPercentage": 63.78402823049849, "yearOnePrincipalPaydownUSD": 85635.31658640636, "yearOneAppreciationUSD": 12000, "totalCashInvestment": 100252, "ltrPerMonthUSD": 1500, "ltrMonthlyExpensesPercentage": 10 } }

POST/v1/external/analysis/create/cohost

Create Cohost Analysis

Create a co-hosting analysis for an owner lead or operator workflow. Return projected STR revenue, co-host commission, host return, and comparable listings.

AI requests are slower than standard calls. Allow up to 90 seconds and set your client timeout to at least 300 seconds. AI work is time-bounded, so a request always returns a usable analysis rather than hanging.

AI-selected comparables are available for United States properties and require at least 8 usable listing photos for the address. Listing photos are gathered in the background when an analysis is created, so calling enhance shortly afterwards is faster than requesting comparables during creation.

When an AI step cannot complete, the response still returns 200 with the valid analysis and a warnings array explaining what was skipped. Check warnings rather than assuming AI results are always present.

Each AI function that completes adds $0.10 to the call. AI steps that fail or time out are never charged, and /enhance is billed only for the AI functions that completed — it carries no base call fee.

Location Parameters (Conditional)

Either provide both lat AND lng, OR provide fullAddress. At least one method is required.

latnumberconditional

Latitude coordinate (must be provided with lng if fullAddress is not used)(e.g., 27.7676)

lngnumberconditional

Longitude coordinate (must be provided with lat if fullAddress is not used)(e.g., -82.6403)

fullAddressstringconditional

Complete property address (can be used instead of lat/lng coordinates)(e.g., 4935 2nd Avenue North, St. Petersburg, FL 33703)

Required Parameters

bedroomsnumberrequired

Number of bedrooms(e.g., 3)

bathroomsnumberrequired

Number of bathrooms(e.g., 2)

accomodatesnumberrequired

Number of guests the property can accommodate(e.g., 6)

Optional Parameters

cohostCommissionPercentagenumberoptional

Cohost commission percentage(e.g., 10)

squareFeetnumberoptional

Property square footage(e.g., 1500)

statestringoptional

State name(e.g., Florida)

citystringoptional

City name(e.g., St. Petersburg)

countystringoptional

County name(e.g., Pinellas County)

postalCodestringoptional

Postal/ZIP code(e.g., 33703)

countrystringoptional

Country name(e.g., United States)

streetstringoptional

Street name(e.g., 2nd Avenue North)

streetNumberstringoptional

Street number(e.g., 4935)

unitstringoptional

Unit/apartment number if applicable

addAICompsbooleanoptional

Select comparables with AI and apply the resulting revenue benchmark. US properties only, and requires at least 8 usable listing photos for the address.(e.g., true)

addAIExpenseEstimatesbooleanoptional

Estimate operating expenses with AI instead of using category defaults(e.g., true)

Example Request

curl -X POST \ https://atlas.bnbcalc.com/v1/external/analysis/create/cohost \ -H "x-bnbcalc-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "lat": 27.7676, "lng": -82.6403, "bedrooms": 3, "bathrooms": 2, "accomodates": 6 }'

Example Response

{ "success": true, "data": { "_id": "000000000000000000000000", "url": "https://www.bnbcalc.com/analysis/example-property/000000000000000000000000", "currency": "USD", "ratePerNightUSD": 364.73770491803276, "occupancyRatePercentage": 48, "bedrooms": 4, "bathrooms": 4, "commonSpaces": 1, "accomodates": 12, "fullAddress": "4935 2nd Avenue North, St. Petersburg, FL 33703", "location": { "type": "Point", "coordinates": [ -82.6403, 27.7676 ] }, "revenue": { "p25": 48210, "p50": 58440, "p75": 63944.76398163934, "p90": 74280, "avg": 60310 }, "adr": { "p25": 214, "p50": 288, "p75": 364.73770491803276, "p90": 431, "avg": 318 }, "occupancy": { "p25": 0.38, "p50": 0.44, "p75": 0.48, "p90": 0.56, "avg": 0.46 }, "quartiles": { "25th_percentile": { "average_daily_rate": 214, "occupancy_rate": 38, "revenue": 48210 }, "50th_percentile": { "average_daily_rate": 288, "occupancy_rate": 44, "revenue": 58440 }, "75th_percentile": { "average_daily_rate": 364.73770491803276, "occupancy_rate": 48, "revenue": 63944.76398163934 }, "90th_percentile": { "average_daily_rate": 431, "occupancy_rate": 56, "revenue": 74280 } }, "comparables": [ { "airbnbId": "12345678", "name": "Modern 4BR near downtown", "listingUrl": "https://www.airbnb.com/rooms/12345678", "bedrooms": 4, "bathrooms": 3, "accommodates": 10, "annualRevenueUSD": 68420, "occupancyRatePercentage": 52, "averageDailyRateUSD": 361, "distanceMiles": 0.4, "photo_urls": [ "https://a0.muscache.com/im/pictures/example/cover.jpg", "https://a0.muscache.com/im/pictures/example/living-room.jpg", "https://a0.muscache.com/im/pictures/example/kitchen.jpg" ] } ], "yearOneRevenueUSD": 161193.91172942825, "yearOneCohostReturnUSD": 116059.61644518835, "yearOneCohostCommissionUSD": 32238.78234588565 } }

POST/v1/external/analysis/enhance

Enhance Analysis with AI

Runs AI enrichment against an analysis you already created and returns the recalculated analysis. Use this when you want AI-selected comparables or AI expense estimates applied after the fact, or when you would rather keep the original create call fast.

AI requests are slower than standard calls. Allow up to 90 seconds and set your client timeout to at least 300 seconds. AI work is time-bounded, so a request always returns a usable analysis rather than hanging.

AI-selected comparables are available for United States properties and require at least 8 usable listing photos for the address. Listing photos are gathered in the background when an analysis is created, so calling enhance shortly afterwards is faster than requesting comparables during creation.

When an AI step cannot complete, the response still returns 200 with the valid analysis and a warnings array explaining what was skipped. Check warnings rather than assuming AI results are always present.

Each AI function that completes adds $0.10 to the call. AI steps that fail or time out are never charged, and /enhance is billed only for the AI functions that completed — it carries no base call fee.

If every AI function you requested fails, the call is free and the response contains only warnings — no data. Your stored analysis is unchanged in that case, so the copy you already have is still current. Create endpoints always return data, because their base fee covers the report itself.

Required Parameters

analysisIdstringrequired

The _id of an analysis previously created with your API key(e.g., 000000000000000000000000)

Optional Parameters

addAICompsbooleanoptional

Select comparables with AI and apply the resulting revenue benchmark. US properties only, and requires at least 8 usable listing photos for the address.(e.g., true)

addAIExpenseEstimatesbooleanoptional

Estimate operating expenses with AI instead of using category defaults(e.g., true)

Example Request

curl -X POST \ https://atlas.bnbcalc.com/v1/external/analysis/enhance \ -H "x-bnbcalc-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "analysisId": "000000000000000000000000", "addAIComps": true, "addAIExpenseEstimates": true }'

Example Response

{ "success": true, "data": { "_id": "000000000000000000000000", "url": "https://www.bnbcalc.com/analysis/example-property/000000000000000000000000", "currency": "USD", "ratePerNightUSD": 364.73770491803276, "occupancyRatePercentage": 48, "bedrooms": 4, "bathrooms": 4, "commonSpaces": 1, "accomodates": 12, "fullAddress": "4935 2nd Avenue North, St. Petersburg, FL 33703", "location": { "type": "Point", "coordinates": [ -82.6403, 27.7676 ] }, "revenue": { "p25": 48210, "p50": 58440, "p75": 63944.76398163934, "p90": 74280, "avg": 60310 }, "adr": { "p25": 214, "p50": 288, "p75": 364.73770491803276, "p90": 431, "avg": 318 }, "occupancy": { "p25": 0.38, "p50": 0.44, "p75": 0.48, "p90": 0.56, "avg": 0.46 }, "quartiles": { "25th_percentile": { "average_daily_rate": 214, "occupancy_rate": 38, "revenue": 48210 }, "50th_percentile": { "average_daily_rate": 288, "occupancy_rate": 44, "revenue": 58440 }, "75th_percentile": { "average_daily_rate": 364.73770491803276, "occupancy_rate": 48, "revenue": 63944.76398163934 }, "90th_percentile": { "average_daily_rate": 431, "occupancy_rate": 56, "revenue": 74280 } }, "comparables": [ { "airbnbId": "12345678", "name": "Modern 4BR near downtown", "listingUrl": "https://www.airbnb.com/rooms/12345678", "bedrooms": 4, "bathrooms": 3, "accommodates": 10, "annualRevenueUSD": 68420, "occupancyRatePercentage": 52, "averageDailyRateUSD": 361, "distanceMiles": 0.4, "photo_urls": [ "https://a0.muscache.com/im/pictures/example/cover.jpg", "https://a0.muscache.com/im/pictures/example/living-room.jpg", "https://a0.muscache.com/im/pictures/example/kitchen.jpg" ] } ], "propertyTaxPercentage": 0.75, "internetAndTVUSD": 90, "waterUSD": 85, "electricUSD": 180, "propertyInsuranceUSD": 210, "HOAUSD": 0, "repairsUSD": 125, "suppliesUSD": 60, "cleaningCostPercentage": 8.5, "monthlyRevenueUSD": 5328.730331803278, "monthlyExpensesUSD": 1474.1603364983607, "yearOneRevenueUSD": 63944.76398163934, "yearOneCashFlowUSD": 24930.83994365901, "yearOneCashOnCashPercentage": 24.86817214984141 }, "aiComps": { "selectedCompIds": [ "12345678", "23456789" ], "benchmark": { "annualRevenueUSD": 63944.76398163934, "ratePerNightUSD": 364.73770491803276, "occupancyRatePercentage": 48 }, "rationale": "Selected comparables matching bedroom count, pool and waterfront access.", "warnings": [], "applied": true } }

AI enrichment behavior

AI enrichment is opt-in per request through addAIComps and addAIExpenseEstimates, and every AI step is time-bounded and fails open. A request that asked for AI still returns 200 with a complete, fully recalculated analysis; anything that could not run is reported in the top-level warnings array instead of raising an error.

Timeouts and rate limits

AI work has a 90-second budget measured from the start of the request, not from the moment the AI step begins — geocoding and analysis creation count against it. When the budget runs out, the analysis is returned without the unfinished AI step and a timeout warning.

Set your client timeout to at least 300 seconds. Most AI calls return well inside the budget, but a client that aborts earlier than the server's own deadline turns a billable, completed analysis into a lost response.

A model call needs at least 45 seconds of remaining budget to start. A request that spends most of its budget waiting for listing photos returns ai_comps_timed_out without calling the model rather than starting a run it cannot finish.

Requests that set an AI flag are rate limited per API key: 10 per minute, with at most 2 in flight at once. Exceeding either returns 429 with a Retry-After header, and X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset are set on every AI request. Calls without an AI flag are not affected by this limit.

To retry a skipped AI step, call POST /v1/external/analysis/enhance with the same analysisId rather than creating the analysis again. Enhance carries no base call fee, so a retry costs only the AI functions that complete.

Response warnings

A 200 response can still carry a warnings array. Treat it as the record of what did not run and check it before assuming AI results are present. Every step reported here was skipped, and skipped steps are never billed.

ai_comps_requires_user_scoped_api_key

AI comps require an API key bound to a user account. The key could not be resolved to an owner, so the comp selector never ran.


ai_comps_unavailable_for_property

AI comps are available for United States properties only, and the stored analysis is outside that scope.


ai_comps_photos_not_ready

Usable listing photos for the address were not ready in time — none were found, too few were usable, or the gallery was still processing when the budget ran out. Photos are gathered in the background after an analysis is created, so retrying with /enhance shortly afterwards usually succeeds.


ai_comps_timed_out

The AI budget ran out before the model returned, so the deterministic comparables and revenue projection were kept.


ai_comps_benchmark_fallback

The model ran but selected too few comparables to form a benchmark, so the existing revenue projection was kept. Nothing was written to the analysis and the step was not charged.


ai_comps_model_unavailable

The model provider was unavailable. This is transient — retry with /enhance.


ai_comps_already_applied

This analysis already has a valid AI benchmark, so nothing was re-run and nothing was charged. Editing the property invalidates it, and the next call runs for real.


ai_comps_run_in_progress

Another AI comps run is already working on this analysis. Wait before retrying — the run holds a lock for up to 10 minutes.


ai_comps_analysis_changed

The analysis was edited while the model was running, so the benchmark was not written rather than overwriting the newer values. Retry with /enhance.


ai_comps_forbidden

The analysis was not created with this API key, so AI comps could not run against it.


ai_comps_failed

AI comps could not be completed for another reason. The analysis itself is valid and unchanged.


ai_expense_estimates_timed_out

The AI budget ran out before the expense estimator returned, so the default operating expenses were kept.


ai_expense_estimates_no_proposals

The estimator produced no expense proposals for this property, so no operating expense was changed.


ai_expense_estimates_stale_preview

The analysis changed while the estimate was being prepared, so it was discarded rather than applied to stale inputs. Retry with /enhance.


ai_expense_estimates_model_unavailable

The model provider was unavailable. This is transient — retry with /enhance.


ai_expense_estimates_already_applied

This analysis already has AI-estimated expenses, so nothing was re-run and nothing was charged.


ai_expense_estimates_unavailable_for_property

No operating expense field on this analysis was eligible for AI estimation, so its default expenses were kept.


ai_expense_estimates_forbidden

The analysis was not created with this API key, so AI expense estimates could not run against it.


ai_expense_estimates_failed

AI expense estimates could not be applied. The analysis keeps its default operating expenses.

Match on the ai_comps_ and ai_expense_estimates_ prefixes rather than the exact string: any other code with those prefixes means that step failed, was not applied, and was not charged.

Example Response

{ "success": true, "warnings": [ "ai_comps_photos_not_ready" ], "data": { "_id": "000000000000000000000000", "monthlyRevenueUSD": 5328.730331803278, "monthlyExpensesUSD": 1474.1603364983607 } }

aiComps.warnings

The nested aiComps.warnings array is a different signal from the top-level one: it describes the quality of the comparable pool the model worked with, not a step that failed. Read aiComps.applied to know whether the AI benchmark was actually written to the analysis.

thin_benchmark_pool

Fewer than four comparables backed the benchmark, so it rests on a small sample.


no_benchmark_comps

No comparable passed selection. The benchmark is empty and the revenue projection was left unchanged.


ai_benchmark_fallback_to_projected_revenue

Fewer than three comparables were selected, so the existing revenue projection was kept instead of the AI benchmark. This is the same outcome reported as ai_comps_benchmark_fallback at the top level.


minimum_benchmark_pool_backfill

The benchmark pool was padded with comparables the model did not choose in order to reach the minimum count.

Billing when AI is partial

Each AI function that completes adds $0.10 to the call. Steps that time out, fail, or fall back to the existing projection are not charged — aiComps.applied set to false means AI comps were not billed — and an /enhance call where every requested step was skipped is not billed at all.


Error Codes

The BNBCalc API uses standard HTTP response status codes to indicate the success or failure of API requests. Successfully created reports return 2xx codes, while errors return 4xx or 5xx codes with additional error information in the response body. You will only be charged for successfully created reports.

200

Success


400

Bad Request - Invalid parameters


401

Unauthorized - Invalid API key


403

Forbidden - The analysis does not belong to your API key, or AI estimates are disabled


404

Not Found - No analysis matches the supplied analysisId


409

Conflict - An AI run is already in progress for this analysis, or its values changed mid-request


429

Too Many Requests - External API route limit exceeded


500

Internal Server Error


502

Bad Gateway - The AI model returned an unusable response


503

Service Unavailable - The AI model is temporarily unavailable