Documentation Index
Fetch the complete documentation index at: https://docs.incentives.leap.energy/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The Incentives API calculates incentives across multiple utility programs for a customer address and device. It automatically handles customer creation, utility lookup, and incentive aggregation. For detailed endpoint specifications, see the Check Incentives API reference.Operation Types
The Incentives API supports three operation modes:lookup Operation
Use for first-time customers or when you need fresh utility data:
- Required fields:
address,building_type, anddevice_idsordevice_names - Creates a new customer if not found
- Geocodes the address to find applicable utilities
- Caches utility data on the customer record for future use
- Creates
customer_devicerecords for all devices (including duplicates when usingdevice_ids) - Slower due to address processing and utility lookup
- Device handling: On first call, creates all devices as customer devices. On subsequent calls, validates that all devices already exist for the customer.
refresh Operation
Use for returning customers with cached utility data (faster):
- Required fields: Only
reference_id - Customer must already exist
- Optional fields:
address: If provided and differs from stored address, updates customer address (still uses cached utilities, no geocoding)building_type: If not provided, resolved from customer’s storedbuilding_type_idin the databasedevice_ids:- If not provided: Uses all existing devices from customer’s
customer_devicestable - If provided: Validates that all
device_idsalready exist for the customer, then uses those devices
- If not provided: Uses all existing devices from customer’s
- Significantly faster—no geocoding or utility lookup required
- Uses cached utility data from previous lookup
- Device handling: Without
device_ids, uses all existing devices. Withdevice_ids, validates they exist before using them.
device_names is not supported for refresh operations. Use device_ids to specify devices, or omit devices entirely to use all existing devices.override Operation
Use when a customer changes their devices completely:
- Required fields:
reference_id,building_type, anddevice_idsordevice_names - Customer must already exist
- Optional fields:
address: If provided and differs from stored address, updates customer address (still uses cached utilities, no geocoding)
- Device handling: Deletes ALL existing customer devices, then creates new ones from the provided devices
- Then refreshes calculation using cached utilities (faster than lookup)
- Use when you need to completely replace a customer’s device list without validation errors
Reference IDs
Thereference_id field is required and serves multiple purposes:
- Must be unique within your account
- Enables fast lookups on subsequent API calls
- Use your internal customer/account ID for easy correlation
Reference IDs are scoped to your account. The same
reference_id can exist in different customer accounts without conflict.Creating Applications
Setcreate_application: true in the Incentives request to automatically create application records. When enabled, the response includes a connect_url field with a link to the customer application portal.
This streamlines the workflow by combining incentive calculation and application creation in a single API call.
Device IDs
Thedevice_ids field is an array that can contain multiple device IDs, including duplicates:
- Array format:
device_ids: [42, 44, 44, 44]creates 4 customer device records (1 for device 42, 3 for device 44) - Device categories: The API extracts unique device categories from all
device_idsand looks up programs for all device types (e.g., EV Chargers, Thermostats, Heat Pumps) - Required for:
lookupandoverrideoperations - Optional for:
refreshoperation (uses existing devices if not provided)
When using
refresh without device_ids, the API uses all existing devices from the customer’s customer_devices table. This allows refreshing with just the reference_id.Device Names
As an alternative todevice_ids, you can pass device_names — an array of your own equipment or product name strings. The API resolves these to Leap device IDs using your organization’s equipment map.
- Supported for:
lookupandoverrideoperations - Not supported for:
refreshoperations - Mutually exclusive with
device_ids— providing both returns a400error
Resolution Behavior
The API matches each name against your organization’s equipment map and resolves it to a Leap device ID:- All names resolve: The request proceeds normally using the resolved device IDs.
- Partial resolution: The request proceeds with the resolved devices. The response includes a
warningsobject listing the unresolved names so you can update your equipment map. - Zero resolution: The request fails with a
400error and anunresolved_device_namesarray listing the names that could not be matched.
Example Response with Warnings
When some device names cannot be resolved, the response includes awarnings object alongside the normal incentive results:
Example Workflow
First-Time Customer (Lookup)
First-Time Customer (Lookup with Device Names)
Returning Customer (Refresh - Minimal)
Returning Customer (Refresh - With Device Validation)
Customer Changed Devices (Override)
Best Practices
Choose the Right Operation Type
- First interaction: Use
lookupwith full address anddevice_idsordevice_names - Subsequent calls (same devices): Use
refreshwith just thereference_id(fastest option) - Subsequent calls (validate specific devices): Use
refreshwithreference_idanddevice_ids - Customer changed devices: Use
overrideto replace all devices - Address changes: Use
lookupto update utility information (geocodes new address)
Device ID Strategy
- Use arrays for
device_idseven for single devices:[42]not42 - Include duplicates in the array if customer has multiple of the same device:
[42, 42, 42] - For
refreshoperations, you can omitdevice_idsto use all existing devices - For
overrideoperations, provide the complete new device list (old devices are deleted)
Device Name Strategy
- Use
device_nameswhen you have equipment model names or product strings but not Leap device IDs - Check the
warningsobject in the response to catch unresolved names early device_namesworks withlookupandoverrideoperations only — usedevice_idsforrefresh- You cannot combine
device_idsanddevice_namesin the same request
Reference ID Strategy
- Use your internal customer/account ID as the
reference_id - Maintain consistency across all API calls for the same customer
- Store the mapping between your IDs and Leap’s
customer_idfor reference - Reference IDs are scoped to your organization (same ID can exist in different organizations)
Error Responses
Non-2xx responses follow a consistent shape:
error— human-readable message, suitable for logs or support tickets. May be revised over time.error_code— stable, typed identifier. Build retry logic and branching againsterror_code, not against the message.details— optional diagnostic payload whose shape varies byerror_code.
Error code reference
error_code | Status | When it happens | Retry? |
|---|---|---|---|
no_utility_at_address | 404 | Address is not covered by any known utility in our territory data | No — address is not serviceable; contact Leap if you believe this is a gap in our data |
address_not_geocodable | 422 | Address could not be resolved by the geocoder | No — correct the address and resubmit |
no_valid_eiaid | 404 | Matched utilities are missing EIA IDs in our catalog | No — contact Leap |
invalid_building_type | 400 | building_type is not a supported value | No — use RESIDENTIAL, MULTIFAMILY, MANUFACTURED_HOME, or COMMERCIAL |
building_type_unresolved | 400 | Could not resolve building type during a refresh | No — include building_type explicitly |
invalid_json_body | 400 | Request body was not valid JSON | No |
mutually_exclusive_device_inputs | 400 | Request included both device_ids and device_names | No — send one or the other |
device_names_not_supported_for_refresh | 400 | device_names is not supported for refresh | No — use device_ids or omit devices |
missing_devices | 400 | device_ids / device_names required for lookup or override | No |
no_device_categories | 400 | Provided device_ids don’t exist in our catalog | No |
upstream_transient | 502 | Transient upstream failure (geocoder, programs service) | Yes — exponential backoff |
upstream_infra | 502 | Upstream infrastructure error | Yes — exponential backoff |
device_name_resolution_failed | 500 | Internal error resolving device names | Yes — exponential backoff |
delete_customer_devices_failed | 500 | Internal error during override | Yes — exponential backoff |
cached_utilities_read_failed | 500 | Internal error reading cached utilities | Yes — exponential backoff |
internal_error | 500 | Unexpected server error | Yes — exponential backoff |
A small number of validation errors (e.g. reference ID mismatches, missing required fields on new-customer creation) currently return
4xx responses without an error_code field. When error_code is absent, fall back to matching on the error message. These paths are being migrated to the typed system.Retry strategy
For5xx errors, use exponential backoff — start at 1 second, double up to a cap of ~30 seconds, with a total retry budget around 60 seconds. Add random jitter to avoid thundering herd.
Do not retry 4xx responses. They indicate a request-level problem that won’t resolve without a change on your end (or a data fix on ours).
Common scenarios
- No utility found (
no_utility_at_address, 404): the address does not match any utility service territory in our data. This is not a transient failure — retrying the same address will return the same result. If you believe the address should be serviced, report it to Leap with thedetails.upstream_bodyfields so we can investigate the territory polygon. - Reference ID mismatch (400, no
error_codeyet): the customer already exists in your account under a differentreference_id. Use the originalreference_idfor this customer, or use a new one for a new customer. - Device not found on refresh: when using
refreshwithdevice_ids, all IDs must already be associated with the customer. Useoverrideif you need to replace the device list. - Unresolved device names: if zero names resolve, the request returns
400with anunresolved_device_namesarray. If some resolve, the request succeeds and the response includeswarnings.unresolved_device_names— update your equipment map for future calls.