API Documentation - Profile Suite

Written by Brad Pirtle
Updated 6 days ago

Overview

This documentation explains how to use the SolarFax API for the Profile suite of functionality, which includes API's for getting usage profile data, getting Storage+Solar recommendations, and getting Storage+Solar bill savings.

Note: using these API's incur additional fees, contact support for more information.

Basics

For the basics on using the SolarFax API, refer to this article: API Documentation.

The first thing to do to use the Profile suite of API's, is to register a profile (similar to an account or site) with an address, which gives you a profile identifier (profile_id).  All other API's will take a profile_id as one of the mandatory parameters.  For seamless integration, you should store the profile_id with the account in your system for future API calls.


API Endpoints

GET profile - register a profile

There are four ways to register a profile:

  1. Address "parts" based. 

    Parameters:

    address_one Address line one
    city Address city
    state Address state
    zipCode Address zip code
    xid (Optional) ID from your system
    Example request:
    profile?address_one=123+East+St&city=Mountain+View&state=CA&zip_code=94043&xid=1234
    Example response:
    {
      "success": true,
      "message": "", 
      "profile": {
          "id": 0, 
          "xid": "1234", 
          "utility_id": 0, 
          "before_rate_schedule_id": 0, 
          "before_metering_id": null, 
          "after_rate_schedule_id": 25, 
          "after_metering_id": 3, 
          "created_on": "2025-08-25T22:14:11.432987", 
          "last_update": "2025-08-25T23:13:55.578894", 
          "utility": "PG&E"
          "address": {
            "address_one": "123 Easy St", 
            "address_two": "", 
            "city": "Mountain View", 
            "state": "CA", 
            "zip_code": "94043",
            "latitude": 37.3927515, 
            "longitude": -122.0682099, 
          }, 
      }, 
    }
  2. Address "string" based, like "123 East St, Mountain View, CA 94043"

    Example request:
    profile?address=123+East+St%2C+Mountain+View%2C+CA+94043
  3. ID lookup.  This lets you get a specific profile from a profile_id.

    Example request:
    profile?id=1234
  4. XID lookup.  XID is an ID field from your system if you specified it when initially registering a profile.

    Example request:
    profile?xid=1234

GET utilities - get nearest matching utilities for a profile

Parameters: 

profileId ID of the profile
searchTerm (Optional) name filter

Restrictions: returns first 25 results of utilities that service zip codes within a geocoded radius of the profile address.  Results are given a relevance "score", where highest is most probable.

Example request:

utilities?profile_id=0

Example CURL command (use your api-key and access-token):

curl -H 'Api-Key: KEY' -H 'Access-Token: TOKEN' -G -d 'profile_id=0' https://api.solardatapros.com/api/v1/utilities

Example response:

{
  "success": true, 
  "message": "", 
  "best_utility_id": 1, 
  "last_utility_id": 1, 
  "count": 1, 
  "utilities": [
    {
      "id": 1, 
      "name": "Pacific Gas & Electric Co.", 
      "short_name": "PG&E", 
      "short_name_alias": "Pacific Gas", 
      "type": 1, 
      "website": null, 
      "ownership_type": "Investor Owned", 
      "score": 1140, 
      "rate_res": 0.27084566974395236, 
      "rate_comm": 0.2504424822592163
    }
  ]
}

Selecting the Initial Utility

To help you select the initial utility for a profile, two fields should be used: last_utility_id (the last utility used by this profile), and best_utility_id (highest score).  Here is example Javascript code to determine the selected utility_id:

var selected_utility_id = null;

// Select the last, then best, then first in order
if (last_utility_id) {
    selected_utility_id = last_utility_id;
} else if (best_utility_id) {
    selected_utility_id = best_utility_id;
} else if (result.utilities.length) {
    selected_utility_id = result.utilities[0].id;
}

GET rate_schedules - get rate scheduled for a utility

Parameters: 

profile_id ID of the profile
utility_id ID of the utility
sector_id ID of the sector.  1 = Residential, 2 = Commercial, unspecified = All

Results are given a relevance "score", where highest is most probable.

Example request:

rate_schedules?profile_id=0&utility_id=0&sector_id=0

Example CURL command (use your api-key and access-token):

curl -H 'Api-Key: KEY' -H 'Access-Token: TOKEN' -G -d 'profile_id=0' -d 'utility_id=0' https://api.solardatapros.com/api/v1/rate_schedules

Example response:

{
  "success": true,
  "message": "",
  "best_rate_schedule_id": 378,
  "best_rate_schedule_metering_id": null,
  "solar_rate_schedule_id": 1,
  "solar_rate_schedule_metering_id": 3,
  "last_before_rate_schedule_id": 378,
  "last_before_rate_schedule_metering_id": null,
  "last_after_rate_schedule_id": 1,
  "last_after_rate_schedule_metering_id": 3,
  "count": 2,
  "rate_schedules": [
    {
      "id": 378,
      "name": "E-1 -Residential Service Baseline",
      "short_name": null,
      "short_name_alias": "E-1 -RES Svc Baseline",
      "provider_id": 1,
      "is_default": true,
      "source_url": "https://www.pge.com/tariffs/assets/pdf/tariffbook/ELEC_SCHEDS_E-1.pdf",
      "sector": "Residential",
      "average_rate": 0.4,
      "metering_id": null,
      "metering": null,
      "score": 11
    },
    {
      "id": 1,
      "name": "E-ELEC Residential Time of Use (Electric Home) - NBT",
      "short_name": "None - NBT",
      "short_name_alias": "E-ELEC RES TOU (Electric Home)",
      "provider_id": 1,
      "is_default": null,
      "source_url": "https://www.pge.com/tariffs/assets/pdf/tariffbook/ELEC_SCHEDS_E-ELEC.pdf",
      "sector": "Residential",
      "average_rate": 0.39,
      "metering_id": 3,
      "metering": "NBT",
      "score": 3
    },
  ]
}

Rate Schedule Metering

Using rate schedules requires both an ID (rate_schedule_id) and a Metering (metering_id).  Metering values are utility specific and by default is NULL.  Metering is very important when needed - for example the California Investor owned utilities (PGE, SCE, SDGE) use metering values 2 (NEM2) and 3 (NEM3 / NBT) to specify the net metering for billing, specifically post adding solar.  This concept will mostly be handled for you, where each rate schedule will have both an id and a metering_id - just be sure to pass both values to API's that need them.

To calculating savings when running a scenario, you will need a "before" rate schedule, and an "after" rate schedule.  This allows you to do two things: first, you can see how switching a rate schedule would effect the bill, and second (if the scenario includes adding solar), allows you to change to a specified solar rate schedule if the utility requires it.

Selecting the Initial "Before" Rate Schedule

 To help you select the initial "before" rate schedule for a profile, two combination fields should be used: last_before_rate_schedule_id / last_before_rate_schedule_metering_id (the last rate schedule used by this profile), and best_rate_schedule_id / best_rate_schedule_metering_id (highest score). 

Here is example Javascript code to determine the selected "before" rate_schedule_id:

var selected_rate_schedule_id = null,  selected_metering_id = null;

// Select the last, then best, then first in order
if (last_before_rate_schedule_id) {
    selected_rate_schedule_id = last_before_rate_schedule_id;
    selected_metering_id = last_before_rate_schedule_metering_id;
} else if (best_before_rate_schedule_id) {
    selected_rate_schedule_id = best_before_rate_schedule_id;
    selected_metering_id = best_before_rate_schedule_metering_id;
} else if (result.rate_schedules.length) {
    selected_rate_schedule_id = result.rate_schedules[0].id;
    selected_metering_id = result.rate_schedules[0].metering_id;
}

Selecting the Initial "After" Rate Schedule

To help you select the initial "after" rate schedule for a profile, three combination fields should be used: solar_rate_schedule_id / solar_rate_schedule_metering_id (if adding solar), last_before_rate_schedule_id / last_before_rate_schedule_metering_id (the last rate schedule used by this profile), and best_rate_schedule_id / best_rate_schedule_metering_id (highest score). 

Solar Rate Schedules

Some utilities require a specific rate schedule / metering when adding solar - an example is the California IOU's, where PG&E requires switching to E-ELEC and NBT/NEM3.  If it is required, this will be specified by the solar_rate_schedule_id / solar_rate_schedule_metering_id fields.

Here is example Javascript code to determine the selected "after" rate_schedule_id:

var selected_rate_schedule_id = null, selected_metering_id = null;
var solar = true;

// Select the solar, then last, then best, then first in order
if (solar && solar_rate_schedule_id) {
    selected_rate_schedule_id = solar_rate_schedule_id;
    selected_metering_id = solar_rate_schedule_metering_id;
} else if (last_after_rate_schedule_id) {
    selected_rate_schedule_id = last_after_rate_schedule_id;
    selected_metering_id = last_after_rate_schedule_metering_id;
} else if (best_after_rate_schedule_id) {
    selected_rate_schedule_id = best_after_rate_schedule_id;
    selected_metering_id = best_after_rate_schedule_metering_id;
} else if (result.rate_schedules.length) {
    selected_rate_schedule_id = result.rate_schedules[0].id;
    selected_metering_id = result.rate_schedules[0].metering_id;
}

GET load_profile - get nearest match hourly load profile for a profile

Parameters:

profile_id ID of the profile
utility_id ID of the utility
rate_schedule_id ID of the rate schedule
rate_schedule_metering_id ID of the rate schedule metering

Example request:

load_profile?profile_id=0&utility_id=0&rate_schedule_id=0&rate_schedule_metering_id=null

Example response:

{
  "success": true,
  "message": "",
  "usage": {
    "net_kWh": 8261.55,
    "annual_cost": 4108.19,
    "intervals": [
      {
        "start": "2024-01-01T00:00:00",
        "pull": 709613,
        "push": 0,
        "net": 709613
      },

      ... [ 8760 hourly values ] ...

      {
        "start": "2024-12-31T23:00:00",
        "pull": 981554,
        "push": 0,
        "net": 981554
      }
    ],
    "monthly_costs": [
      356.58,
      320.29,
      312.29,
      282.17,
      285.03,
      347.67,
      392.68,
      407.93,
      409.42,
      341.96,
      304.6,
      347.57
    ],
    "duration": 60,
    "units": "mWh"
  },
}

Hourly Interval Data

The usage field returns a year of hourly interval data, where each hour specifies the start date/time, and the push/pull/net usage values.  The duration field is in minutes, where 60 means hourly.  The units field specifies the unit of each value, currently this is "mWh" (milliwatt-hours).  This allows integer math (no decimals), where you can covert final values to kWh (kilowatt-hours):

kwh = mwh * 1e-6     // Move 6 decimal places

Costs

By passing a rate schedule, the monthly bills are calculated for you and returned in the monthly_costs field (an array of 12 monthly values).  These are calculated down to the hour using the correct rates (including Time of Use), and are not an average value.

POST modify_consumption - modify hourly consumption data

This API is used to modify hourly consumption data.  This data can be from the load_profile API, or it can be actual data from a CSV or data provider (including SolarFax).  It allows you to modify the consumption by giving "one number", currently one month of consumption or the annual consumption - the consumption data is scaled based on that.

Example: if the annual consumption is 10,000 kWh and you pass 20,000 as the modifiers_annual_kwh parameter, the consumption would be doubled.

This API allows you to have an interactive UI similar to this:

Parameters:

profile_id ID of the profile
usage_data hourly consumption data
utility_id ID of the utility
rate_schedule_id ID of the rate schedule
rate_schedule_metering_id ID of the rate schedule metering
modifiers_annual_kwh Modified annual consumption
modifiers_monthly_kwh Modified monthly consumption (array)

Example request (POST data):

{
   profile_id: 0,
   usage_data: [
      {
        "start": "2024-01-01T00:00:00",
        "pull": 709613,
        "push": 0,
        "net": 709613
      },
      ... [ 8760 hourly values ] ...
   ],
   utility_id: 0,
   rate_schedule_id: 0,
   rate_schedule_metering_id: null,
   modifiers_monthly_kwh: [null, null, null, null, null, 500, null, null, null, null, null, null],
   modifiers_annual_kwh: null,
}

Example response (same as response from the load_profile API):

{
  "success": true,
  "message": "",
  "usage": {
    "net_kWh": 8261.55,
    "annual_cost": 4108.19,
    "intervals": [
      {
        "start": "2024-01-01T00:00:00",
        "pull": 709613,
        "push": 0,
        "net": 709613
      },

      ... [ 8760 hourly values ] ...

      {
        "start": "2024-12-31T23:00:00",
        "pull": 981554,
        "push": 0,
        "net": 981554
      }
    ],
    "monthly_costs": [
      356.58,
      320.29,
      312.29,
      282.17,
      285.03,
      347.67,
      392.68,
      407.93,
      409.42,
      341.96,
      304.6,
      347.57
    ],
    "duration": 60,
    "units": "mWh"
  },
}

This API returns the same payload as the load_profile API, so they are interchangeable.

POST recommendation - Storage+Solar recommendation

This API is used to analyze a year of hourly consumption data, and give recommendations for storage sizing (batteries) and solar system sizing (production).  It currently returns a "min" and "max" recommendation, where min is enough to cover consumption during peak hours (the most expensive energy), and max is enough to cover peak+overnight (maximize grid independence).

Parameters:

profile_id ID of the profile
usage_data hourly consumption data
utility_id ID of the utility
rate_schedule_id ID of the rate schedule
rate_schedule_metering_id ID of the rate schedule metering

Example request (POST data):

{
   profile_id: 0,
   usage_data: [
      {
        "start": "2024-01-01T00:00:00",
        "pull": 709613,
        "push": 0,
        "net": 709613
      },
      ... [ 8760 hourly values ] ...
   ],
   utility_id: 0,
   rate_schedule_id: 0,
   rate_schedule_metering_id: null,
}

Example response:

{
  "success": true,
  "message": "",
  "recommendations": {
    "min": {
      "battery": 7.5,
      "nearest_battery": 10,
      "production": 4324.41,
      "system_size": 2.88,
      "consumption_offset": 52.3
    },
    "max": {
      "battery": 13.5,
      "nearest_battery": 15,
      "production": 6131.62,
      "system_size": 4.09,
      "consumption_offset": 74.2
    }
  }
}

This API request usage_data is the same payload as returned by the load_profile and modify_consumption API's, so you can pass them forward.

Battery Recommendation

Each recommendation contains the specific battery size battery (kWh), then the nearest battery nearest_battery, which is rounded to a multiple of the allowed battery sizes you setup in advance (kWh) - this is the value you should use.

Solar Recommendation

Each recommendation contains the production (kWh), system_size (kW) and consumption_offset (%).

POST savings - Savings from adding Storage+Solar

This API calculates the bill savings by adding storage+solar to a consumption profile, and/or changing the rate schedule. This is calculated down to the hour using the correct rates (including Time of Use), and are not average values.

Parameters:

profile_id ID of the profile
usage_data hourly consumption data
utility_id ID of the utility
before_rate_schedule_id ID of the rate schedule "before"
before_rate_schedule_metering_id ID of the rate schedule metering "before"
after_rate_schedule_id ID of the rate schedule "after"
after_rate_schedule_metering_id ID of the rate schedule metering "after"
battery_size Storage to add (kWh)
production Production to add (kWh)

Example request (POST data):

{
   profile_id: 0,
   usage_data: [
      {
        "start": "2024-01-01T00:00:00",
        "pull": 709613,
        "push": 0,
        "net": 709613
      },
      ... [ 8760 hourly values ] ...
   ],
   utility_id: 0,
   before_rate_schedule_id: 0,
   before_rate_schedule_metering_id: null,
   after_rate_schedule_id: 1,
   after_rate_schedule_metering_id: 3,
   battery_size: 10,
   production: 4324,
}

Example response:

{
  "success": true,
  "message": "",
  "savings": {
    "usage_cost_before": 341.5,
    "usage_cost_after": 121.25,
    "base_fee_before": 0,
    "base_fee_after": 15,
    "savings": 205.25
  }
}

This API request usage_data is the same payload as returned by the load_profile and modify_consumption API's, so you can pass them forward.  The battery_size and production values can come directly from the recommendation API result.

Savings

The response contains the average monthly usage cost before usage_cost_before ($), the average monthly usage_cost after usage_cost_after ($), the average monthly base fee before base_fee_before ($), the average monthly base fee after base_fee_after ($), and the average monthly savings savings ($).  All values are for the first year.

Here is an example graph from these values:

Did this answer your question?