Migrating from v0 to v1

The main motivation for v1 was the expansion of coverage to state, local, and utility (SLU) incentives. These incentives are much more diverse than the Inflation Reduction Act programs that are the entirety of v0 coverage, so we needed to make some major changes to the API to support them. This document is a guide to those changes, for clients who need to migrate from v0 to v1.

For more detailed documentation, please see here for requests and here for responses.

The "/incentives" endpoint was removed

With the set of incentives vastly expanded, it no longer makes sense to show a user all of them at once, unfiltered. If you have a use case for /v0/incentives that is not user-facing, you may be better served by using the underlying incentives data directly; you can contact us to discuss your needs.

The "/v1/utilities" endpoint was added

Incentives from utilities make up a sizable portion of the total. Given only an imprecise location like a ZIP code, though, we generally can’t tell which utility’s service territory a customer is in, and thus which utility’s offerings to consider. So we added this endpoint, which takes a ZIP code or address and returns a list of utilities that may serve that location.

The intended flow is that the user enters their location, and is presented with the list of utilities returned from this endpoint. They select one, and the selected utility is then passed to /v1/calculator to get incentives offered by that utility.

Total savings numbers were removed

The top-level /v0/calculator response had fields that contained estimates of how much money a consumer could save using the incentives in the response. In v1, we removed those fields, and we currently have no plans to add anything similar.

As we expanded to SLU incentives, we found many that were impossible to sensibly estimate a single numerical value for. Capacity-based heat pump incentives, for example, vary widely depending on the size of the consumer’s home, which the API doesn’t know. Some incentives also don’t have clearly defined monetary values of any kind; this is common among weatherization programs.

Furthermore, even if it were possible to estimate a dollar value for each incentive, we felt that simply adding them up would produce a misleading number. For example, a consumer may be eligible for a ground-source heat pump incentive and an air-source heat pump incentive, but it’s very unlikely that they would claim both; adding them would overestimate savings. It would be possible to implement such mutual-exclusion logic in code, but we decided that that shouldn’t be a concern of this API; it’s an “editorial” decision that depends on how the information is presented to users.

Responses now include the authorities offering incentives

In v0, all incentives could be assumed to be administered by the US federal government. With SLU incentives, there are many entities that offer incentives, of many different kinds, so we needed to add that to the API.

In v1, incentives have an authority field, which is a key into the top-level response’s authorities map. Each entry in that map includes a human-readable name for the authority, and optionally a logo. Incentives also have an authority_type field indicating the nature of the authority: what level of government they are, or whether they’re a utility, or something else.

More request parameters

Request parameters have been added to /v1/calculator endpoint to allow for filtering by item and authority type. There is also an address parameter, to which you can pass an address string instead of just a ZIP code.

Incentives’ "eligible" field was removed; ineligible incentives are not returned

The v0 API returned all incentives (after some deduplication, which we don’t need to go into here), each with a boolean eligible flag indicating whether the user was eligible given their inputs. The v1 API only returns eligible incentives, and does not have the eligible field. This is, again, because the set of all incentives is now much larger. The vast majority of them would be completely irrelevant to any given user, because they would be SLU incentives in other states.

Incentives’ "amount" became an object and gained a new type

We turned the separate amount and amount_type fields into a single amount field whose value is an object. amount_type became the type field of that object, and it has a new value, dollars_per_unit, that captures an incentive structure that wasn’t part of the IRA programs. This is for incentives whose monetary value scales linearly with some property of the product or service — e.g. heat pump size, battery capacity, insulation coverage area, and so on.

The object structure also captures maximum and minimum dollar amounts for incentives.

Incentives’ "type" and "item_type" became "payment_methods"

These fields generally describe how incentives are paid out to consumers. There were several reasons for these changes.

Most significantly, we found incentives that could be paid out in multiple ways, depending on various factors. For example, there are some utility incentives that are paid as an account credit if they’re below a certain amount, or as a check rebate otherwise.

We renamed the concept to payment_methods for clarity (“type” is a very generic term). item_type was mostly duplicative of type, and where it wasn’t, it was mixing in some unrelated concepts, so we removed it.

Additionally, there are more possible payment methods than there were “types”. Notably, we added rebate (post-purchase rebates), account_credit (a credit against utility bills), and assistance_program (the provision of no-cost products or services). These all came up as part of the SLU expansion; none of the IRA programs use them.

Incentives’ singular "item" became a list of "items" with more possible values

There are SLU incentives for many more categories of product and service than there are IRA programs. There are things the IRA programs don’t cover at all (like plug-in hybrid vehicles), and finer distinctions between categories than the IRA programs have (for example, different amounts for ducted and ductless heat pumps). To accurately express more of these distinctions, we’ve expanded the set of items that an incentive can pertain to. See this page for description of all the possible values.

In tandem with that expansion, the singular item value of the v0 API has become a list of items, to accommodate incentives that offer the same amount for any of several products and services.

Finally, v0’s singular item and item_es were user-facing strings; v1’s items are not localized, and not meant to be shown to users as-is. The best way to show labels for incentives’ items is dependent on the surrounding UI, so determining that is now left up to clients.

Incentives emphasize provider URLs

In v0, each incentive had a more_info_url field, which led to a Rewiring America page with background information about the equipment the incentive was for. Those pages no longer exist --- their URLs redirect to Rewiring America pages about the corresponding incentive programs --- and we’ve generally moved away from that style of content.

Incentives in v1 now have a program_url, which leads to a source directly from the incentive provider. When there are multiple candidate pages, we try to choose the one that seems most central (i.e. that links out to others), or that has the most specific information on the details of the incentive and how to claim it.

Some incentives also have an optional more_info_url, which leads to a non-official page with supplemental information on the incentive program. Currently all such pages are published by Rewiring America, but this may not always be the case.

Furthermore, in v0, the URLs were relative, with an assumed host of www.rewiringamerica.org. In v1, all URLs in responses are absolute.

Incentives’ "start_date" and "end_date" became more detailed

These fields were numeric in v0, representing just a year. In v1, they are strings, and they can express start and end dates of an incentive with year, month, day, half-year, or quarter-year granularity.

We made this change because a year is not precise enough to express our knowledge of when an incentive will begin, or cease, to be available. The simplest change would have been to switch to day granularity, but that didn’t make sense either: often, we only know that an incentive will begin “late in the year” or something like that, and representing that with a specific day would imply more precision than we want.

Localization is now done through a request parameter

The v0 API response included both English and Spanish versions of all user-visible strings. In v1, there is now a request parameter language, which can have the value en or es. Only that language’s version of each user-visible string is included. The new approach avoids sending unnecessary data in the response, and will scale better to more languages.

The list of incentive results is not partitioned by type

In the v0 response, there were two separate lists of incentives: pos_rebate_incentives and tax_credit_incentives. In v1, there is a single list called incentives. v1’s expansion of the possible incentive types made the partitioned lists less sensible. Each incentive already has a field indicating how it is paid out, so no information is lost.