openapi: 3.1.0
info:
title: Gridshare Partner API
description: |
The Gridshare Partner API is Lunar Energy's operator-facing surface for
utilities, retailers, and DER aggregators managing residential
distributed energy resources at fleet scale. Covers Sites, Devices,
Telemetry, Operation Mode, Overlay Plans, Periodical Tariffs, Dynamic
Tariffs, Flex Groups, Flex Events, Flex Dispatches, Prognoses with
Diff Requests and Diff Orders, Counterfactuals, and on-site Visits.
Authentication is OAuth 2.0 client-credentials against an Amazon Cognito
user pool. Tokens expire after 1 hour and are sent as
`Authorization: Bearer <access_token>` on every request.
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.partner.us.mygridshare.com
description: Production server (US)
- url: https://developer-api.partner.mygridshare.com
description: Production server (Rest of World)
- url: https://developer-api.partner.dev0.us.mygridshare.com
description: Development server (US)
- url: https://developer-api.partner.dev0.mygridshare.com
description: Development server (Rest of World)
security:
- bearerAuth: []
tags:
- name: Sites
description: List, get, create, and replace sites in the partner fleet
- name: Devices
description: List, get, create, replace, and patch DER devices
- name: Telemetry
description: Retrieve time-bucketed device telemetry and counterfactuals
- 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
- name: Periodical Tariffs
description: Manage periodical (recurring) tariffs
- name: Dynamic Tariffs
description: Manage dynamic time-series tariffs with 7-day pagination
- name: Flex Groups
description: Define and manage groups of DERs participating in flex programs
- name: Flex Events
description: Schedule and update flex events for a flex group
- name: Flex Dispatches
description: Opt participants out of an active flex dispatch
- name: Prognoses
description: Forecasted aggregate power profiles for flex groups
- name: Diff Requests
description: Request and commit differential adjustments to a prognosis
- name: Visits
description: Record on-site visits for installation or service
paths:
/api/v1/sites:
get:
operationId: listSites
summary: List Sites
description: List all sites the authenticated partner can access.
tags: [Sites]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/SiteList'
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
post:
operationId: createSite
summary: Create Site
description: Create a new site in the partner fleet.
tags: [Sites]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Site'
responses:
'201':
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/Site'
/api/v1/sites/{siteId}:
parameters:
- $ref: '#/components/parameters/SiteId'
get:
operationId: getSite
summary: Get Site
description: Get a site by ID.
tags: [Sites]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Site'
put:
operationId: replaceSite
summary: Replace Site
description: Override a site with new attributes.
tags: [Sites]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Site'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Site'
/api/v1/sites/{siteId}/topology:
parameters:
- $ref: '#/components/parameters/SiteId'
get:
operationId: getSiteTopology
summary: Get Site Topology
description: |
Return the electrical topology tree of a site. Nodes with
`"kind": "sensor"` expose an `id` that may be passed to the
device telemetry endpoint and a `channels` array of available
data streams.
tags: [Sites]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Topology'
/api/v1/devices:
get:
operationId: listDevices
summary: List Devices
description: List all devices in the partner fleet.
tags: [Devices]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/DeviceList'
post:
operationId: createDevice
summary: Create Device
description: Create a new device.
tags: [Devices]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Device'
responses:
'201':
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/Device'
/api/v1/devices/{synthId}:
parameters:
- $ref: '#/components/parameters/SynthId'
get:
operationId: getDevice
summary: Get Device
description: Get a device by ID with its static properties.
tags: [Devices]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Device'
put:
operationId: replaceOrCreateDevice
summary: Replace Or Create Device
description: Override an existing device with new properties or create one if it does not yet exist.
tags: [Devices]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Device'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Device'
/api/v1/devices/{synthId}/telemetry:
parameters:
- $ref: '#/components/parameters/SynthId'
get:
operationId: getDeviceTelemetry
summary: Get Device Telemetry
description: |
Get time-bucketed telemetry for a device or sensor. `synthId` can be
a device ID or a sensor ID from the site topology. Supported device
kinds: `inverter`, `battery_pack`, `PV`, `EV`, `meter`,
`load_control_relay`. Include `energy_Wh_increment` and
`energy_Wh_decrement` by passing `include=default,energy`.
tags: [Telemetry]
parameters:
- in: query
name: include
schema: { type: string }
description: Comma-separated set of telemetry fields. `energy` is opt-in.
- 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 }
description: Time-bucket size (e.g. `PT1H`).
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Telemetry'
/api/v1/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 for 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/v1/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
/api/v1/periodicaltariffs:
get:
operationId: listPeriodicalTariffs
summary: List Periodical Tariffs
description: List all periodical tariffs.
tags: [Periodical Tariffs]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/PeriodicalTariffList'
post:
operationId: createPeriodicalTariff
summary: Create Periodical Tariff
tags: [Periodical Tariffs]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PeriodicalTariff'
responses:
'201':
description: Created
/api/v1/periodicaltariffs/{tariffId}:
parameters:
- $ref: '#/components/parameters/TariffId'
get:
operationId: getPeriodicalTariff
summary: Get Periodical Tariff
tags: [Periodical Tariffs]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/PeriodicalTariff'
patch:
operationId: updatePeriodicalTariff
summary: Update Periodical Tariff
description: |
Update properties of an existing periodical tariff. Append or
rewrite pricing periods. Tariffs may have an open-ended latest
period; PATCH-ing in a later period closes it automatically.
tags: [Periodical Tariffs]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PeriodicalTariff'
responses:
'200':
description: OK
/api/v1/dynamictariffs:
get:
operationId: listDynamicTariffs
summary: List Dynamic Tariffs
description: List all dynamic tariffs for the calling partner account.
tags: [Dynamic Tariffs]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/DynamicTariffList'
post:
operationId: createDynamicTariff
summary: Create Dynamic Tariff
description: Create a dynamic tariff with an optional initial set of timeseries values.
tags: [Dynamic Tariffs]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DynamicTariff'
responses:
'201':
description: Created
/api/v1/dynamictariffs/{tariffId}:
parameters:
- $ref: '#/components/parameters/TariffId'
get:
operationId: getDynamicTariff
summary: Get Dynamic Tariff
description: |
Return metadata for a dynamic tariff together with a single page of
timeseries values covering a 7-day window. Paginate via `nextToken`.
tags: [Dynamic Tariffs]
parameters:
- in: query
name: interval
schema: { type: string }
- in: query
name: nextToken
schema: { type: string }
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/DynamicTariff'
patch:
operationId: updateDynamicTariff
summary: Update Dynamic Tariff
description: Append or override periods of a dynamic tariff. Existing values are not deleted.
tags: [Dynamic Tariffs]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DynamicTariff'
responses:
'200':
description: OK
/api/v1/flexgroups:
get:
operationId: listFlexGroups
summary: List Flex Groups
tags: [Flex Groups]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/FlexGroupList'
post:
operationId: createFlexGroup
summary: Create Flex Group
tags: [Flex Groups]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/FlexGroup'
responses:
'201':
description: Created
/api/v1/flexgroups/{flexGroupId}:
parameters:
- $ref: '#/components/parameters/FlexGroupId'
get:
operationId: getFlexGroup
summary: Get Flex Group
tags: [Flex Groups]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/FlexGroup'
/api/v1/flexgroups/{flexGroupId}/participants:
parameters:
- $ref: '#/components/parameters/FlexGroupId'
get:
operationId: listFlexGroupParticipants
summary: List Flex Group Participants
tags: [Flex Groups]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/ParticipantList'
post:
operationId: addFlexGroupParticipant
summary: Add Flex Group Participant
tags: [Flex Groups]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Participant'
responses:
'201':
description: Created
/api/v1/flexgroups/{flexGroupId}/participants/{participantId}:
parameters:
- $ref: '#/components/parameters/FlexGroupId'
- $ref: '#/components/parameters/ParticipantId'
get:
operationId: getFlexGroupParticipant
summary: Get Flex Group Participant
tags: [Flex Groups]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Participant'
delete:
operationId: deleteFlexGroupParticipant
summary: Delete Flex Group Participant
tags: [Flex Groups]
responses:
'204':
description: Deleted
/api/v1/flexgroups/{flexGroupId}/participants/bulk:
parameters:
- $ref: '#/components/parameters/FlexGroupId'
post:
operationId: createBulkParticipantsAction
summary: Create Bulk Participants Action
description: |
Overwrite the participants of a flex group by sending a full
replacement list. This action is irreversible.
tags: [Flex Groups]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ParticipantList'
responses:
'202':
description: Accepted
/api/v1/flexgroups/{flexGroupId}/participants/bulk/{bulkId}:
parameters:
- $ref: '#/components/parameters/FlexGroupId'
- in: path
name: bulkId
required: true
schema: { type: string }
get:
operationId: getBulkParticipantsAction
summary: Get Bulk Participants Action
description: Retrieve the status of a bulk participants update.
tags: [Flex Groups]
responses:
'200':
description: OK
/api/v1/flexevent:
get:
operationId: listFlexEvents
summary: List Flex Events
description: List all flex events within a time range, optionally filtered by group.
tags: [Flex Events]
parameters:
- in: query
name: start
schema: { type: string, format: date-time }
- in: query
name: end
schema: { type: string, format: date-time }
- in: query
name: flexGroupId
schema: { type: string }
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/FlexEventList'
post:
operationId: createFlexEvent
summary: Create Flex Event
description: |
Create a flex event for a defined flex group. Supports flat-dispatch
events that target a flat power profile across a specified window.
tags: [Flex Events]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/FlexEvent'
responses:
'201':
description: Created
/api/v1/flexevents/{flexEventId}:
parameters:
- in: path
name: flexEventId
required: true
schema: { type: string }
patch:
operationId: updateFlexEvent
summary: Update Flex Event
description: Update or cancel an existing flex event.
tags: [Flex Events]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/FlexEvent'
responses:
'200':
description: OK
/api/v1/flexdispatches/{flexDispatchId}/optout:
parameters:
- in: path
name: flexDispatchId
required: true
schema: { type: string }
post:
operationId: optOutFlexDispatch
summary: Opt Out Of Flex Dispatch
description: |
Opt a participant out of a flex dispatch. Participants may be
identified by site ID or participant ID. Idempotent — repeat opt-outs
return the original opt-out details.
tags: [Flex Dispatches]
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
siteId: { type: string }
participantId: { type: string }
reason: { type: string }
responses:
'200':
description: OK
/api/v1/flexgroups/{flexGroupId}/prognoses:
parameters:
- $ref: '#/components/parameters/FlexGroupId'
get:
operationId: listPrognoses
summary: List Prognoses
description: |
List prognoses for a specific flex group. A new prognosis is generated
when the group forecast changes due to prediction updates or
explicit flex actions.
tags: [Prognoses]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/PrognosisList'
/api/v1/prognoses/{prognosisId}/prognosisdiffrequests:
parameters:
- in: path
name: prognosisId
required: true
schema: { type: string }
post:
operationId: createPrognosisDiffRequest
summary: Create Prognosis Diff Request
description: |
Request a modification to a prognosis profile. Allows charging or
discharging to the network in a coordinated manner by submitting a
differential profile over the original prognosis. Asynchronous —
poll the Diff Request endpoint for status.
tags: [Diff Requests]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PrognosisDiffRequest'
responses:
'202':
description: Accepted
/api/v1/prognosisdiffrequests/{prognosisDiffRequestId}:
parameters:
- in: path
name: prognosisDiffRequestId
required: true
schema: { type: string }
get:
operationId: getPrognosisDiffRequest
summary: Get Prognosis Diff Request
description: Poll status and feasible offer for a prognosis diff request.
tags: [Diff Requests]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/PrognosisDiffRequest'
/api/v1/prognosisdiffrequests/{prognosisDiffRequestId}/prognosisdifforders:
parameters:
- in: path
name: prognosisDiffRequestId
required: true
schema: { type: string }
post:
operationId: createPrognosisDiffOrder
summary: Create Prognosis Diff Order
description: |
Confirm and commit to the offer associated with a prognosis diff
request. Commands are dispatched to the underlying devices.
tags: [Diff Requests]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PrognosisDiffOrder'
responses:
'201':
description: Created
/api/v1/prognosisdifforders/{prognosisDiffOrderId}:
parameters:
- in: path
name: prognosisDiffOrderId
required: true
schema: { type: string }
get:
operationId: getPrognosisDiffOrder
summary: Get Prognosis Diff Order
description: Retrieve a committed flex offer order including price and power profile.
tags: [Diff Requests]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/PrognosisDiffOrder'
/api/v1/counterfactuals/{counterfactualName}/devices/{deviceId}/telemetry:
parameters:
- in: path
name: counterfactualName
required: true
schema: { type: string }
- in: path
name: deviceId
required: true
schema: { type: string }
get:
operationId: getCounterfactualTelemetry
summary: Get Counterfactual Telemetry
description: |
Counterfactual telemetry — what the device would have done if it had
not been smartly controlled. Availability depends on the
counterfactuals enabled for your partner account.
tags: [Telemetry]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Telemetry'
/api/v1/visits:
get:
operationId: listVisits
summary: List Visits
tags: [Visits]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/VisitList'
post:
operationId: createVisit
summary: Create Visit
tags: [Visits]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Visit'
responses:
'201':
description: Created
/api/v1/visits/{visitId}:
parameters:
- in: path
name: visitId
required: true
schema: { type: string }
get:
operationId: getVisit
summary: Get Visit
tags: [Visits]
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Visit'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
OAuth 2.0 client-credentials access token obtained from the
Gridshare partner Cognito authentication endpoint.
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.
TariffId:
in: path
name: tariffId
required: true
schema: { type: string }
FlexGroupId:
in: path
name: flexGroupId
required: true
schema: { type: string }
ParticipantId:
in: path
name: participantId
required: true
schema: { type: string }
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' }
schemas:
Site:
type: object
required: [siteId]
properties:
siteId: { type: string }
name: { type: string }
timezone: { type: string }
address:
type: object
properties:
country: { type: string }
region: { type: string }
city: { type: string }
postalCode: { type: string }
line1: { type: string }
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 }
deviceId: { type: string }
kind:
type: string
enum: [inverter, battery_pack, PV, EV, meter, load_control_relay]
type: { type: string }
siteId: { type: string }
manufacturer: { type: string }
model: { type: string }
serialNumber: { type: string }
properties:
type: object
additionalProperties: true
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' }
TariffExceptionPeriod:
type: object
properties:
start: { type: string, format: date }
end: { type: string, format: date }
rate: { type: number }
PricingPeriod:
type: object
properties:
start: { type: string, format: date }
end: { type: string, format: date }
rates:
type: array
items:
type: object
properties:
dayOfWeek: { type: string }
from: { type: string }
to: { type: string }
price: { type: number }
exceptions:
type: array
items: { $ref: '#/components/schemas/TariffExceptionPeriod' }
PeriodicalTariff:
type: object
required: [name, companyName]
properties:
tariffId: { type: string }
name: { type: string }
companyName: { type: string }
currency: { type: string }
pricingPeriods:
type: array
items: { $ref: '#/components/schemas/PricingPeriod' }
PeriodicalTariffList:
type: object
properties:
entries:
type: array
items: { $ref: '#/components/schemas/PeriodicalTariff' }
DynamicTariffValue:
type: object
properties:
timestamp: { type: string, format: date-time }
price: { type: number }
DynamicTariff:
type: object
properties:
tariffId: { type: string }
name: { type: string }
currency: { type: string }
values:
type: array
items: { $ref: '#/components/schemas/DynamicTariffValue' }
nextToken: { type: string }
DynamicTariffList:
type: object
properties:
entries:
type: array
items: { $ref: '#/components/schemas/DynamicTariff' }
Participant:
type: object
properties:
participantId: { type: string }
siteId: { type: string }
deviceIds:
type: array
items: { type: string }
ParticipantList:
type: object
properties:
entries:
type: array
items: { $ref: '#/components/schemas/Participant' }
FlexGroup:
type: object
properties:
flexGroupId: { type: string }
name: { type: string }
description: { type: string }
settlementPoint: { type: string }
FlexGroupList:
type: object
properties:
entries:
type: array
items: { $ref: '#/components/schemas/FlexGroup' }
FlexEvent:
type: object
properties:
flexEventId: { type: string }
flexGroupId: { type: string }
type:
type: string
enum: [flatDispatch, ramp]
start: { type: string, format: date-time }
end: { type: string, format: date-time }
powerProfile_W: { type: number }
status:
type: string
enum: [pending, scheduled, active, completed, cancelled]
FlexEventList:
type: object
properties:
# --- truncated at 32 KB (34 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/lunar-energy/refs/heads/main/openapi/gridshare-partner-api-openapi.yml