Partner API
The Partner API provides pre-computed JSON snapshots optimized for embedding and partner integrations. It uses ETag-based conditional GETs and in-memory caching to deliver sub-100ms response times on repeated requests.
Available Snapshots
| Endpoint | Method | Description |
|---|---|---|
| KPI Rollup | get_kpi_rollup() / getKpiRollup() |
Key performance indicators for a site (EarKpis + FinancialKpis; optional battery block) |
| Maintenance Signals | get_maintenance_signals() / getMaintenanceSignals() |
Fault and anomaly signals by severity |
| Maintenance Schedule | get_maintenance_schedule() / getMaintenanceSchedule() |
Preventive maintenance schedule (SEP-062) |
| Forecast Snapshot | get_forecast_snapshot() / getForecastSnapshot() |
Pre-computed 24h solar forecast |
| Generic Snapshot | get_snapshot() / getSnapshot() |
Fetch any snapshot kind by name |
Access via client.partner (Python) or sdk.partner (JavaScript).
Configuration
export ASOBA_API_KEY=<your_api_key>
Endpoint defaults to https://partner.api.asoba.co. Optional override: ASOBA_PARTNER_ENDPOINT.
Python
import json
import time
from asoba import OnaClient
client = OnaClient() # api_key from ASOBA_API_KEY
site_id = "Sibaya"
# ── KPI Rollup (with ETag caching demo) ──
start = time.time()
kpis = client.partner.get_kpi_rollup(site_id=site_id)
duration = (time.time() - start) * 1000
print(f"Fetch 1: {duration:.2f}ms")
print(json.dumps(kpis, indent=2, default=str))
# Second fetch — served from cache via 304 Not Modified
start2 = time.time()
cached_kpis = client.partner.get_kpi_rollup(site_id=site_id)
duration2 = (time.time() - start2) * 1000
print(f"Fetch 2: {duration2:.2f}ms (cache hit)")
Expected output:
Fetch 1: 145.32ms
Fetch 2: 3.12ms (cache hit)
✅ Second fetch was faster (served from cache via 304 Not Modified)
Maintenance Signals
signals = client.partner.get_maintenance_signals(
site_id=site_id,
since='2025-11-01T00:00:00',
severity="high",
)
for signal in signals.get('signals', []):
print(f" [{signal['severity']}] {signal['message']}")
Forecast Snapshot
forecast = client.partner.get_forecast_snapshot(site_id=site_id)
print(f"{forecast['horizon_hours']}h, {len(forecast['intervals'])} intervals")
Maintenance Schedule (SEP-062)
schedule = client.partner.get_maintenance_schedule(site_id=site_id)
summary = schedule.get("summary", {})
print(f"Horizon: {schedule.get('horizon')}")
print(f"Total tasks: {summary.get('total_tasks')}")
print(f"By priority: {summary.get('by_priority')}")
for task in schedule.get("tasks", [])[:3]:
print(f" - {task.get('task_type') or task.get('title')} (priority: {task['priority']})")
JavaScript
const { OnaSDK } = require('@asobacloud/sdk');
const sdk = new OnaSDK(); // apiKey from ASOBA_API_KEY
const siteId = 'Sibaya';
// ── KPI Rollup (with ETag caching demo) ──
const start = Date.now();
const kpis = await sdk.partner.getKpiRollup({ site_id: siteId });
console.log(`Fetch 1: ${Date.now() - start}ms`);
console.log(JSON.stringify(kpis, null, 2));
// Second fetch — served from cache
const start2 = Date.now();
const cachedKpis = await sdk.partner.getKpiRollup({ site_id: siteId });
console.log(`Fetch 2: ${Date.now() - start2}ms (cache hit)`);
// ── Maintenance Signals ──
const signals = await sdk.partner.getMaintenanceSignals({
site_id: siteId,
since: '2025-11-01T00:00:00',
severity: 'high',
});
// ── Forecast Snapshot ──
const forecast = await sdk.partner.getForecastSnapshot({ site_id: siteId });
console.log(`${forecast.horizon_hours}h, ${forecast.intervals.length} intervals`);
// ── Maintenance Schedule (SEP-062) ──
const schedule = await sdk.partner.getMaintenanceSchedule({ site_id: siteId });
console.log('Horizon:', schedule.horizon);
console.log('Total tasks:', schedule.summary.total_tasks);
console.log('By priority:', JSON.stringify(schedule.summary.by_priority));
How ETag Caching Works
- First request: The server returns the JSON payload with an
ETagheader (a content hash). - Subsequent requests: The SDK automatically sends
If-None-Match: <etag>. If the data hasn’t changed, the server responds with304 Not Modifiedand no body — the SDK returns the cached response. - Data changes: When the underlying data updates, the server returns a new
ETagand the full payload.
This means repeated polling for snapshots (e.g., in a dashboard) costs almost nothing after the first fetch.
Full Example
See Also
- Authentication — API key configuration
- Error Handling — Retry logic and rate limiting