HTTP Webhook
Universal. Any language or stack.
Fast onboarding and SaaS integrations.
- security:
- TLS 1.3 + HMAC
- throughput:
- 10k req/s
ZenovaConnect is for teams already building energy software: monitoring SaaS, asset operations platforms, VPPs, EMS, storage aggregators, C&I energy-carbon platforms, or in-house enterprise systems. You do not need to write one parser per vendor — we normalize disparate device sources into stable entities, metrics, alarms, and time-series, then deliver them through the channel you choose.
Get an API key → add vendor credentials → register webhook → receive data → expand to more vendors.
Submit the contact form; our sales engineering team issues a sandbox account (username + password) within one business day. The Free tier includes a permanent 10-device quota.
Once you have an account, exchange username/password for an access_token. All subsequent API calls carry this token via the Authorization header:
# After receiving credentials, exchange username/password for an access_token
curl -X POST 'https://api.zenovaconnect.com/sol-emqx/login' \
-d 'username=YOUR_USERNAME' \
-d 'password=YOUR_PASSWORD'
# Response:
# {
# "success": true,
# "code": 200,
# "result": { "access_token": "eyJ..." }
# }After getting the token, hand us the vendor account credentials (issued by the vendor developer portal) and call the sync endpoint to pull every plant + device under that account:
import requests
TOKEN = "eyJ..."
headers = {"Authorization": f"Bearer {TOKEN}"}
# Sync all plants and devices under a vendor account
resp = requests.get(
"https://api.zenovaconnect.com/apiDevice/syncApiPlantAndDevice",
headers=headers,
params={"dataAccessUserId": "your-account-id"}
)
plants = resp.json()["result"]
print(f"Synced {len(plants)} plants")Implement a webhook endpoint and we'll push device data in the unified BaseData schema. Verify the HMAC signature first, then handle the payload:
// Your webhook endpoint receives device data pushed by ZenovaConnect
app.post('/webhooks/zenova', (req, res) => {
const payload = req.body;
// Verify the signature (HMAC-SHA256)
const sig = req.headers['x-zenova-signature'];
if (!verifyHmac(payload, sig, process.env.ZENOVA_SECRET)) {
return res.status(401).end();
}
// payload follows the unified BaseData schema
const { DataSources, InverterSN, EDay, PowerACOutputActive } = payload;
console.log(`[${DataSources}] ${InverterSN} today ${EDay} kWh`);
res.status(200).end();
});Adding more vendor accounts is just repeating Step 3. ZenovaConnect natively supports 15 vendors today (Huawei, Sungrow, Goodwe, Solis, Growatt, Sineng, Aiswei, Sofar, Hopewind, APsystems, Maitian, Sigenergy, Hoymiles, Yibang, Hikvision). Bulk device management, plant grouping, and online/offline events are all available via the OpenAPI.
No matter which vendor it came from, the fields, units, and precision are the same.
15+ vendors use 15+ different field names, units, and timezone conventions. We normalize them into a single 50+ field BaseData schema and push that to you — write your parser once, and adding new vendors never touches your code.
Below are two real-shape samples from different vendors (BaseData schema). 50+ fields cover inverter, collector, and component-level operating data — three-phase voltage/current (UAC1/IAC1/UAC2/IAC2/UAC3/IAC3) + multi-MPPT inputs (UPV1/IPV1...) + alarm arrays. Notice the DataSources field tells you which vendor it came from, InverterSN carries the real device SN, and every other field is identical across vendors:
From Goodwe (SEMS Portal)
{
"deviceType": "inverter",
"CollectorSN": "C1234567890",
"InverterSN": "INV20250526001",
"DataSources": "goodwe",
"Timezone": "GMT+8",
"Datetime": 1748246400,
"currentDateTime": "2026-05-26 12:00:00",
"State": "1",
"StateDesc": "正常发电",
"EDay": 35.6,
"ETotal": 128500.8,
"PowerACOutputActive": 8.75,
"Temperature": 42.5,
"FrqAC": 50.01,
"UAC1": 231.5,
"IAC1": 12.6,
"UPV1": 620.5,
"IPV1": 9.8,
"AlertArray": [],
"turnonTime": "2026-05-26 06:30:00"
}From Huawei (FusionSolar)
{
"deviceType": "inverter",
"CollectorSN": "C9876543210",
"InverterSN": "INV20250526002",
"DataSources": "huawei",
"Timezone": "GMT+8",
"Datetime": 1748246400,
"currentDateTime": "2026-05-26 12:00:00",
"State": "1",
"StateDesc": "正常发电",
"EDay": 41.2,
"ETotal": 215800.4,
"PowerACOutputActive": 9.12,
"Temperature": 38.9,
"FrqAC": 49.99,
"UAC1": 230.8,
"IAC1": 13.2,
"UPV1": 615.7,
"IPV1": 10.1,
"AlertArray": [],
"turnonTime": "2026-05-26 06:28:00"
}The 50+ BaseData fields, timestamp timezone, and units (kWh / kW / V / A / Hz / °C) are uniform across every vendor. Your parsing logic gets written once — and the DataSources field always tells you which vendor a payload came from, which makes debugging trivial.
| Field | Type | Description |
|---|---|---|
| deviceType | string | Device type (always "inverter" for inverters) |
| DataSources | string | Vendor source (huawei / sungrow / goodwe... matches the /protocols matrix) |
| InverterSN | string | Vendor-native inverter serial number |
| Datetime | long | Sample timestamp (Unix seconds); currentDateTime gives the human-readable form |
| State / StateDesc | string | Inverter status code + localized description, e.g. "1" / "正常发电" |
| EDay | double | Energy generated today (kWh) |
| ETotal | double | Lifetime energy generated (kWh) |
| PowerACOutputActive | double | Current AC active power output (kW) |
| UAC1 / UAC2 / UAC3 | double | Three-phase AC voltage (V) — industrial-grade three-phase data |
| IAC1 / IAC2 / IAC3 | double | Three-phase AC current (A) |
| UPV1 – UPV32 | double | Per-string DC voltage (V), up to 32 strings |
| IPV1 – IPV32 | double | Per-string DC current (A), up to 32 strings |
| Temperature | double | Inverter case temperature (°C) |
| AlertArray / WarnArray / StatusArray | array | Alarm / warning / status arrays, passed through as-is |
Pick the channel that fits your stack. HTTP, Kafka, or MQTT.
Universal. Any language or stack.
Fast onboarding and SaaS integrations.
High-throughput consumption from SaaS clusters.
Multi-consumer pipelines, data platforms, and event-driven architectures.
Standard IoT protocol, low-bandwidth friendly.
Real-time subscription, edge, and IoT scenarios.
Every payload your system receives is signed, replayable, and carries an idempotency key. Three things to wire up at integration time.
Webhook requests carry an X-ZenovaConnect-Signature header — HMAC-SHA256 over the raw body using your shared secret. Kafka uses SASL_SSL + TLS, MQTT uses TLS + JWT/ACL — no extra signing needed there. Your receiver must verify the signature before processing and respond with 401 on mismatch.
Webhook: non-2xx responses or timeouts (default 10s) trigger exponential backoff for up to 8 attempts spanning ~24 hours. Kafka uses native acks + consumer offsets, and we retry until ack. MQTT uses QoS 1; the broker handles redelivery. Your handler must be idempotent.
Each payload carries an idempotency_key derived from vendor + device_id + ts, globally unique. Retries keep the same key — dedupe on it in your DB or Redis and the same device-timestamp event is processed exactly once.
Request technical onboarding — our team will be in touch within one business day with a sandbox API key and credential setup guide.
Talk to engineering →