Skip to main content

REST API

API Reference

REST API

EnerOS REST API follows RESTful conventions, using standard HTTP method semantics, with all response bodies in JSON. Endpoints are provided by the eneros-api crate, validated by eneros-gateway and forwarded to the kernel. Each endpoint goes through the complete authentication, rate limiting, and audit chain.

Common Conventions

HTTP Method Semantics

MethodSemanticsIdempotentSafeRequest BodyTypical Use
GETRead resourceYesYesNoQuery list/details
POSTCreate resource / Trigger actionNoNoYesCreate network, trigger load flow
PUTFull update resourceYesNoYesReplace resource
PATCHPartial update resourceNoNoYesModify fields
DELETEDelete resourceYesNoNoDelete resource

Endpoint List

MethodPathDescriptionAuthRate Limit
GET/api/v1/healthHealth checkNo60/min
POST/api/v1/auth/tokenGet TokenNo30/min
POST/api/v1/auth/refreshRefresh TokenYes30/min
GET/api/v1/networksNetwork listYes600/min
POST/api/v1/networksCreate networkYes60/min
GET/api/v1/networks/{id}Network detailsYes600/min
PUT/api/v1/networks/{id}Update networkYes60/min
DELETE/api/v1/networks/{id}Delete networkYes30/min
POST/api/v1/networks/{id}/powerflowTrigger load flow calculationYes30/min
POST/api/v1/networks/{id}/validateValidate topologyYes60/min
GET/api/v1/agentsAgent listYes600/min
POST/api/v1/agentsCreate AgentYes60/min
GET/api/v1/agents/{id}Agent detailsYes600/min
PUT/api/v1/agents/{id}Update Agent configurationYes60/min
DELETE/api/v1/agents/{id}Delete AgentYes30/min
POST/api/v1/agents/{id}/commandDispatch Agent commandYes100/min
POST/api/v1/agents/{id}/pausePause AgentYes60/min
POST/api/v1/agents/{id}/resumeResume AgentYes60/min
GET/api/v1/devicesDevice listYes600/min
GET/api/v1/devices/{id}Device detailsYes600/min
PATCH/api/v1/devices/{id}Update device statusYes60/min
GET/api/v1/timeseriesTime-series data queryYes600/min
POST/api/v1/timeseries/batchBatch write time-seriesYes1000/min
GET/api/v1/eventsEvent historyYes600/min
GET/api/v1/alarmsAlarm listYes600/min
PATCH/api/v1/alarms/{id}/ackAcknowledge alarmYes60/min
GET/api/v1/auditAudit logYes600/min
GET/api/v1/tasks/{id}Task status queryYes600/min
DELETE/api/v1/tasks/{id}Cancel taskYes30/min

Pagination, Filtering, Sorting

Pagination Parameters

List endpoints uniformly support the following pagination parameters:

ParameterTypeRequiredDefaultDescription
pageintNo1Page number, starting from 1
page_sizeintNo20Items per page, max 100
cursorstringNoCursor (for cursor pagination, takes precedence over page)

Pagination response:

{
  "data": [/* ... */],
  "meta": {
    "page": 1,
    "page_size": 20,
    "total": 137,
    "total_pages": 7,
    "next_cursor": "eyJpZCI6Im5ldF94eHgifQ=="
  }
}

Filter Parameters

Examples of filter fields supported by each endpoint:

EndpointFilter FieldsExample
/networksstatus, name?status=ready&name=IEEE
/agentsstatus, type?status=running&type=dispatch
/devicestype, online?type=PV&online=true
/alarmsseverity, status, from, to?severity=critical&from=2026-07-06T00:00:00Z
/eventstopic, from, to?topic=alarm.critical&from=...

Sort Parameters

ParameterTypeRequiredDefaultDescription
sortstringNo-created_atPrefix - for descending order
sort multi-fieldstringNoComma-separated, e.g., name,-created_at

Example: ?sort=-created_at&page=2&page_size=50

Endpoint Details

Health Check

GET /api/v1/health checks service availability, no authentication required.

Request Parameters: None

Response Fields:

FieldTypeDescription
statusstringok / degraded / down
versionstringEnerOS version number
uptime_secondsintService uptime
checksobjectSubsystem status

cURL Example:

curl http://localhost:8080/api/v1/health

Response Example:

{
  "data": {
    "status": "ok",
    "version": "0.47.0",
    "uptime_seconds": 86400,
    "checks": {
      "database": "ok",
      "timeseries": "ok",
      "eventbus": "ok",
      "realtime": "ok"
    }
  },
  "request_id": "req_20260706_001",
  "timestamp": "2026-07-06T08:30:00Z"
}

Get Token

POST /api/v1/auth/token exchanges username/password for a Bearer Token.

Request Parameters:

FieldTypeRequiredDefaultDescription
usernamestringYesUsername
passwordstringYesPassword
tenant_idstringNoDefault tenantTenant ID
scopestringNodefaultPermission scope

cURL Example:

curl -X POST http://localhost:8080/api/v1/auth/token \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"admin"}'

Response Example:

{
  "data": {
    "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refresh_token": "rft_20260706_abc123",
    "expires_in": 3600,
    "token_type": "Bearer"
  },
  "request_id": "req_20260706_002",
  "timestamp": "2026-07-06T08:30:00Z"
}

Create Network

POST /api/v1/networks creates a new network model.

Request Parameters:

FieldTypeRequiredDefaultDescription
namestringYesNetwork name, max 64 characters
descriptionstringNo""Description, max 256 characters
base_kvfloatNo110.0Base voltage (kV)
base_mvafloatNo100.0Base capacity (MVA)
busesarrayYesBus list, at least 1
buses[].idintYesBus number
buses[].typestringYesslack / pv / pq
buses[].vfloatNo1.0Voltage per-unit (required for slack/pv)
buses[].thetafloatNo0.0Phase angle (radians, required for slack)
buses[].areaintNo1Area number
branchesarrayNo[]Branch list
branches[].fromintYesFrom bus
branches[].tointYesTo bus
branches[].rfloatYesResistance per-unit
branches[].xfloatYesReactance per-unit
branches[].bfloatNo0.0Charging susceptance per-unit
generatorsarrayNo[]Generator list
loadsarrayNo[]Load list
tagsobjectNo{}Custom tags

cURL Example:

curl -X POST http://localhost:8080/api/v1/networks \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "IEEE-14",
    "base_kv": 110.0,
    "base_mva": 100.0,
    "buses": [
      {"id": 1, "type": "slack", "v": 1.05, "theta": 0.0},
      {"id": 2, "type": "pv", "v": 1.04},
      {"id": 3, "type": "pq"}
    ],
    "branches": [
      {"from": 1, "to": 2, "r": 0.01938, "x": 0.05917, "b": 0.0528}
    ],
    "generators": [
      {"bus": 1, "mw": 50.0, "mvar": 0.0}
    ],
    "loads": [
      {"bus": 3, "mw": 94.2, "mvar": 19.0}
    ],
    "tags": {"owner": "ieee", "scenario": "summer"}
  }'

Rust Example:

use eneros_sdk::{ApiClient, models::NetworkInput};
use serde_json::json;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let client = ApiClient::builder()
        .endpoint("http://localhost:8080")
        .token("<bearer-token>")
        .build()?;

    let input = NetworkInput {
        name: "IEEE-14".to_string(),
        base_kv: Some(110.0),
        base_mva: Some(100.0),
        buses: vec![
            json!({"id": 1, "type": "slack", "v": 1.05, "theta": 0.0}),
            json!({"id": 2, "type": "pv", "v": 1.04}),
            json!({"id": 3, "type": "pq"}),
        ],
        branches: vec![
            json!({"from": 1, "to": 2, "r": 0.01938, "x": 0.05917, "b": 0.0528}),
        ],
        generators: vec![json!({"bus": 1, "mw": 50.0, "mvar": 0.0})],
        loads: vec![json!({"bus": 3, "mw": 94.2, "mvar": 19.0})],
        tags: json!({"owner": "ieee", "scenario": "summer"}),
        ..Default::default()
    };

    let network = client.networks().create(&input).await?;
    println!("created network: {}", network.id);
    Ok(())
}

Python Example:

from eneros_sdk import ApiClient

client = ApiClient(
    endpoint="http://localhost:8080",
    token="<bearer-token>",
)

network = client.networks.create({
    "name": "IEEE-14",
    "base_kv": 110.0,
    "base_mva": 100.0,
    "buses": [
        {"id": 1, "type": "slack", "v": 1.05, "theta": 0.0},
        {"id": 2, "type": "pv", "v": 1.04},
        {"id": 3, "type": "pq"},
    ],
    "branches": [
        {"from": 1, "to": 2, "r": 0.01938, "x": 0.05917, "b": 0.0528},
    ],
    "generators": [{"bus": 1, "mw": 50.0, "mvar": 0.0}],
    "loads": [{"bus": 3, "mw": 94.2, "mvar": 19.0}],
    "tags": {"owner": "ieee", "scenario": "summer"},
})
print(f"created network: {network.id}")

Response Example:

{
  "data": {
    "id": "net_8f3a2b",
    "name": "IEEE-14",
    "description": "",
    "base_kv": 110.0,
    "base_mva": 100.0,
    "bus_count": 14,
    "branch_count": 20,
    "generator_count": 5,
    "load_count": 11,
    "status": "ready",
    "tags": {"owner": "ieee", "scenario": "summer"},
    "created_at": "2026-07-06T08:30:00Z",
    "updated_at": "2026-07-06T08:30:00Z"
  },
  "request_id": "req_20260706_003",
  "timestamp": "2026-07-06T08:30:00Z"
}

Get Network List

GET /api/v1/networks returns the list of networks under the current tenant.

Request Parameters (Query):

FieldTypeRequiredDefaultDescription
pageintNo1Page number
page_sizeintNo20Items per page
statusstringNoFilter status
namestringNoFuzzy match name
tagstringNoFilter by tag, format key:value
sortstringNo-created_atSort field

Response Example:

{
  "data": [
    {
      "id": "net_8f3a2b",
      "name": "IEEE-14",
      "bus_count": 14,
      "status": "ready",
      "created_at": "2026-07-06T08:30:00Z"
    },
    {
      "id": "net_9c4d1e",
      "name": "IEEE-30",
      "bus_count": 30,
      "status": "ready",
      "created_at": "2026-07-05T10:00:00Z"
    }
  ],
  "meta": {
    "page": 1,
    "page_size": 20,
    "total": 2,
    "total_pages": 1
  },
  "request_id": "req_20260706_004",
  "timestamp": "2026-07-06T08:30:00Z"
}

Trigger Load Flow Calculation

POST /api/v1/networks/{id}/powerflow triggers a load flow calculation task.

Path Parameters:

FieldTypeRequiredDescription
idstringYesNetwork ID

Request Parameters:

FieldTypeRequiredDefaultDescription
methodstringNonewton_raphsonAlgorithm: newton_raphson / fast_decoupled / dc
tolerancefloatNo1e-8Convergence tolerance
max_iterationsintNo50Maximum iterations
asyncboolNofalseWhether to execute asynchronously
flat_startboolNofalseWhether flat start
timeout_msintNo30000Timeout (milliseconds)

cURL Example:

curl -X POST http://localhost:8080/api/v1/networks/net_8f3a2b/powerflow \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"method": "newton_raphson", "tolerance": 1e-8, "max_iterations": 50}'

Response Example (synchronous mode):

{
  "data": {
    "task_id": "pf_20260706_001",
    "network_id": "net_8f3a2b",
    "status": "converged",
    "method": "newton_raphson",
    "iterations": 4,
    "duration_ms": 12,
    "tolerance": 1e-8,
    "buses": [
      {"id": 1, "v": 1.05, "theta": 0.0, "p_gen": 50.0, "q_gen": 12.5},
      {"id": 2, "v": 1.04, "theta": -0.039, "p_gen": 0.0, "q_gen": 0.0}
    ],
    "branches": [
      {"from": 1, "to": 2, "p_from": 50.0, "q_from": 12.5, "loading": 0.45}
    ],
    "losses": {"p_mw": 1.23, "q_mvar": 5.67},
    "started_at": "2026-07-06T08:30:00Z",
    "completed_at": "2026-07-06T08:30:00.012Z"
  },
  "request_id": "req_20260706_005",
  "timestamp": "2026-07-06T08:30:00Z"
}

Response Example (asynchronous mode):

{
  "data": {
    "task_id": "pf_20260706_002",
    "network_id": "net_8f3a2b",
    "status": "queued",
    "poll_url": "/api/v1/tasks/pf_20260706_002"
  },
  "request_id": "req_20260706_006",
  "timestamp": "2026-07-06T08:30:00Z"
}

Create Agent

POST /api/v1/agents creates and registers a new Agent.

Request Parameters:

FieldTypeRequiredDefaultDescription
namestringYesAgent name
typestringYesdispatch / self_healing / trading / maintenance / planning
network_idstringNoAssociated network ID
configobjectNo{}Agent configuration
toolsarrayNo[]List of allowed tools
reasoning_modelstringNodefaultReasoning model
max_actions_per_minuteintNo60Maximum action frequency
auto_startboolNofalseAuto-start after creation

cURL Example:

curl -X POST http://localhost:8080/api/v1/agents \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "DispatchAgent-01",
    "type": "dispatch",
    "network_id": "net_8f3a2b",
    "config": {"objective": "economic", "horizon_minutes": 15},
    "tools": ["powerflow", "topology", "forecast"],
    "reasoning_model": "default",
    "max_actions_per_minute": 30,
    "auto_start": true
  }'

JavaScript Example:

import { ApiClient } from '@eneros/sdk';

const client = new ApiClient({
  endpoint: 'http://localhost:8080',
  token: '<bearer-token>',
});

const agent = await client.agents.create({
  name: 'DispatchAgent-01',
  type: 'dispatch',
  networkId: 'net_8f3a2b',
  config: { objective: 'economic', horizonMinutes: 15 },
  tools: ['powerflow', 'topology', 'forecast'],
  reasoningModel: 'default',
  maxActionsPerMinute: 30,
  autoStart: true,
});
console.log('created agent:', agent.id);

Response Example:

{
  "data": {
    "id": "agent_dispatch_01",
    "name": "DispatchAgent-01",
    "type": "dispatch",
    "network_id": "net_8f3a2b",
    "status": "running",
    "config": {"objective": "economic", "horizon_minutes": 15},
    "tools": ["powerflow", "topology", "forecast"],
    "reasoning_model": "default",
    "max_actions_per_minute": 30,
    "created_at": "2026-07-06T08:30:00Z",
    "started_at": "2026-07-06T08:30:01Z"
  },
  "request_id": "req_20260706_007",
  "timestamp": "2026-07-06T08:30:00Z"
}

Dispatch Agent Command

POST /api/v1/agents/{id}/command dispatches a command to an Agent.

Request Parameters:

FieldTypeRequiredDefaultDescription
commandstringYesCommand name
paramsobjectNo{}Command parameters
prioritystringNonormallow / normal / high / emergency
timeout_msintNo5000Command timeout
await_resultboolNotrueWhether to wait for result

cURL Example:

curl -X POST http://localhost:8080/api/v1/agents/agent_dispatch_01/command \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "command": "set_generation",
    "params": {"bus": 2, "mw": 50.0},
    "priority": "normal",
    "timeout_ms": 5000,
    "await_result": true
  }'

Response Example:

{
  "data": {
    "command_id": "cmd_20260706_001",
    "agent_id": "agent_dispatch_01",
    "command": "set_generation",
    "status": "success",
    "result": {
      "bus": 2,
      "mw_set": 50.0,
      "constraint_checked": true,
      "audit_id": "aud_20260706_001"
    },
    "duration_ms": 12,
    "executed_at": "2026-07-06T08:30:00Z"
  },
  "request_id": "req_20260706_008",
  "timestamp": "2026-07-06T08:30:00Z"
}

Time-Series Data Query

GET /api/v1/timeseries queries time-series data, supporting aggregation and downsampling.

Request Parameters (Query):

FieldTypeRequiredDefaultDescription
metricstringYesMetric name, e.g., branch_loading
tagsstringNoTag filter, format key:value,key2:value2
fromdatetimeYesStart time (RFC 3339)
todatetimeYesEnd time
aggregationstringNononenone / avg / sum / max / min / count
intervalstringNoDownsampling interval, e.g., 1m / 5m / 1h
fillstringNonullMissing value fill strategy: null / zero / linear
limitintNo10000Maximum return points

cURL Example:

curl -G http://localhost:8080/api/v1/timeseries \
  -H "Authorization: Bearer <token>" \
  --data-urlencode "metric=branch_loading" \
  --data-urlencode "tags=network:net_8f3a2b,branch:1-2" \
  --data-urlencode "from=2026-07-06T00:00:00Z" \
  --data-urlencode "to=2026-07-06T08:00:00Z" \
  --data-urlencode "aggregation=avg" \
  --data-urlencode "interval=5m"

Python Example:

from eneros_sdk import ApiClient
from datetime import datetime, timezone, timedelta

client = ApiClient(endpoint="http://localhost:8080", token="<bearer-token>")

result = client.timeseries.query(
    metric="branch_loading",
    tags={"network": "net_8f3a2b", "branch": "1-2"},
    from_=datetime.now(timezone.utc) - timedelta(hours=8),
    to=datetime.now(timezone.utc),
    aggregation="avg",
    interval="5m",
)
for point in result.points:
    print(f"{point.timestamp} -> {point.value}")

Response Example:

{
  "data": {
    "metric": "branch_loading",
    "tags": {"network": "net_8f3a2b", "branch": "1-2"},
    "aggregation": "avg",
    "interval": "5m",
    "points": [
      {"timestamp": "2026-07-06T00:00:00Z", "value": 0.42},
      {"timestamp": "2026-07-06T00:05:00Z", "value": 0.45},
      {"timestamp": "2026-07-06T00:10:00Z", "value": 0.48}
    ],
    "count": 96
  },
  "request_id": "req_20260706_009",
  "timestamp": "2026-07-06T08:30:00Z"
}

Batch Write Time-Series

POST /api/v1/timeseries/batch batch writes time-series data points, up to 10000 points per call.

Request Parameters:

FieldTypeRequiredDefaultDescription
pointsarrayYesData point array
points[].metricstringYesMetric name
points[].timestampdatetimeNoCurrent timeTimestamp
points[].valuefloatYesValue
points[].tagsobjectNo{}Tags

cURL Example:

curl -X POST http://localhost:8080/api/v1/timeseries/batch \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "points": [
      {"metric": "branch_loading", "timestamp": "2026-07-06T08:30:00Z", "value": 0.42, "tags": {"network": "net_8f3a2b", "branch": "1-2"}},
      {"metric": "bus_voltage", "timestamp": "2026-07-06T08:30:00Z", "value": 1.05, "tags": {"network": "net_8f3a2b", "bus": "1"}}
    ]
  }'

Response Example:

{
  "data": {
    "accepted": 2,
    "rejected": 0,
    "errors": []
  },
  "request_id": "req_20260706_010",
  "timestamp": "2026-07-06T08:30:00Z"
}

Alarm List and Acknowledgment

GET /api/v1/alarms gets alarm list, PATCH /api/v1/alarms/{id}/ack acknowledges alarm.

List Request Parameters:

FieldTypeRequiredDefaultDescription
severitystringNoinfo / warn / error / critical
statusstringNoactive / acknowledged / cleared
network_idstringNoLimit to network
fromdatetimeNoStart time
todatetimeNoEnd time

Acknowledge Alarm Request Parameters:

FieldTypeRequiredDefaultDescription
acknowledged_bystringYesAcknowledger
notestringNo""Note

Response Example (list):

{
  "data": [
    {
      "id": "alm_001",
      "severity": "critical",
      "status": "active",
      "type": "BRANCH_OVERLOAD",
      "message": "Branch 1-2 overload: 105% of limit",
      "network_id": "net_8f3a2b",
      "source": {"type": "constraint_engine", "id": "ce_01"},
      "details": {"branch_id": "1-2", "loading": 1.05, "limit": 1.0},
      "raised_at": "2026-07-06T08:30:00Z",
      "acknowledged_at": null,
      "cleared_at": null
    }
  ],
  "meta": {"page": 1, "page_size": 20, "total": 1, "total_pages": 1},
  "request_id": "req_20260706_011",
  "timestamp": "2026-07-06T08:30:00Z"
}

Audit Log Query

GET /api/v1/audit queries operation audit logs, requires audit permission.

Request Parameters:

FieldTypeRequiredDefaultDescription
actorstringNoOperator
actionstringNoOperation type
resource_typestringNoResource type
resource_idstringNoResource ID
fromdatetimeNoStart time
todatetimeNoEnd time
pageintNo1Page number
page_sizeintNo50Items per page

Response Example:

{
  "data": [
    {
      "id": "aud_20260706_001",
      "timestamp": "2026-07-06T08:30:00Z",
      "actor": {"type": "user", "id": "admin", "tenant": "default"},
      "action": "agent.command",
      "resource": {"type": "agent", "id": "agent_dispatch_01"},
      "request_id": "req_20260706_008",
      "ip": "192.168.1.10",
      "user_agent": "curl/7.88.1",
      "result": "success",
      "details": {"command": "set_generation", "params": {"bus": 2, "mw": 50.0}}
    }
  ],
  "meta": {"page": 1, "page_size": 50, "total": 1, "total_pages": 1},
  "request_id": "req_20260706_012",
  "timestamp": "2026-07-06T08:30:00Z"
}

Error Codes

Common Error Codes

HTTP StatusError CodeMeaning
400INVALID_REQUESTInvalid request parameters
400INVALID_FIELDInvalid field value
401UNAUTHORIZEDNot authenticated or token invalid
401TOKEN_EXPIREDToken has expired
403FORBIDDENInsufficient permissions
404NOT_FOUNDResource does not exist
405METHOD_NOT_ALLOWEDMethod not supported
409CONFLICTResource state conflict
409CONSTRAINT_VIOLATIONSecurity constraint violation
413PAYLOAD_TOO_LARGERequest body too large
422VALIDATION_FAILEDBusiness validation failed
429RATE_LIMITEDRate limit triggered
500INTERNAL_ERRORKernel error
503SERVICE_UNAVAILABLEService unavailable
504GATEWAY_TIMEOUTGateway timeout

Business Error Codes

HTTP StatusError CodeMeaning
409POWERFLOW_DIVERGEDLoad flow did not converge
409NETWORK_LOCKEDNetwork is locked
422TOPOLOGY_INVALIDTopology invalid
422PARAM_OUT_OF_RANGEParameter out of bounds
422AGENT_BUSYAgent busy
422BUS_NOT_FOUNDBus does not exist
422BRANCH_NOT_FOUNDBranch does not exist
422ISLANDED_BUSBus is islanded
422VOLTAGE_OUT_OF_LIMITVoltage out of limits

Unified error response body format:

{
  "error": {
    "code": "CONSTRAINT_VIOLATION",
    "message": "Branch 1-2 overload: 105% of limit",
    "details": {"branch_id": "1-2", "loading": 1.05, "limit": 1.0},
    "trace_id": "trace_abc123",
    "doc_url": "https://docs.openeneros.com/api-reference/rest#error-codes"
  },
  "request_id": "req_20260706_008"
}

Field Enum Value Descriptions

NetworkStatus

ValueDescription
draftDraft, editable
readyReady, can participate in calculations
lockedLocked (computation in progress), not modifiable
archivedArchived, read-only

AgentType

ValueDescription
dispatchDispatch Agent
self_healingSelf-healing Agent
tradingTrading Agent
maintenanceMaintenance Agent
planningPlanning Agent

AgentStatus

ValueDescription
idleIdle
runningRunning
pausedPaused
errorError
stoppedStopped

PowerFlowMethod

ValueDescription
newton_raphsonNewton-Raphson method (default)
fast_decoupledFast decoupled method (PQ decomposition)
dcDC load flow

BusType

ValueDescription
slackSlack bus
pvPV bus (voltage controllable)
pqPQ bus (load bus)

DeviceType

ValueDescription
PVPhotovoltaic
WINDWind power
BESSEnergy storage
EVElectric vehicle
LOADLoad
TRANSFORMERTransformer
BREAKERCircuit breaker

Batch Operations

In addition to time-series writes, the REST API also supports the following batch endpoints:

MethodPathDescriptionSingle Batch Limit
POST/api/v1/networks/batchBatch create networks20
POST/api/v1/agents/batchBatch create Agents50
POST/api/v1/devices/batchBatch create devices200
DELETE/api/v1/networks/batchBatch delete networks50

Batch requests uniformly return independent results for each entry:

{
  "data": {
    "succeeded": [{"index": 0, "id": "net_a"}, {"index": 1, "id": "net_b"}],
    "failed": [{"index": 2, "error": {"code": "VALIDATION_FAILED", "message": "invalid bus"}}]
  }
}