> ## 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.

# Update Application

> Update an application by application ID. Supports updating application fields, customer information, and customer devices.

## Overview

Update application fields, customer information, and customer devices. Use `dryRun=true` as a query parameter to validate the request without applying changes.

<Tip>
  **Customer Devices**: Each device in `customer_devices` must include `id` (required, not optional). Missing `id` will return a 400 Bad Request error.
</Tip>

For more details on dry run mode and best practices, see the [API Guide](/api-reference/guides/api-guide).


## OpenAPI

````yaml PATCH /applications/{application_id}
openapi: 3.0.3
info:
  title: Leap Energy API
  description: >-
    The Leap Energy API provides a unified interface for managing rebate
    incentives and applications.


    ## Incentives API

    Search for and calculate incentive amounts across multiple utility programs.
    Given a customer

    address and building type, the API identifies applicable utility programs
    and calculates potential

    incentive amounts for various device and tier combinations. When your
    organization has a webhook URL

    configured (Webhook Config API), each successful lookup triggers a POST to
    your URL with the response

    and optional custom fields (`webhook_custom_fields`).


    ## Applications API

    Manage rebate applications on behalf of customers. Applications represent a
    customer's request

    for a rebate under a specific utility program, including customer
    information, device details,

    and application metadata.
  version: 2.0.0
  contact:
    name: Leap Energy
    url: https://leap.energy
servers:
  - url: https://api.incentives.leap.energy/alpha
    description: Production API
security:
  - ApiKeyAuth: []
  - BearerAuth: []
paths:
  /applications/{application_id}:
    patch:
      summary: Update application by application ID
      description: >
        Updates an application identified by application ID. Supports updating
        application fields, customer information, and customer devices.


        **Authentication:**

        Requires API key authentication via `x-api-key` header. The application
        must belong to your organization.


        **Application ID:**

        Use the `application_id` path parameter to identify which application to
        update. The API verifies the application belongs to your organization.


        **Request Structure:**

        Matches the GET `/applications/{id}` response structure (without
        protected fields):

        - Application fields at top level (e.g., `rebate_type`, `approval_date`)

        - `customer` (optional): Customer fields to update

        - `customer_devices` (optional): Array of devices to update (must
        include `id`)


        **Protected Fields:**

        The following fields cannot be updated: `id`, `customer_id`,
        `organization_id`, `program_id`, `status`, `created_at`, `updated_at`


        **Dry Run:**

        Set `dryRun=true` as a query parameter to validate the request without
        applying changes.


        **Partial Update Behavior:**

        - Only include fields you want to change

        - Omitted fields will keep their current values

        - Set a field to `null` to clear its value (where nullable)


        **Customer Devices:**

        - Must include `id` (required) to identify the device

        - Missing `id` will return 400 Bad Request with error code
        `invalid_body`


        **Status Field:**

        The `status` field is read-only for organizations and cannot be updated
        through this endpoint.


        All updates are transactional - if any part fails, the entire operation
        is rolled back.
      operationId: patchApplicationById
      parameters:
        - name: application_id
          in: path
          description: >-
            Application ID to update. The application must belong to your
            organization.
          required: true
          schema:
            type: integer
          example: 123
        - name: dryRun
          in: query
          description: If true, validates the request without applying changes
          required: false
          schema:
            type: boolean
            default: false
            example: false
      requestBody:
        required: true
        description: |
          Application update request. See schema for details.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OrgApplicationPatchRequest'
            examples:
              application_and_customer:
                summary: Update application and customer
                value:
                  approval_date: '2025-01-25'
                  customer:
                    email: newemail@example.com
                    phone: '+15559876543'
              application_only:
                summary: Update application only
                value:
                  submission_date: '2025-01-20'
              customer_and_devices:
                summary: Update customer and devices
                value:
                  customer:
                    email: updated@example.com
                  customer_devices:
                    - id: 78
                      inspection_passed: true
                      permit_number: PERMIT-2025-001
      responses:
        '200':
          description: Successfully updated application(s)
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    example: true
                  requestId:
                    type: string
                    example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                  application_id:
                    type: integer
                    example: 123
                  customer_id:
                    type: integer
                    example: 456
                  mutations:
                    type: object
                    description: Details about what was updated
                    properties:
                      application:
                        type: object
                        properties:
                          updated:
                            type: boolean
                          fields:
                            type: array
                            items:
                              type: string
                      customer:
                        type: object
                        properties:
                          updated:
                            type: boolean
                          fields:
                            type: array
                            items:
                              type: string
                      customer_devices:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            action:
                              type: string
                            fields:
                              type: array
                              items:
                                type: string
                  data:
                    type: object
                    description: >-
                      Complete snapshot matching GET `/applications/{id}`
                      response structure
                    allOf:
                      - $ref: '#/components/schemas/Application'
                      - type: object
                        properties:
                          customer:
                            $ref: '#/components/schemas/Customer'
              examples:
                successful_update:
                  summary: Successful update
                  value:
                    ok: true
                    requestId: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                    application_id: 123
                    customer_id: 456
                    mutations:
                      application:
                        updated: true
                        fields:
                          - status
                          - approval_date
                      customer:
                        updated: true
                        fields:
                          - email
                    data:
                      id: 123
                      program_id: 45
                      customer_id: 456
                      organization_id: 550e8400-e29b-41d4-a716-446655440000
                      status: approved
                      approval_date: '2025-01-25'
                      submission_date: '2025-01-15'
                      created_at: '2025-01-10T10:00:00Z'
                      updated_at: '2025-01-25T16:45:00Z'
                      customer:
                        id: 456
                        first_name: Jane
                        last_name: Doe
                        email: newemail@example.com
                        customer_devices:
                          - id: 10
                            customer_id: 456
                            device_id: 5
                            quantity: 1
        '400':
          description: Invalid request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Application not in your organization
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Application not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          $ref: '#/components/responses/InternalServerError'
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |-
            curl -X PATCH \
              "https://api.incentives.leap.energy/alpha/applications/123" \
              -H "x-api-key: leap_live_..." \
              -H "Content-Type: application/json" \
              -d '{
                "approval_date": "2025-01-25",
                "customer": {
                  "email": "newemail@example.com"
                }
              }'
        - lang: python
          label: Python
          source: |-
            import requests

            url = "https://api.incentives.leap.energy/alpha/applications/123"

            payload = {
                "approval_date": "2025-01-25",
                "customer": {
                    "email": "newemail@example.com"
                }
            }

            headers = {
                "x-api-key": "leap_live_...",
                "Content-Type": "application/json"
            }

            response = requests.patch(url, json=payload, headers=headers)
            print(response.json())
        - lang: javascript
          label: JavaScript
          source: |-
            const response = await fetch(
              'https://api.incentives.leap.energy/alpha/applications/123',
              {
                method: 'PATCH',
                headers: {
                  'x-api-key': 'leap_live_...',
                  'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                  approval_date: '2025-01-25',
                  customer: {
                    email: 'newemail@example.com'
                  }
                })
              }
            );

            const data = await response.json();
            console.log(data);
        - lang: node
          label: Node.js
          source: >-
            const axios = require('axios');


            const url =
            'https://api.incentives.leap.energy/alpha/applications/123';


            const payload = {
              approval_date: '2025-01-25',
              customer: {
                email: 'newemail@example.com'
              }
            };


            const response = await axios.patch(url, payload, {
              headers: {
                'x-api-key': 'leap_live_...',
                'Content-Type': 'application/json'
              }
            });


            console.log(response.data);
        - lang: php
          label: PHP
          source: |-
            <?php

            $url = 'https://api.incentives.leap.energy/alpha/applications/123';

            $payload = [
                'approval_date' => '2025-01-25',
                'customer' => [
                    'email' => 'newemail@example.com'
                ]
            ];

            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                'x-api-key: leap_live_...',
                'Content-Type: application/json'
            ]);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

            $response = curl_exec($ch);
            curl_close($ch);

            print_r(json_decode($response, true));
        - lang: java
          label: Java
          source: >-
            import java.net.http.*;

            import java.net.URI;


            HttpClient client = HttpClient.newHttpClient();


            String json = """{
              "approval_date": "2025-01-25",
              "customer": {
                "email": "newemail@example.com"
              }
            }""";


            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://api.incentives.leap.energy/alpha/applications/123"))
                .header("x-api-key", "leap_live_...")
                .header("Content-Type", "application/json")
                .method("PATCH", HttpRequest.BodyPublishers.ofString(json))
                .build();

            HttpResponse<String> response = client.send(request,
            HttpResponse.BodyHandlers.ofString());

            System.out.println(response.body());
        - lang: ruby
          label: Ruby
          source: >-
            require 'net/http'

            require 'json'


            uri =
            URI('https://api.incentives.leap.energy/alpha/applications/123')


            payload = {
              approval_date: '2025-01-25',
              customer: {
                email: 'newemail@example.com'
              }
            }


            http = Net::HTTP.new(uri.host, uri.port)

            http.use_ssl = true


            request = Net::HTTP::Patch.new(uri)

            request['x-api-key'] = 'leap_live_...'

            request['Content-Type'] = 'application/json'

            request.body = payload.to_json


            response = http.request(request)

            puts JSON.parse(response.body)
        - lang: go
          label: Go
          source: "package main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n)\n\nfunc main() {\n\turl := \"https://api.incentives.leap.energy/alpha/applications/123\"\n\n\tpayload := map[string]interface{}{\n\t\t\"approval_date\": \"2025-01-25\",\n\t\t\"customer\": map[string]interface{}{\n\t\t\t\"email\": \"newemail@example.com\",\n\t\t},\n\t}\n\n\tjsonData, _ := json.Marshal(payload)\n\treq, _ := http.NewRequest(\"PATCH\", url, bytes.NewBuffer(jsonData))\n\treq.Header.Set(\"x-api-key\", \"leap_live_...\")\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tclient := &http.Client{}\n\tresp, _ := client.Do(req)\n\tdefer resp.Body.Close()\n\n\tvar result map[string]interface{}\n\tjson.NewDecoder(resp.Body).Decode(&result)\n\tfmt.Println(result)\n}"
        - lang: csharp
          label: C#
          source: >-
            using System;

            using System.Net.Http;

            using System.Text;

            using System.Text.Json;

            using System.Threading.Tasks;


            var client = new HttpClient();

            var url =
            "https://api.incentives.leap.energy/alpha/applications/123";


            var payload = new {
                approval_date = "2025-01-25",
                customer = new {
                    email = "newemail@example.com"
                }
            };


            var content = new StringContent(
                JsonSerializer.Serialize(payload),
                Encoding.UTF8,
                "application/json"
            );


            var request = new HttpRequestMessage(new HttpMethod("PATCH"), url) {
                Content = content
            };

            request.Headers.Add("x-api-key", "leap_live_...");


            var response = await client.SendAsync(request);

            var result = await response.Content.ReadAsStringAsync();

            Console.WriteLine(result);
components:
  schemas:
    OrgApplicationPatchRequest:
      type: object
      description: >
        Request body for updating an application by application ID (organization
        authentication).

        Matches GET `/applications/{id}` response structure without protected
        fields.

        All fields are optional - only include fields you want to modify.


        **Protected fields** (cannot be updated): `id`, `customer_id`,
        `organization_id`, `program_id`, `status`, `created_at`, `updated_at`
      properties:
        rebate_type:
          type: string
          nullable: true
          description: Type of rebate being requested
        payee_type:
          type: string
          enum:
            - customer
            - contractor
            - instant
          nullable: true
          description: Who will receive the rebate payment
        submission_date:
          type: string
          format: date
          nullable: true
          description: Date the application was submitted
          example: '2025-01-20'
        approval_date:
          type: string
          format: date
          nullable: true
          description: Date the application was approved
          example: '2025-01-25'
        total_requested_amount:
          type: number
          format: decimal
          nullable: true
          description: Total rebate amount being requested
        equipment_complete:
          type: boolean
          nullable: true
          description: Whether equipment documentation is complete
        permit_complete:
          type: boolean
          nullable: true
          description: Whether permit documentation is complete
        utility_complete:
          type: boolean
          nullable: true
          description: Whether utility documentation is complete
        customer_device_id:
          type: array
          items:
            type: integer
          nullable: true
          description: Array of customer device IDs associated with this application
        customer:
          $ref: '#/components/schemas/CustomerPatchRequest'
          description: Customer fields to update (optional)
        customer_devices:
          type: array
          description: >-
            Array of customer devices to update. Each device must include 'id'
            to identify the device.
          items:
            $ref: '#/components/schemas/CustomerDevicePatchRequest'
    Application:
      type: object
      description: Complete application with nested customer and device information
      required:
        - id
        - program_id
        - customer_id
        - status
      properties:
        id:
          type: integer
          description: Unique identifier for the application
          example: 123
        program_id:
          type: integer
          description: ID of the rebate program this application is for
          example: 339
        customer_id:
          type: integer
          description: ID of the customer who owns this application
          example: 609
        reference_id:
          type: string
          nullable: true
          description: >-
            Your unique identifier for the customer in your system. Must be
            unique per customer within your organization and matches the value
            you use with the incentives API.
          example: external-ref-123
        customer_device_id:
          type: array
          items:
            type: integer
          description: Array of customer device IDs associated with this application
          example:
            - 45
            - 46
        rebate_type:
          type: string
          nullable: true
          description: Type of rebate being requested
          example: instant
        payee_type:
          type: string
          enum:
            - customer
            - contractor
            - instant
          nullable: true
          description: Who will receive the rebate payment
          example: customer
        submission_date:
          type: string
          format: date
          nullable: true
          description: Date the application was submitted
          example: '2025-01-15'
        approval_date:
          type: string
          format: date
          nullable: true
          description: Date the application was approved
          example: '2025-01-20'
        total_requested_amount:
          type: number
          format: decimal
          nullable: true
          description: Total rebate amount being requested
          example: 150
        recaptcha_token:
          type: string
          nullable: true
          description: reCAPTCHA token for bot prevention
        agree_terms:
          type: boolean
          nullable: true
          description: Whether customer agreed to terms and conditions
          example: true
        customer_signature:
          type: boolean
          nullable: true
          description: Whether customer has signed the application
          example: true
        customer_sig_date:
          type: string
          format: date
          nullable: true
          description: Date of customer signature
          example: '2025-01-15'
        contractor_signature:
          type: boolean
          nullable: true
          description: Whether contractor has signed the application
          example: false
        contractor_sig_date:
          type: string
          format: date
          nullable: true
          description: Date of contractor signature
        project_name:
          type: string
          maxLength: 255
          nullable: true
          description: Name/description of the project
          example: EV Charger Installation
        eligibility_category:
          type: string
          enum:
            - 1A
            - 1B
            - 1C
            - '2'
          nullable: true
          description: Eligibility category for tiered programs
        income_backup_onfile:
          type: boolean
          default: false
          description: Whether income verification documentation is on file
        neat_sir_verified:
          type: boolean
          nullable: true
          description: Whether NEAT/SIR verification is complete
        proposed_measures:
          type: object
          nullable: true
          description: JSONB object containing proposed energy efficiency measures
        prepay_amount:
          type: number
          format: decimal
          nullable: true
          description: Amount to be prepaid to contractor
        authorize_contractor:
          type: boolean
          default: false
          description: Authorization to pay contractor directly
        authorize_payee:
          type: boolean
          default: false
          description: Authorization to pay specified payee
        utility_account_attestation:
          type: boolean
          nullable: true
          description: Attestation that applicant is utility account holder
        status:
          type: string
          enum:
            - not_started
            - in_progress
            - awaiting_customer
            - awaiting_partner
            - completed
            - submitted
            - approved
            - rejected
          default: not_started
          description: Current status of the application
          example: in_progress
        equipment_complete:
          type: boolean
          nullable: true
          description: Whether all equipment documentation is complete
        permit_complete:
          type: boolean
          nullable: true
          description: Whether all permit documentation is complete
        utility_complete:
          type: boolean
          nullable: true
          description: Whether all utility documentation is complete
        created_at:
          type: string
          format: date-time
          description: Timestamp when application was created
          example: '2025-01-10T15:30:00Z'
        updated_at:
          type: string
          format: date-time
          description: Timestamp when application was last updated
          example: '2025-01-15T10:45:00Z'
        customer:
          $ref: '#/components/schemas/Customer'
    Customer:
      type: object
      description: Customer information associated with an application
      required:
        - id
        - address_line1
        - city
        - state
        - zip_code
      properties:
        id:
          type: integer
          description: Unique identifier for the customer
          example: 609
        first_name:
          type: string
          nullable: true
          description: Customer's first name
          example: John
        last_name:
          type: string
          nullable: true
          description: Customer's last name
          example: Doe
        email:
          type: string
          format: email
          nullable: true
          description: Customer's email address
          example: john.doe@example.com
        phone:
          type: string
          nullable: true
          description: Customer's phone number
          example: 555-123-4567
        address_line1:
          type: string
          description: Street address line 1
          example: 123 Peachtree St
        address_line2:
          type: string
          nullable: true
          description: Street address line 2 (apt, suite, etc.)
          example: Apt 4B
        city:
          type: string
          description: City
          example: Atlanta
        state:
          type: string
          description: State code (2 letters)
          example: GA
        zip_code:
          type: string
          description: ZIP code
          example: '30303'
        eiaid:
          type: string
          nullable: true
          description: Energy Information Administration utility ID
          example: '14354'
        utility_account_number:
          type: string
          nullable: true
          description: Customer's utility account number
          example: ACC-123456789
        building_type_id:
          type: integer
          nullable: true
          description: ID of the building type
          example: 1
        is_homeowner:
          type: boolean
          default: false
          description: Whether customer owns the property
          example: true
        is_income_qualified:
          type: boolean
          default: false
          description: Whether customer qualifies for income-based programs
          example: false
        building_age_years:
          type: integer
          nullable: true
          description: Age of the building in years
          example: 25
        within_city_limits:
          type: boolean
          nullable: true
          description: Whether property is within city limits
          example: true
        referral_source:
          type: string
          maxLength: 255
          nullable: true
          description: How customer heard about the program
          example: utility website
        fax:
          type: string
          nullable: true
          description: Customer's fax number
        conditioned_sqft:
          type: integer
          nullable: true
          description: Square footage of conditioned space
          example: 2000
        gut_rehab:
          type: boolean
          default: false
          description: Whether property is undergoing gut rehabilitation
        gas_appliance_present:
          type: boolean
          default: false
          description: Whether gas appliances are present
        home_energy_assessment_completed:
          type: boolean
          default: false
          description: Whether a home energy assessment has been completed
        household_size:
          type: integer
          nullable: true
          description: Number of people in household
          example: 4
        mailing_address_line1:
          type: string
          nullable: true
          description: Mailing address if different from property address
        mailing_city:
          type: string
          nullable: true
          description: Mailing address city
        mailing_state:
          type: string
          nullable: true
          description: Mailing address state
        mailing_zip:
          type: string
          nullable: true
          description: Mailing address ZIP code
        alt_phone:
          type: string
          nullable: true
          description: Alternate phone number
        biz_tax_status:
          type: string
          nullable: true
          description: Business tax status
        ca_entity_id:
          type: string
          nullable: true
          description: California entity ID
        county_parish:
          type: string
          nullable: true
          description: County or parish name
          example: Fulton County
        is_indigenous:
          type: boolean
          default: false
          description: Whether customer identifies as indigenous
        is_veteran:
          type: boolean
          default: false
          description: Whether customer is a veteran
        is_senior:
          type: boolean
          default: false
          description: Whether customer is a senior
        is_first_responder:
          type: boolean
          default: false
          description: Whether customer is a first responder
        property_details:
          type: object
          default: {}
          description: Additional property details as JSONB
        utility_rate_plan:
          type: string
          nullable: true
          description: Customer's utility rate plan
          example: R-1B
        utility_account_status:
          type: string
          enum:
            - active
            - inactive
            - pending
          default: active
          description: Status of utility account
        dwelling_units:
          type: integer
          nullable: true
          description: Number of dwelling units in building
          example: 1
        is_test:
          type: boolean
          default: false
          description: Whether this is a test customer record
        customer_devices:
          type: array
          description: Array of devices associated with this customer
          items:
            $ref: '#/components/schemas/CustomerDevice'
    Error:
      type: object
      required:
        - code
        - message
        - requestId
      properties:
        code:
          type: string
          description: Error code identifying the type of error
          example: not_found
        message:
          type: string
          description: Human-readable error message
          example: Application 123 not found
        details:
          description: Additional error details (optional)
          example: Additional context about the error
        requestId:
          type: string
          description: Unique request identifier for tracking and debugging
          example: 550e8400-e29b-41d4-a716-446655440000
    CustomerPatchRequest:
      type: object
      description: |
        Customer information to partially update.
        All fields are optional - only include fields you want to modify.
      properties:
        first_name:
          type: string
          nullable: true
        last_name:
          type: string
          nullable: true
        email:
          type: string
          format: email
          nullable: true
        phone:
          type: string
          nullable: true
        address_line1:
          type: string
        address_line2:
          type: string
          nullable: true
        city:
          type: string
        state:
          type: string
        zip_code:
          type: string
        eiaid:
          type: string
          nullable: true
        utility_account_number:
          type: string
          nullable: true
        building_type_id:
          type: integer
          nullable: true
        is_homeowner:
          type: boolean
        is_income_qualified:
          type: boolean
        building_age_years:
          type: integer
          nullable: true
        within_city_limits:
          type: boolean
          nullable: true
        referral_source:
          type: string
          maxLength: 255
          nullable: true
        fax:
          type: string
          nullable: true
        conditioned_sqft:
          type: integer
          nullable: true
        gut_rehab:
          type: boolean
        gas_appliance_present:
          type: boolean
        home_energy_assessment_completed:
          type: boolean
        household_size:
          type: integer
          nullable: true
        mailing_address_line1:
          type: string
          nullable: true
        mailing_city:
          type: string
          nullable: true
        mailing_state:
          type: string
          nullable: true
        mailing_zip:
          type: string
          nullable: true
        alt_phone:
          type: string
          nullable: true
        biz_tax_status:
          type: string
          nullable: true
        ca_entity_id:
          type: string
          nullable: true
        county_parish:
          type: string
          nullable: true
        is_indigenous:
          type: boolean
        is_veteran:
          type: boolean
        is_senior:
          type: boolean
        is_first_responder:
          type: boolean
        property_details:
          type: object
        utility_rate_plan:
          type: string
          nullable: true
        utility_account_status:
          type: string
          enum:
            - active
            - inactive
            - pending
        dwelling_units:
          type: integer
          nullable: true
        customer_devices:
          type: array
          description: >
            Array of customer devices to update or create.

            Include `id` to update existing device, omit `id` to create new
            device.
          items:
            $ref: '#/components/schemas/CustomerDevicePatchRequest'
    CustomerDevicePatchRequest:
      type: object
      description: |
        Customer device information to update.
        - Must include 'id' (required) to identify the device
        - All other fields are optional
      required:
        - id
      properties:
        id:
          type: integer
          description: ID of existing customer device (required)
          example: 78
        device_id:
          type: integer
          nullable: true
        quantity:
          type: integer
        purchase_price:
          type: number
          format: decimal
          nullable: true
        installation_cost:
          type: number
          format: decimal
          nullable: true
        total_project_cost:
          type: number
          format: decimal
          nullable: true
        purchase_date:
          type: string
          format: date
          nullable: true
        installation_date:
          type: string
          format: date
          nullable: true
        existing_equipment_age_years:
          type: integer
          nullable: true
        existing_equipment_operational:
          type: boolean
          nullable: true
        existing_equipment_manufacturer:
          type: string
          maxLength: 100
          nullable: true
        existing_equipment_model:
          type: string
          maxLength: 100
          nullable: true
        installation_location:
          type: string
          maxLength: 100
          nullable: true
        contractor_name:
          type: string
          maxLength: 200
          nullable: true
        contractor_license:
          type: string
          maxLength: 100
          nullable: true
        permits_obtained:
          type: boolean
        inspection_passed:
          type: boolean
        application_submitted_date:
          type: string
          format: date
          nullable: true
        permit_number:
          type: string
          nullable: true
        vehicle_year:
          type: integer
          nullable: true
        vehicle_vin:
          type: string
          nullable: true
        dealership:
          type: string
          nullable: true
        contractor_contact_email:
          type: string
          format: email
          nullable: true
        contractor_contact_phone:
          type: string
          nullable: true
        contractor_website:
          type: string
          format: uri
          nullable: true
        trenching_required:
          type: boolean
          nullable: true
        contractor_contact_name:
          type: string
          maxLength: 255
          nullable: true
        contractor_address_line1:
          type: string
          maxLength: 255
          nullable: true
        contractor_city:
          type: string
          maxLength: 255
          nullable: true
        contractor_state:
          type: string
          maxLength: 255
          nullable: true
        contractor_zip:
          type: string
          maxLength: 20
          nullable: true
        existing_equipment_photos_provided:
          type: boolean
          nullable: true
        existing_equipment_serial:
          type: string
          maxLength: 255
          nullable: true
        existing_heating_type:
          type: string
          maxLength: 255
          nullable: true
        device_serial:
          type: string
          maxLength: 255
          nullable: true
        louvered_sides:
          type: boolean
          nullable: true
        contractor_fax:
          type: string
          nullable: true
        coil_make_model:
          type: string
          nullable: true
    CustomerDevice:
      type: object
      description: Device purchased and installed by customer
      required:
        - id
        - customer_id
      properties:
        id:
          type: integer
          description: Unique identifier for this customer device record
          example: 45
        customer_id:
          type: integer
          description: ID of the customer who owns this device
          example: 609
        device_id:
          type: integer
          nullable: true
          description: ID of the device from the devices catalog
          example: 240
        quantity:
          type: integer
          default: 1
          description: Number of devices purchased
          example: 1
        purchase_price:
          type: number
          format: decimal
          nullable: true
          description: Price paid for the device
          example: 599.99
        installation_cost:
          type: number
          format: decimal
          nullable: true
          description: Cost of installation
          example: 450
        total_project_cost:
          type: number
          format: decimal
          nullable: true
          description: Total cost including equipment and installation
          example: 1049.99
        purchase_date:
          type: string
          format: date
          nullable: true
          description: Date device was purchased
          example: '2025-01-05'
        installation_date:
          type: string
          format: date
          nullable: true
          description: Date device was installed
          example: '2025-01-10'
        existing_equipment_age_years:
          type: integer
          nullable: true
          description: Age of equipment being replaced
          example: 15
        existing_equipment_operational:
          type: boolean
          nullable: true
          description: Whether existing equipment is still operational
          example: false
        existing_equipment_manufacturer:
          type: string
          maxLength: 100
          nullable: true
          description: Manufacturer of existing equipment
          example: Old Brand
        existing_equipment_model:
          type: string
          maxLength: 100
          nullable: true
          description: Model of existing equipment
          example: Model-X
        installation_location:
          type: string
          maxLength: 100
          nullable: true
          description: Where device was installed
          example: Garage
        contractor_name:
          type: string
          maxLength: 200
          nullable: true
          description: Name of contractor who performed installation
          example: ABC Electric
        contractor_license:
          type: string
          maxLength: 100
          nullable: true
          description: Contractor's license number
          example: EC-12345
        permits_obtained:
          type: boolean
          default: false
          description: Whether required permits were obtained
          example: true
        inspection_passed:
          type: boolean
          default: false
          description: Whether inspection passed
          example: true
        application_submitted_date:
          type: string
          format: date
          nullable: true
          description: Date application was submitted
          example: '2025-01-15'
        permit_number:
          type: string
          nullable: true
          description: Permit number
          example: PMT-2025-001
        vehicle_year:
          type: integer
          nullable: true
          description: Year of vehicle (for EV chargers)
          example: 2023
        vehicle_vin:
          type: string
          nullable: true
          description: Vehicle identification number
          example: 5YJ3E1EA9KF123456
        dealership:
          type: string
          nullable: true
          description: Dealership where vehicle was purchased
          example: Tesla Atlanta
        contractor_contact_email:
          type: string
          format: email
          nullable: true
          description: Contractor's email
          example: contact@abcelectric.com
        contractor_contact_phone:
          type: string
          nullable: true
          description: Contractor's phone number
          example: 555-987-6543
        contractor_website:
          type: string
          format: uri
          nullable: true
          description: Contractor's website
          example: https://www.abcelectric.com
        trenching_required:
          type: boolean
          nullable: true
          description: Whether trenching was required for installation
          example: false
        contractor_contact_name:
          type: string
          maxLength: 255
          nullable: true
          description: Name of contractor contact person
          example: Jane Smith
        contractor_address_line1:
          type: string
          maxLength: 255
          nullable: true
          description: Contractor's street address
          example: 789 Business Blvd
        contractor_city:
          type: string
          maxLength: 255
          nullable: true
          description: Contractor's city
          example: Atlanta
        contractor_state:
          type: string
          maxLength: 255
          nullable: true
          description: Contractor's state
          example: GA
        contractor_zip:
          type: string
          maxLength: 20
          nullable: true
          description: Contractor's ZIP code
          example: '30301'
        existing_equipment_photos_provided:
          type: boolean
          nullable: true
          description: Whether photos of existing equipment were provided
        existing_equipment_serial:
          type: string
          maxLength: 255
          nullable: true
          description: Serial number of existing equipment
        existing_heating_type:
          type: string
          maxLength: 255
          nullable: true
          description: Type of existing heating system
          example: Gas furnace
        device_serial:
          type: string
          maxLength: 255
          nullable: true
          description: Serial number of new device
          example: SN-123456789
        louvered_sides:
          type: boolean
          nullable: true
          description: Whether device has louvered sides
        contractor_fax:
          type: string
          nullable: true
          description: Contractor's fax number
        coil_make_model:
          type: string
          nullable: true
          description: Make and model of coil (for HVAC)
        added_by:
          type: string
          enum:
            - organization
            - customer
          description: >-
            Indicates who added the device record: 'organization' when created
            via incentives lookup, or 'customer' when added directly by the
            customer or partner.
          example: organization
        device:
          type: object
          nullable: true
          description: >-
            Device information from the devices catalog (only present when
            device_id is set)
          properties:
            model_name:
              type: string
              nullable: true
              description: Marketing or product line name for the device
              example: Smart Splitter
            manufacturer:
              type: string
              nullable: true
              description: Company or brand that manufactures the device
              example: ChargePoint
            manufacture_year:
              type: integer
              nullable: true
              description: Year the specific unit was manufactured
              example: 2024
            device_category_name:
              type: string
              nullable: true
              description: >-
                Name of the device category (e.g., EV Charger, HVAC, Water
                Heater)
              example: EV Charger
        created_at:
          type: string
          format: date-time
          description: Timestamp when record was created
          example: '2025-01-10T12:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: Timestamp when record was last updated
          example: '2025-01-15T14:30:00Z'
  responses:
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >
        API key for authentication. Include your Leap API key in the `x-api-key`
        header: `x-api-key: leap_live_...`
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Clerk JWT token for portal authentication

````