/v1/sessions Create Session
Create a charging session and optionally run anomaly analysis. Meter values are optional — session can be created empty and populated later via PUT or PATCH. If >= 3 meter values are provided, the CSAR-2 pipeline runs automatically. Sessions longer than 6 hours are truncated to the last 6h window for inference.
Headers
Authorization * Request Body
session_id * charging_station_id * connector_id evse_id meter_values timestamp * value * measurand unit phase location metadata Response 200
session_id * status * is_anomaly anomaly_score anomaly_confidence is_incident is_recurring anomalies * category * score * confidence * bucket_range * start_unit * end_unit * time_range start_timestamp end_timestamp analyzed_at {
"session_id": "sess-abc-001",
"charging_station_id": "CP-NL-AMS-0042",
"connector_id": "1",
"meter_values": [
{
"timestamp": "2026-02-27T10:00:00Z",
"measurand": "Energy.Active.Import.Register",
"unit": "kWh",
"value": 0.0
},
{
"timestamp": "2026-02-27T10:15:00Z",
"measurand": "Energy.Active.Import.Register",
"unit": "kWh",
"value": 5.5
},
{
"timestamp": "2026-02-27T10:30:00Z",
"measurand": "Energy.Active.Import.Register",
"unit": "kWh",
"value": 11.1
}
]
} {
"session_id": "sess-abc-001",
"status": "active",
"is_anomaly": true,
"anomaly_score": 0.85,
"anomaly_confidence": 0.92,
"is_incident": false,
"is_recurring": true,
"anomalies": [
{
"category": "KWH_DECREASE",
"score": 0.87,
"confidence": 0.92,
"bucket_range": { "start_unit": 4, "end_unit": 7 },
"time_range": {
"start_timestamp": "2026-02-27T11:00:00Z",
"end_timestamp": "2026-02-27T11:45:00Z"
}
}
],
"analyzed_at": "2026-02-27T10:31:02Z"
} /v1/sessions/{session_id} Replace Session
Replace all meter values for a session. Deletes existing meter values and sets new ones. Requires at least 1 reading. If >= 3 meter values after replacement, CSAR-2 inference runs automatically. Sessions longer than 6 hours are truncated to the last 6h window for inference.
Headers
Authorization * Path Parameters
session_id * Request Body
meter_values * timestamp * value * measurand unit metadata Response 200
session_id * status * is_anomaly anomaly_score anomaly_confidence anomalies * analyzed_at {
"meter_values": [
{
"timestamp": "2026-02-27T10:00:00Z",
"measurand": "Energy.Active.Import.Register",
"unit": "kWh",
"value": 0.0
},
{
"timestamp": "2026-02-27T10:15:00Z",
"measurand": "Energy.Active.Import.Register",
"unit": "kWh",
"value": 5.5
},
{
"timestamp": "2026-02-27T10:30:00Z",
"measurand": "Energy.Active.Import.Register",
"unit": "kWh",
"value": 11.1
}
]
} {
"session_id": "sess-abc-001",
"status": "active",
"is_anomaly": false,
"anomaly_score": 0.12,
"anomaly_confidence": 0.95,
"anomalies": [],
"analyzed_at": "2026-02-27T10:31:02Z"
} /v1/sessions/{session_id} Update Session
Append meter values to an existing session (OCPI-like incremental push). Empty meter_values list = no changes, returns current state. If >= 3 accumulated meter values after append, CSAR-2 inference runs automatically. Sessions longer than 6 hours are truncated to the last 6h window for inference.
Headers
Authorization * Path Parameters
session_id * Request Body
meter_values * timestamp * value * measurand unit metadata Response 200
session_id * status * is_anomaly anomaly_score anomaly_confidence anomalies * analyzed_at {
"meter_values": [
{
"timestamp": "2026-02-27T10:45:00Z",
"measurand": "Energy.Active.Import.Register",
"unit": "kWh",
"value": 16.5
}
]
} {
"session_id": "sess-abc-001",
"status": "active",
"is_anomaly": true,
"anomaly_score": 0.85,
"anomaly_confidence": 0.92,
"anomalies": [
{
"category": "KWH_DECREASE",
"score": 0.87,
"confidence": 0.92,
"bucket_range": { "start_unit": 4, "end_unit": 7 }
}
],
"analyzed_at": "2026-02-27T10:46:05Z"
} /v1/sessions List Sessions
List analyzed sessions with pagination and filters. Reads from pre-joined materialized view for session + latest inference + anomalies.
Headers
Authorization * Query Parameters
page page_size charging_station_id evse_id is_anomaly min_score min_confidence date_from date_to Response 200
items * session_id * external_session_id * charging_station_id * is_anomaly * anomaly_score * anomaly_count * status * created_at * last_analyzed_at * total * page * page_size * {
"items": [
{
"session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"external_session_id": "sess-abc-001",
"charging_station_id": "CP-NL-AMS-0042",
"is_anomaly": true,
"anomaly_score": 0.85,
"anomaly_count": 2,
"status": "active",
"created_at": "2026-02-27T10:00:00Z",
"last_analyzed_at": "2026-02-27T10:31:02Z"
}
],
"total": 1250,
"page": 1,
"page_size": 20
} /v1/sessions/{session_id} Get Session Detail
Get full session details including meter values, analysis result, and anomaly categories.
Headers
Authorization * Path Parameters
session_id * Response 200
session_id * status * is_anomaly anomaly_score anomaly_confidence is_incident is_recurring anomalies * analyzed_at meter_values * timestamp * value * measurand unit created_at * {
"session_id": "sess-abc-001",
"status": "active",
"is_anomaly": true,
"anomaly_score": 0.85,
"anomaly_confidence": 0.92,
"is_incident": false,
"is_recurring": true,
"anomalies": [
{
"category": "KWH_DECREASE",
"score": 0.87,
"confidence": 0.92,
"bucket_range": { "start_unit": 4, "end_unit": 7 },
"time_range": {
"start_timestamp": "2026-02-27T11:00:00Z",
"end_timestamp": "2026-02-27T11:45:00Z"
}
}
],
"analyzed_at": "2026-02-27T10:31:02Z",
"meter_values": [
{ "timestamp": "2026-02-27T10:00:00Z", "measurand": "Energy.Active.Import.Register", "unit": "kWh", "value": 0.0 },
{ "timestamp": "2026-02-27T10:15:00Z", "measurand": "Energy.Active.Import.Register", "unit": "kWh", "value": 5.5 },
{ "timestamp": "2026-02-27T10:30:00Z", "measurand": "Energy.Active.Import.Register", "unit": "kWh", "value": 11.1 }
],
"created_at": "2026-02-27T09:58:00Z"
} /v1/sessions/{session_id}/explain Explain Session
Get an LLM-generated explanation of session anomalies.
Headers
Authorization * Path Parameters
session_id * Request Body
Response 200
session_id * explanation * {} {
"session_id": "sess-abc-001",
"explanation": "The session shows a kWh decrease between meter values 4–7, indicating the energy register dropped unexpectedly. This typically signals a meter reset or communication error between the charger and the backend."
} /v1/sessions/{session_id}/ask Ask Session
Ask a natural language question about a specific session.
Headers
Authorization * Path Parameters
session_id * Request Body
question * Response 200
session_id * answer * {
"question": "Why did the SoC drop unexpectedly?"
} {
"session_id": "sess-abc-001",
"answer": "The SoC dropped from 80% to 65% because the charger reported an unexpected discharge event during meter values 3–5, likely caused by a bi-directional charging cycle (V2G)."
} /v1/sessions/batch Submit Batch
Submit multiple sessions for asynchronous batch analysis. Returns batch_id for polling status.
Headers
Authorization * Request Body
sessions * session_id * charging_point_id * meter_values * Response 200
batch_id * total_sessions * status * {
"sessions": [
{
"session_id": "sess-001",
"charging_point_id": "CP-001",
"meter_values": [
{ "timestamp": "2026-02-27T10:00:00Z", "unit": "kwh", "value": 0.0 },
{ "timestamp": "2026-02-27T10:15:00Z", "unit": "kwh", "value": 5.5 },
{ "timestamp": "2026-02-27T10:30:00Z", "unit": "kwh", "value": 11.1 }
]
},
{
"session_id": "sess-002",
"charging_point_id": "CP-002",
"meter_values": [
{ "timestamp": "2026-02-27T11:00:00Z", "unit": "kwh", "value": 0.0 },
{ "timestamp": "2026-02-27T11:15:00Z", "unit": "kwh", "value": 7.2 },
{ "timestamp": "2026-02-27T11:30:00Z", "unit": "kwh", "value": 14.8 }
]
}
]
} {
"batch_id": "batch-a1b2c3d4",
"total_sessions": 2,
"status": "pending"
} /v1/sessions/batch/{batch_id} Get Batch Status
Get batch processing status and results. Poll until status is "completed" or "failed".
Headers
Authorization * Path Parameters
batch_id * Response 200
batch_id * status * total_sessions * processed_sessions * failed_sessions * results * created_at * completed_at * {
"batch_id": "batch-a1b2c3d4",
"status": "completed",
"total_sessions": 2,
"processed_sessions": 2,
"failed_sessions": 0,
"results": [
{
"session_id": "sess-001",
"status": "active",
"is_anomaly": false,
"anomaly_score": 0.12,
"sequence_length": 9,
"anomalies": []
}
],
"created_at": "2026-02-27T10:00:00Z",
"completed_at": "2026-02-27T10:02:15Z"
} /v1/stations List Stations
List tenant charging stations with aggregated anomaly statistics. Reads from pre-aggregated materialized view.
Headers
Authorization * Query Parameters
page page_size Response 200
items * charging_station_id * external_station_id * total_sessions * anomalous_sessions * max_anomaly_score * last_anomaly_at * total * page * page_size * {
"items": [
{
"charging_station_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"external_station_id": "ST-NL-AMS-01",
"total_sessions": 142,
"anomalous_sessions": 7,
"max_anomaly_score": 0.91,
"last_anomaly_at": "2026-02-27T09:45:00Z"
}
],
"total": 12,
"page": 1,
"page_size": 20
} /v1/stations/{charging_station_id} Get Station Detail
Get station details: connectors, energy data, anomaly counts. Joins station aggregates with per-session anomaly details.
Headers
Authorization * Path Parameters
charging_station_id * Response 200
charging_station_id * external_station_id * connectors * connector_id * total_sessions * anomalous_sessions * total_sessions * anomalous_sessions * metadata * {
"charging_station_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"external_station_id": "ST-NL-AMS-01",
"connectors": [
{ "connector_id": "1", "total_sessions": 80, "anomalous_sessions": 3 },
{ "connector_id": "2", "total_sessions": 62, "anomalous_sessions": 4 }
],
"total_sessions": 142,
"anomalous_sessions": 7,
"metadata": {
"address": "Keizersgracht 100, Amsterdam",
"operator": "FastNed"
}
} /v1/stations/{charging_station_id}/connectors Get Station Connectors
Get station connectors with per-category anomaly breakdown.
Headers
Authorization * Path Parameters
charging_station_id * Response 200
charging_station_id * connectors * connector_id * total_sessions * anomalous_sessions * anomaly_categories * {
"charging_station_id": "ST-NL-AMS-01",
"connectors": [
{
"connector_id": "1",
"total_sessions": 80,
"anomalous_sessions": 3,
"anomaly_categories": {
"KWH_DECREASE": 2,
"ENERGY_PIT": 1
}
},
{
"connector_id": "2",
"total_sessions": 62,
"anomalous_sessions": 4,
"anomaly_categories": {
"ZERO_SESSION": 3,
"CHARGING_EXPECTED": 1
}
}
]
} /v1/stations/{charging_station_id}/inference Station Inference
Get latest SHADE inference result for a station. Replaces the former POST /stations/analyze endpoint.
Headers
Authorization * Path Parameters
charging_station_id * Response 200
charging_station_id * is_anomaly * anomaly_score * detection_details * analyzed_at * {
"charging_station_id": "ST-NL-AMS-01",
"is_anomaly": true,
"anomaly_score": 0.72,
"detection_details": {
"anomaly_type": "energy_drop",
"affected_period": "2026-02-27",
"expected_energy_kwh": 1200.0,
"actual_energy_kwh": 980.2
},
"analyzed_at": "2026-02-27T12:00:00Z"
} /v1/stations/{charging_station_id}/anomalies Station Anomalies
Get station-level anomaly history from SHADE detection results.
Headers
Authorization * Path Parameters
charging_station_id * Query Parameters
page page_size Response 200
items * inference_id * is_anomaly * anomaly_score * detection_details * analyzed_at * total * page * page_size * {
"items": [
{
"inference_id": "inf-xyz-001",
"is_anomaly": true,
"anomaly_score": 0.72,
"detection_details": {
"anomaly_type": "energy_drop",
"affected_period": "2026-02-27"
},
"analyzed_at": "2026-02-27T12:00:00Z"
}
],
"total": 5,
"page": 1,
"page_size": 20
} /v1/models List Models
List available base models and tenant fine-tuned models.
Headers
Authorization * Response 200
models * id * name * type * version * is_base * base_model metrics * status * created_at * {
"models": [
{
"id": "model-csar2-base",
"name": "CSAR-2 Base",
"type": "csar_2",
"version": "1.0.0",
"is_base": true,
"base_model": null,
"metrics": { "f1_score": 0.94, "precision": 0.92 },
"status": "active",
"created_at": "2026-01-15T00:00:00Z"
}
]
} /v1/models/{model_id} Get Model Detail
Get model details: version, metrics, training date, status.
Headers
Authorization * Path Parameters
model_id * Response 200
id * name * type * version * is_base * base_model metrics * status * created_at * s3_path description {
"id": "model-csar2-base",
"name": "CSAR-2 Base",
"type": "csar_2",
"version": "1.0.0",
"is_base": true,
"base_model": null,
"metrics": {
"f1_score": 0.94,
"precision": 0.92,
"recall": 0.96
},
"status": "active",
"created_at": "2026-01-15T00:00:00Z",
"s3_path": "models/csar2/v1.0.0/model.pt",
"description": "Base CSAR-2 autoencoder model"
} /v1/models/fine-tune Start Fine-Tune
Trigger model fine-tuning on your session data. Specify base model and training data source.
Headers
Authorization * Request Body
base_model_id * name * data_source * type * session_filter training_config Response 200
job_id * status * base_model_id * created_at * {
"base_model_id": "model-csar2-base",
"name": "CSAR-2 Amsterdam Fine-Tuned",
"data_source": {
"type": "sessions",
"session_filter": {
"station_id": "ST-NL-AMS-01",
"date_from": "2026-01-01"
}
},
"training_config": {
"epochs": 50,
"learning_rate": 0.001
}
} {
"job_id": "ft-job-xyz-001",
"status": "queued",
"base_model_id": "model-csar2-base",
"created_at": "2026-02-27T14:00:00Z"
} /v1/models/fine-tune/{job_id} Fine-Tune Status
Get fine-tuning job progress and result model ID.
Headers
Authorization * Path Parameters
job_id * Response 200
job_id * status * base_model_id * result_model_id * config * created_at * started_at * completed_at * error_message * {
"job_id": "ft-job-xyz-001",
"status": "completed",
"base_model_id": "model-csar2-base",
"result_model_id": "model-csar2-ams-ft-001",
"config": { "epochs": 50, "learning_rate": 0.001 },
"created_at": "2026-02-27T14:00:00Z",
"started_at": "2026-02-27T14:01:00Z",
"completed_at": "2026-02-27T14:45:00Z",
"error_message": null
} /v1/statistics Get Statistics
Get tenant-wide summary: sessions, anomalies, stations, anomaly rate. Reads from pre-aggregated materialized views.
Headers
Authorization * Response 200
total_sessions * anomalous_sessions * total_stations * stations_with_anomalies * anomaly_rate * {
"total_sessions": 1250,
"anomalous_sessions": 47,
"total_stations": 12,
"stations_with_anomalies": 4,
"anomaly_rate": 0.0376
} /v1/webhooks (configured via Dashboard) Webhook Configuration
The platform can send webhook notifications for station health events detected by SHADE (Station Health Anomaly Detection Engine). Webhooks are configured through the management dashboard — no API endpoint is needed. When SHADE detects a station-level anomaly, a POST request is sent to your configured URL with the event payload below.
Headers
Authorization * Response 200
event * charging_station_id * is_anomaly * anomaly_score * detection_details * analyzed_at * webhook_id * {
"event": "station.anomaly_detected",
"charging_station_id": "CP-NL-AMS-0042",
"is_anomaly": true,
"anomaly_score": 0.72,
"detection_details": {
"anomaly_type": "energy_drop",
"affected_period": "2026-02-27",
"expected_energy_kwh": 1200.0,
"actual_energy_kwh": 980.2
},
"analyzed_at": "2026-02-27T12:00:00Z",
"webhook_id": "wh-evt-a1b2c3d4"
}