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.

Gridshare Customer API is one of 3 APIs that Lunar Energy publishes on the APIs.io network, described by a machine-readable OpenAPI specification.

This API exposes 3 machine-runnable capabilities that can be deployed as REST, MCP, or Agent Skill surfaces via Naftiko.

Tagged areas include Customer, Home Energy Management, Devices, Telemetry, and Topology. The published artifact set on APIs.io includes API documentation, an OpenAPI specification, and 3 Naftiko capability specs.

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: [email protected]
  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 }