Gridshare Customer API

The Gridshare Customer API is the homeowner-delegated surface for partners that need to read or control devices on behalf of a specific Lunar Energy customer. It implements OAuth 2.0 Authorization Code flow against the lunar-customer Amazon Cognito user pool with four scopes — `lunar/device.read`, `lunar/device.write`, `lunar/plan.read`, `lunar/plan.write`. v2 endpoints expose lightweight Site listing, Site Topology (a sensor tree usable to drive telemetry queries), Device listing and retrieval, Telemetry (per-sensor time-bucketed readings with energy_Wh_increment / energy_Wh_decrement when include=energy), Operation Mode (Simple / Schedule / Smart), Overlay Plans for short-term device control, and partial device updates. Production servers developer-api.customer.mygridshare.com.

OpenAPI Specification

gridshare-customer-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Gridshare Customer API
  description: |
    The Gridshare Customer API is the homeowner-delegated surface of
    Lunar Energy's Gridshare DERMS platform. It allows partners — apps,
    installers, retailers — to read or control devices on behalf of a
    specific Lunar Energy customer once that customer has granted
    consent via OAuth 2.0 Authorization Code flow against the
    lunar-customer Amazon Cognito user pool.

    Four scopes are available: `lunar/device.read`, `lunar/device.write`,
    `lunar/plan.read`, `lunar/plan.write`.
  version: v1.0
  contact:
    name: Lunar Energy
    url: https://www.gridshare.com
    email: developers@gridshare.com
  x-logo:
    url: https://www.lunarenergy.com/favicon.ico
servers:
  - url: https://developer-api.customer.mygridshare.com
    description: Production server
  - url: https://developer-api.customer.dev0.mygridshare.com
    description: Development server
security:
  - bearerAuth: []
tags:
  - name: Sites
    description: List sites and read site topology
  - name: Devices
    description: List, get, and partially update customer devices
  - name: Telemetry
    description: Time-bucketed per-sensor telemetry readings
  - name: Operation Mode
    description: Read or change the Gridshare operation mode of a device
  - name: Plans
    description: Read or set overlay plans for short-term device dispatch
paths:
  /api/v2/sites:
    get:
      operationId: listSites
      summary: List Sites
      description: |
        List the siteIds the authenticated customer has access to. v2 is
        the lightweight external endpoint — pair it with
        `GET /api/v2/sites/{siteId}/topology` and `GET /api/v2/devices` to
        drill into a site's structure or devices.
      tags: [Sites]
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SiteList'
        '401': { $ref: '#/components/responses/Unauthorized' }
        '403': { $ref: '#/components/responses/Forbidden' }
  /api/v2/sites/{siteId}/topology:
    parameters:
      - $ref: '#/components/parameters/SiteId'
    get:
      operationId: getSiteTopology
      summary: Get Site Topology
      description: |
        Return the electrical topology of a site the authenticated customer
        has access to. Nodes with `"kind": "sensor"` expose an `id` that may
        be passed to `GET /api/v2/devices/{synthId}/telemetry` and a
        `channels` array listing available streams. See the Topology key
        concepts page for worked examples.
      tags: [Sites]
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Topology'
        '401': { $ref: '#/components/responses/Unauthorized' }
        '403': { $ref: '#/components/responses/Forbidden' }
  /api/v2/devices:
    get:
      operationId: listDevices
      summary: List Devices
      description: List all devices the authenticated customer has access to.
      tags: [Devices]
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceList'
        '400': { $ref: '#/components/responses/Malformed' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '403': { $ref: '#/components/responses/Forbidden' }
        '422': { $ref: '#/components/responses/Unprocessable' }
  /api/v2/devices/{synthId}:
    parameters:
      - $ref: '#/components/parameters/SynthId'
    get:
      operationId: getDevice
      summary: Get Device
      description: Get a device by ID along with its static properties.
      tags: [Devices]
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Device'
    patch:
      operationId: patchDevice
      summary: Partially Update Device
      description: Update a device.
      tags: [Devices]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Device'
      responses:
        '200':
          description: OK
  /api/v2/devices/{synthId}/telemetry:
    parameters:
      - $ref: '#/components/parameters/SynthId'
    get:
      operationId: getDeviceTelemetry
      summary: Get Device Telemetry
      description: |
        Time-bucketed telemetry for a single device sensor stream.
        `synthId` must be a **sensor ID** from the site topology — any node
        with `"kind": "sensor"`. On most installations telemetry streams
        are keyed by derived sensor IDs such as
        `<deviceId>__GRID_METER_DERIVED`, `<deviceId>__bb_agg`, and
        `<deviceId>__PV_DERIVED`.

        `energy_Wh_increment` and `energy_Wh_decrement` are populated only
        when `include=energy` (or `include=default,energy`):
          - `energy_Wh_increment` — lifetime cumulative energy flowing **into** the device (positive)
          - `energy_Wh_decrement` — lifetime cumulative energy flowing **out of** the device (negative)
      tags: [Telemetry]
      parameters:
        - in: query
          name: include
          schema: { type: string }
        - in: query
          name: start
          schema: { type: string, format: date-time }
        - in: query
          name: end
          schema: { type: string, format: date-time }
        - in: query
          name: bucket
          schema: { type: string }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Telemetry'
  /api/v2/devices/{synthId}/operationmode:
    parameters:
      - $ref: '#/components/parameters/SynthId'
    get:
      operationId: getDeviceOperationMode
      summary: Get Device Operation Mode
      description: |
        Get the current Gridshare operation mode of a device. Valid modes:
        - `Simple` — follow the simplest plan possible for the device kind
        - `Schedule` — follow a periodical plan
        - `Smart` — AI-optimized smart plan
        - `Unknown` — operation mode cannot be determined
      tags: [Operation Mode]
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OperationMode'
    put:
      operationId: setDeviceOperationMode
      summary: Change Device Operation Mode
      description: Set the Gridshare operation mode of a device.
      tags: [Operation Mode]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OperationMode'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OperationMode'
  /api/v2/devices/{synthId}/plans/overlay:
    parameters:
      - $ref: '#/components/parameters/SynthId'
    get:
      operationId: getDeviceOverlayPlan
      summary: Get Device Overlay Plan
      description: Get the current overlay plan for the device.
      tags: [Plans]
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OverlayPlan'
    put:
      operationId: setDeviceOverlayPlan
      summary: Set Device Overlay Plan
      description: |
        Set an overlay plan for the device. To delete an overlay plan,
        send an empty `commands` array in the request body.
      tags: [Plans]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OverlayPlan'
      responses:
        '200':
          description: OK
components:
  securitySchemes:
    bearerAuth:
      type: oauth2
      description: |
        OAuth 2.0 Authorization Code flow against the lunar-customer
        Amazon Cognito user pool.
      flows:
        authorizationCode:
          authorizationUrl: https://lunar-customer-prod-us-west-1.auth.us-west-1.amazoncognito.com/oauth2/authorize
          tokenUrl: https://lunar-customer-prod-us-west-1.auth.us-west-1.amazoncognito.com/oauth2/token
          refreshUrl: https://lunar-customer-prod-us-west-1.auth.us-west-1.amazoncognito.com/oauth2/token
          scopes:
            lunar/device.read: Read device metadata and telemetry (excluding plans)
            lunar/device.write: Modify devices including operation mode
            lunar/plan.read: Read existing device plans
            lunar/plan.write: Send plans to a device
  parameters:
    SiteId:
      in: path
      name: siteId
      required: true
      schema: { type: string }
    SynthId:
      in: path
      name: synthId
      required: true
      schema: { type: string }
      description: A device ID or a sensor ID from the site topology.
  responses:
    Unauthorized:
      description: 401 Unauthorized
      content:
        application/json:
          schema: { $ref: '#/components/schemas/UnauthorizedResponse' }
    Forbidden:
      description: 403 Forbidden
      content:
        application/json:
          schema: { $ref: '#/components/schemas/ForbiddenResponse' }
    Malformed:
      description: 400 Malformed Input
      content:
        application/json:
          schema: { $ref: '#/components/schemas/MalformedInputResponse' }
    Unprocessable:
      description: 422 Unprocessable
      content:
        application/json:
          schema: { $ref: '#/components/schemas/UnprocessableResponse' }
  schemas:
    SiteListItem:
      type: object
      required: [siteId]
      properties:
        siteId: { type: string }
    SiteList:
      type: object
      required: [entries]
      properties:
        entries:
          type: array
          items: { $ref: '#/components/schemas/SiteListItem' }
    TopologyNode:
      type: object
      properties:
        id: { type: string }
        kind:
          type: string
          enum: [site, device, sensor]
        channels:
          type: array
          items: { type: string }
        children:
          type: array
          items: { $ref: '#/components/schemas/TopologyNode' }
    Topology:
      type: object
      properties:
        root: { $ref: '#/components/schemas/TopologyNode' }
    Device:
      type: object
      required: [synthId]
      properties:
        synthId: { type: string }
        kind:
          type: string
          enum: [inverter, battery_pack, PV, EV, meter, load_control_relay]
        siteId: { type: string }
        manufacturer: { type: string }
        model: { type: string }
        serialNumber: { type: string }
    DeviceListItem:
      type: object
      required: [synthId]
      properties:
        synthId: { type: string }
    DeviceList:
      type: object
      required: [entries]
      properties:
        entries:
          type: array
          items: { $ref: '#/components/schemas/DeviceListItem' }
    Telemetry:
      type: object
      properties:
        entries:
          type: array
          items:
            type: object
            properties:
              timestamp: { type: string, format: date-time }
              power_W: { type: number }
              voltage_V: { type: number }
              current_A: { type: number }
              stateOfCharge_pct: { type: number }
              energy_Wh_increment: { type: number }
              energy_Wh_decrement: { type: number }
    OperationMode:
      type: object
      required: [mode]
      properties:
        mode:
          type: string
          enum: [Simple, Schedule, Smart, Unknown]
    OverlayPlanCommand:
      type: object
      properties:
        start: { type: string, format: date-time }
        end: { type: string, format: date-time }
        action:
          type: string
          enum: [charge, discharge, hold, follow]
        powerLimit_W: { type: number }
    OverlayPlan:
      type: object
      required: [commands]
      properties:
        commands:
          type: array
          items: { $ref: '#/components/schemas/OverlayPlanCommand' }
    ForbiddenResponse:
      type: object
      properties:
        message: { type: string }
        code: { type: string }
    MalformedInputResponse:
      type: object
      properties:
        message: { type: string }
        code: { type: string }
    UnauthorizedResponse:
      type: object
      properties:
        message: { type: string }
        code: { type: string }
    UnprocessableResponse:
      type: object
      properties:
        message: { type: string }
        code: { type: string }