Skip to content

Properties & Portfolios

The Properties API manages real estate assets and portfolios. Portfolios group properties for aggregate analytics and reporting. All endpoints require authentication and are prefixed with /pm.


Portfolios

POST /pm/portfolios

Create a new portfolio.

Auth required Yes

Request Body

Field Type Required Description
name string Yes Portfolio name
description string No Freeform description

Example Request

curl -X POST https://app.meterbase.io/api/v1/pm/portfolios \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "West Coast Holdings",
    "description": "All properties in CA, OR, and WA"
  }'

Example Response

201 Created

{
  "id": "pf_abc123",
  "name": "West Coast Holdings",
  "description": "All properties in CA, OR, and WA",
  "owner_id": "usr_a1b2c3d4",
  "created_at": "2026-03-25T14:00:00Z"
}

Error Cases

Status Detail Cause
401 "Not authenticated" Missing or expired token
422 "field required" Missing name field

GET /pm/portfolios

List all portfolios for the authenticated user.

Auth required Yes

Query Parameters

Parameter Type Default Description
page integer 1 Page number
per_page integer 20 Items per page (max 100)

Example Request

curl https://app.meterbase.io/api/v1/pm/portfolios \
  -H "Authorization: Bearer $TOKEN"

Example Response

200 OK

{
  "items": [
    {
      "id": "pf_abc123",
      "name": "West Coast Holdings",
      "description": "All properties in CA, OR, and WA",
      "property_count": 12,
      "created_at": "2026-03-25T14:00:00Z"
    }
  ],
  "total": 1,
  "page": 1,
  "per_page": 20,
  "pages": 1
}

GET /pm/portfolios/{id}

Retrieve a portfolio with a summary of its properties and costs.

Auth required Yes

Path Parameters

Parameter Type Description
id string Portfolio ID

Example Request

curl https://app.meterbase.io/api/v1/pm/portfolios/pf_abc123 \
  -H "Authorization: Bearer $TOKEN"

Example Response

200 OK

{
  "id": "pf_abc123",
  "name": "West Coast Holdings",
  "description": "All properties in CA, OR, and WA",
  "owner_id": "usr_a1b2c3d4",
  "created_at": "2026-03-25T14:00:00Z",
  "summary": {
    "property_count": 12,
    "total_monthly_cost": 48750.00,
    "total_annual_cost": 585000.00,
    "avg_cost_per_kwh": 0.187,
    "total_sqft": 245000
  }
}

Error Cases

Status Detail Cause
404 "Portfolio not found" Invalid or inaccessible portfolio ID

GET /pm/portfolios/{id}/analytics

Retrieve full analytics for a portfolio including cost trends, rate comparisons, and savings opportunities.

Auth required Yes

Path Parameters

Parameter Type Description
id string Portfolio ID

Example Request

curl https://app.meterbase.io/api/v1/pm/portfolios/pf_abc123/analytics \
  -H "Authorization: Bearer $TOKEN"

Example Response

200 OK

{
  "portfolio_id": "pf_abc123",
  "period": "2025-04-01/2026-03-31",
  "total_cost": 585000.00,
  "total_usage_kwh": 3128342,
  "avg_rate_per_kwh": 0.187,
  "cost_by_month": [
    { "month": "2025-04", "cost": 42500.00, "usage_kwh": 227272 },
    { "month": "2025-05", "cost": 44100.00, "usage_kwh": 235828 }
  ],
  "cost_by_property": [
    { "property_id": "prop_001", "name": "Sunset Apartments", "annual_cost": 72000.00 },
    { "property_id": "prop_002", "name": "Harbor View Plaza", "annual_cost": 96000.00 }
  ],
  "potential_savings": {
    "total_annual": 34200.00,
    "properties_with_savings": 8,
    "top_opportunity": {
      "property_id": "prop_002",
      "current_tariff": "SCE TOU-GS-2",
      "recommended_tariff": "SCE TOU-GS-3",
      "annual_savings": 8400.00
    }
  }
}

Properties

POST /pm/properties

Create a new property.

Auth required Yes

Request Body

Field Type Required Description
name string Yes Property name
address string Yes Street address
city string Yes City
state string Yes Two-letter state code (e.g., CA)
zip_code string Yes 5-digit ZIP code
property_type string Yes One of: residential, commercial, industrial, mixed_use
sqft integer No Total square footage
unit_count integer No Number of units (for multifamily)
year_built integer No Year the property was built
portfolio_id string No Portfolio to assign the property to
utility_account_number string No Utility account number
meter_number string No Meter identifier
tariff_id string No Current tariff ID from the tariff database
monthly_usage_kwh number No Estimated average monthly usage in kWh
monthly_demand_kw number No Estimated average monthly peak demand in kW
has_solar boolean No Whether the property has solar panels (default: false)
solar_capacity_kw number No Solar system capacity in kW
annual_revenue number No Annual revenue for NOI calculations
noi number No Net Operating Income
energy_pct_of_noi number No Energy cost as a percentage of NOI (auto-calculated if noi and energy cost are set)

Example Request

curl -X POST https://app.meterbase.io/api/v1/pm/properties \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Sunset Apartments",
    "address": "123 Main St",
    "city": "Los Angeles",
    "state": "CA",
    "zip_code": "90001",
    "property_type": "residential",
    "sqft": 24000,
    "unit_count": 32,
    "year_built": 1998,
    "portfolio_id": "pf_abc123",
    "monthly_usage_kwh": 15000,
    "monthly_demand_kw": 45,
    "has_solar": false
  }'

Example Response

201 Created

{
  "id": "prop_abc123",
  "name": "Sunset Apartments",
  "address": "123 Main St",
  "city": "Los Angeles",
  "state": "CA",
  "zip_code": "90001",
  "property_type": "residential",
  "sqft": 24000,
  "unit_count": 32,
  "year_built": 1998,
  "portfolio_id": "pf_abc123",
  "utility_account_number": null,
  "meter_number": null,
  "tariff_id": null,
  "monthly_usage_kwh": 15000,
  "monthly_demand_kw": 45,
  "has_solar": false,
  "solar_capacity_kw": null,
  "owner_id": "usr_a1b2c3d4",
  "created_at": "2026-03-25T14:00:00Z",
  "updated_at": "2026-03-25T14:00:00Z"
}

Error Cases

Status Detail Cause
422 "field required" Missing a required field
422 "Invalid state code" State not a valid 2-letter code
404 "Portfolio not found" Invalid portfolio_id

GET /pm/properties

List properties with optional filters.

Auth required Yes

Query Parameters

Parameter Type Default Description
portfolio_id string - Filter by portfolio
state string - Filter by state code
city string - Filter by city name
property_type string - Filter by property type
page integer 1 Page number
per_page integer 20 Items per page (max 100)

Example Request

curl "https://app.meterbase.io/api/v1/pm/properties?state=CA&property_type=residential&per_page=10" \
  -H "Authorization: Bearer $TOKEN"

Example Response

200 OK

{
  "items": [
    {
      "id": "prop_abc123",
      "name": "Sunset Apartments",
      "address": "123 Main St",
      "city": "Los Angeles",
      "state": "CA",
      "zip_code": "90001",
      "property_type": "residential",
      "sqft": 24000,
      "unit_count": 32,
      "monthly_usage_kwh": 15000,
      "portfolio_id": "pf_abc123"
    }
  ],
  "total": 1,
  "page": 1,
  "per_page": 10,
  "pages": 1
}

GET /pm/properties/{id}

Retrieve a property with full details and available tariffs for its service area.

Auth required Yes

Path Parameters

Parameter Type Description
id string Property ID

Example Request

curl https://app.meterbase.io/api/v1/pm/properties/prop_abc123 \
  -H "Authorization: Bearer $TOKEN"

Example Response

200 OK

{
  "id": "prop_abc123",
  "name": "Sunset Apartments",
  "address": "123 Main St",
  "city": "Los Angeles",
  "state": "CA",
  "zip_code": "90001",
  "property_type": "residential",
  "sqft": 24000,
  "unit_count": 32,
  "year_built": 1998,
  "portfolio_id": "pf_abc123",
  "utility_account_number": null,
  "meter_number": null,
  "tariff_id": "trf_sce_tou_gs2",
  "monthly_usage_kwh": 15000,
  "monthly_demand_kw": 45,
  "has_solar": false,
  "solar_capacity_kw": null,
  "owner_id": "usr_a1b2c3d4",
  "created_at": "2026-03-25T14:00:00Z",
  "updated_at": "2026-03-25T14:00:00Z",
  "available_tariffs": [
    {
      "id": "trf_sce_tou_gs1",
      "name": "SCE TOU-GS-1",
      "utility_name": "Southern California Edison",
      "rate_type": "tou",
      "sector": "commercial"
    },
    {
      "id": "trf_sce_tou_gs2",
      "name": "SCE TOU-GS-2",
      "utility_name": "Southern California Edison",
      "rate_type": "tou",
      "sector": "commercial"
    }
  ]
}

Error Cases

Status Detail Cause
404 "Property not found" Invalid or inaccessible property ID

PATCH /pm/properties/{id}

Update one or more fields on an existing property. Only include the fields you want to change.

Auth required Yes

Path Parameters

Parameter Type Description
id string Property ID

Request Body

Any subset of the fields from POST /pm/properties. All fields are optional.

Example Request

curl -X PATCH https://app.meterbase.io/api/v1/pm/properties/prop_abc123 \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tariff_id": "trf_sce_tou_gs3",
    "monthly_usage_kwh": 16500,
    "has_solar": true,
    "solar_capacity_kw": 50
  }'

Example Response

200 OK

Returns the full updated property object (same schema as GET /pm/properties/{id}, without available_tariffs).

Error Cases

Status Detail Cause
404 "Property not found" Invalid or inaccessible property ID
422 Validation errors Invalid field values

POST /pm/properties/{id}/analyze-rates

Run a rate analysis for a property, comparing its current tariff against all available alternatives.

Auth required Yes

Path Parameters

Parameter Type Description
id string Property ID

Example Request

curl -X POST https://app.meterbase.io/api/v1/pm/properties/prop_abc123/analyze-rates \
  -H "Authorization: Bearer $TOKEN"

Example Response

200 OK

{
  "property_id": "prop_abc123",
  "current_tariff": {
    "id": "trf_sce_tou_gs2",
    "name": "SCE TOU-GS-2",
    "estimated_monthly_cost": 3150.00
  },
  "alternatives": [
    {
      "tariff_id": "trf_sce_tou_gs3",
      "name": "SCE TOU-GS-3",
      "estimated_monthly_cost": 2850.00,
      "monthly_savings": 300.00,
      "annual_savings": 3600.00,
      "savings_percent": 9.5
    },
    {
      "tariff_id": "trf_sce_tou_gs1",
      "name": "SCE TOU-GS-1",
      "estimated_monthly_cost": 3400.00,
      "monthly_savings": -250.00,
      "annual_savings": -3000.00,
      "savings_percent": -7.9
    }
  ],
  "recommendation": "trf_sce_tou_gs3",
  "analyzed_at": "2026-03-25T14:30:00Z"
}

Tip

This endpoint requires the property to have monthly_usage_kwh set (and optionally monthly_demand_kw). If usage data is missing, you will receive a 400 error.

Error Cases

Status Detail Cause
404 "Property not found" Invalid property ID
400 "Property has no usage data" monthly_usage_kwh is not set
400 "No tariffs available for this service area" No tariffs found for the property's ZIP code

Dashboard

GET /pm/dashboard/stats

Retrieve aggregate dashboard statistics across all properties.

Auth required Yes

Example Request

curl https://app.meterbase.io/api/v1/pm/dashboard/stats \
  -H "Authorization: Bearer $TOKEN"

Example Response

200 OK

{
  "total_properties": 47,
  "total_portfolios": 3,
  "total_sqft": 1250000,
  "total_monthly_cost": 187500.00,
  "total_annual_cost": 2250000.00,
  "avg_cost_per_sqft": 1.80,
  "avg_cost_per_kwh": 0.172,
  "properties_with_savings": 23,
  "total_potential_savings": 124000.00,
  "alerts_unread": 5,
  "bills_this_month": 12
}

GET /pm/dashboard/cost-trend

Retrieve monthly cost trend data based on real bill data across all properties. Returns actual billed amounts (not estimates) for dashboard visualization.

Auth required Yes

Query Parameters

Parameter Type Default Description
months integer 12 Number of months to include (max 36)
portfolio_id string - Filter to a specific portfolio

Example Request

curl "https://app.meterbase.io/api/v1/pm/dashboard/cost-trend?months=12" \
  -H "Authorization: Bearer $TOKEN"

Example Response

200 OK

{
  "months": [
    { "month": "2025-04", "total_cost": 42500.00, "total_kwh": 227272, "property_count": 47 },
    { "month": "2025-05", "total_cost": 44100.00, "total_kwh": 235828, "property_count": 47 },
    { "month": "2025-06", "total_cost": 48200.00, "total_kwh": 257754, "property_count": 47 }
  ],
  "trend_direction": "increasing",
  "avg_monthly_cost": 44933.33
}

GET /pm/dashboard/global-analytics

Cross-portfolio analytics providing a unified view of energy costs, usage patterns, and savings across all properties the user has access to.

Auth required Yes

Example Request

curl https://app.meterbase.io/api/v1/pm/dashboard/global-analytics \
  -H "Authorization: Bearer $TOKEN"

Example Response

200 OK

{
  "total_properties": 47,
  "total_portfolios": 3,
  "total_annual_cost": 2250000.00,
  "total_annual_kwh": 12000000,
  "avg_cost_per_kwh": 0.1875,
  "avg_cost_per_sqft": 1.80,
  "cost_by_state": [
    { "state": "CA", "annual_cost": 1200000.00, "property_count": 25 },
    { "state": "OR", "annual_cost": 650000.00, "property_count": 12 }
  ],
  "cost_by_property_type": [
    { "type": "residential", "annual_cost": 1800000.00, "property_count": 38 },
    { "type": "mixed_use", "annual_cost": 450000.00, "property_count": 9 }
  ],
  "total_potential_savings": 124000.00,
  "properties_with_savings": 23
}

GET /pm/analytics/benchmarks

Benchmark properties against each other and against portfolio/regional averages. Returns rankings, percentiles, and outlier detection.

Auth required Yes (Pro tier required)

Query Parameters

Parameter Type Default Description
portfolio_id string - Filter to a specific portfolio
metric string cost_per_sqft Benchmark metric: cost_per_sqft, cost_per_unit, cost_per_kwh, kwh_per_sqft

Example Request

curl "https://app.meterbase.io/api/v1/pm/analytics/benchmarks?metric=cost_per_sqft" \
  -H "Authorization: Bearer $TOKEN"

Example Response

200 OK

{
  "metric": "cost_per_sqft",
  "portfolio_avg": 1.80,
  "portfolio_median": 1.65,
  "rankings": [
    { "property_id": "prop_005", "name": "Oakwood Residences", "value": 2.45, "percentile": 95, "outlier": true },
    { "property_id": "prop_002", "name": "Harbor View Plaza", "value": 2.10, "percentile": 82, "outlier": false },
    { "property_id": "prop_001", "name": "Sunset Apartments", "value": 1.65, "percentile": 50, "outlier": false }
  ],
  "outlier_threshold": 2.30,
  "outlier_count": 1
}

Pro Tier Required

Benchmarking is available only on the Pro and Enterprise tiers. Free tier users will receive a 403 response with an upgrade prompt.


POST /pm/due-diligence

Model projected utility costs for a prospective property acquisition. Provide property characteristics and receive estimated energy costs based on comparable properties and local tariff rates.

Auth required Yes (Pro tier required)

Request Body

Field Type Required Description
address string Yes Property street address
city string Yes City
state string Yes Two-letter state code
zip_code string Yes 5-digit ZIP code
unit_count integer Yes Number of units
sqft integer No Total square footage
property_type string No Property type (default: residential)
annual_revenue number No Projected annual revenue for NOI calculation

Example Request

curl -X POST https://app.meterbase.io/api/v1/pm/due-diligence \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "456 Oak Ave",
    "city": "Portland",
    "state": "OR",
    "zip_code": "97201",
    "unit_count": 64,
    "sqft": 72000,
    "annual_revenue": 1200000
  }'

Example Response

200 OK

{
  "property_summary": {
    "address": "456 Oak Ave",
    "city": "Portland",
    "state": "OR",
    "zip_code": "97201",
    "unit_count": 64,
    "sqft": 72000
  },
  "serving_utility": {
    "id": 842,
    "name": "Portland General Electric"
  },
  "estimated_costs": {
    "annual_energy_cost": 86400.00,
    "monthly_energy_cost": 7200.00,
    "cost_per_unit": 112.50,
    "cost_per_sqft": 1.20
  },
  "comparable_properties": 8,
  "available_tariffs": 5,
  "best_tariff": {
    "name": "PGE Schedule 32",
    "estimated_annual_cost": 78000.00
  },
  "noi_impact": {
    "annual_revenue": 1200000,
    "energy_pct_of_revenue": 7.2,
    "estimated_noi_impact": 86400.00
  }
}

GET /pm/properties/health

Retrieve health scores for all properties using a RAG (red/amber/green) status system. Health is determined by factors including bill anomalies, cost trends, savings opportunities, and data completeness.

Auth required Yes

Query Parameters

Parameter Type Default Description
portfolio_id string - Filter to a specific portfolio
status string - Filter by health status: green, yellow, red

Example Request

curl "https://app.meterbase.io/api/v1/pm/properties/health?status=red" \
  -H "Authorization: Bearer $TOKEN"

Example Response

200 OK

{
  "summary": {
    "green": 32,
    "yellow": 10,
    "red": 5,
    "total": 47
  },
  "properties": [
    {
      "property_id": "prop_005",
      "name": "Oakwood Residences",
      "status": "red",
      "score": 35,
      "issues": [
        "Cost per sqft 36% above portfolio average",
        "No bill data for 2+ months",
        "Savings opportunity of $8,400/year not acted on"
      ]
    },
    {
      "property_id": "prop_012",
      "name": "Riverside Commons",
      "status": "red",
      "score": 28,
      "issues": [
        "Usage anomaly detected (42% above rolling average)",
        "Missing tariff assignment"
      ]
    }
  ]
}