This is a development version of the documentation. Content may change without notice.
Voke Documentation
ReferenceREST API

Trading

Trading and ESM integration endpoints

Get trading partner configuration for this org

GET
/api/v1/trading/config

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://loading/api/v1/trading/config"
{
  "createdAt": "2019-08-24T14:15:22Z",
  "esmApiUrl": "string",
  "esmClientId": "string",
  "hasEsmCredentials": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "lastSyncAt": "2019-08-24T14:15:22Z",
  "lastSyncError": "string",
  "organizationId": "7bc05553-4b68-44e8-b7bc-37be63c6d9e9",
  "queuePrefix": "string",
  "status": "ENABLED",
  "updatedAt": "2019-08-24T14:15:22Z"
}
{
  "code": "UNAUTHORIZED",
  "details": {},
  "error": "Unauthorized",
  "message": "Unauthorized",
  "statusCode": 400
}
{
  "code": "FORBIDDEN",
  "details": {},
  "error": "Forbidden",
  "message": "Forbidden",
  "statusCode": 400
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "details": {},
  "error": "Internal Server Error",
  "message": "Internal server error",
  "statusCode": 400
}

Create or update trading partner configuration

POST
/api/v1/trading/config

Request Body

application/json

esmApiUrl?string

ESM partner API base URL (public http/https only; private, loopback, link-local, and metadata addresses are rejected).

esmClientId?string

ESM OAuth client ID

esmClientSecret?string

ESM OAuth client secret (stored encrypted)

queuePrefix?string

Override queue prefix (defaults to org slug). 2-50 lowercase alphanumeric or hyphens.

Match/^[a-z0-9][a-z0-9-]{0,48}[a-z0-9]$/

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://loading/api/v1/trading/config" \  -H "Content-Type: application/json" \  -d '{}'
{
  "createdAt": "2019-08-24T14:15:22Z",
  "esmApiUrl": "string",
  "esmClientId": "string",
  "hasEsmCredentials": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "lastSyncAt": "2019-08-24T14:15:22Z",
  "lastSyncError": "string",
  "organizationId": "7bc05553-4b68-44e8-b7bc-37be63c6d9e9",
  "queuePrefix": "string",
  "status": "ENABLED",
  "updatedAt": "2019-08-24T14:15:22Z"
}
{
  "code": "VALIDATION_ERROR",
  "details": {},
  "error": "Bad Request",
  "message": "Validation error",
  "statusCode": 400
}
{
  "code": "UNAUTHORIZED",
  "details": {},
  "error": "Unauthorized",
  "message": "Unauthorized",
  "statusCode": 400
}
{
  "code": "FORBIDDEN",
  "details": {},
  "error": "Forbidden",
  "message": "Forbidden",
  "statusCode": 400
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "details": {},
  "error": "Internal Server Error",
  "message": "Internal server error",
  "statusCode": 400
}

Disable trading (removes AMQP queues)

POST
/api/v1/trading/config/disable

Response Body

application/json

application/json

application/json

application/json

curl -X POST "https://loading/api/v1/trading/config/disable"
{
  "createdAt": "2019-08-24T14:15:22Z",
  "esmApiUrl": "string",
  "esmClientId": "string",
  "hasEsmCredentials": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "lastSyncAt": "2019-08-24T14:15:22Z",
  "lastSyncError": "string",
  "organizationId": "7bc05553-4b68-44e8-b7bc-37be63c6d9e9",
  "queuePrefix": "string",
  "status": "ENABLED",
  "updatedAt": "2019-08-24T14:15:22Z"
}
{
  "code": "UNAUTHORIZED",
  "details": {},
  "error": "Unauthorized",
  "message": "Unauthorized",
  "statusCode": 400
}
{
  "code": "FORBIDDEN",
  "details": {},
  "error": "Forbidden",
  "message": "Forbidden",
  "statusCode": 400
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "details": {},
  "error": "Internal Server Error",
  "message": "Internal server error",
  "statusCode": 400
}

Enable trading (creates AMQP queues)

POST
/api/v1/trading/config/enable

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://loading/api/v1/trading/config/enable"
{
  "createdAt": "2019-08-24T14:15:22Z",
  "esmApiUrl": "string",
  "esmClientId": "string",
  "hasEsmCredentials": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "lastSyncAt": "2019-08-24T14:15:22Z",
  "lastSyncError": "string",
  "organizationId": "7bc05553-4b68-44e8-b7bc-37be63c6d9e9",
  "queuePrefix": "string",
  "status": "ENABLED",
  "updatedAt": "2019-08-24T14:15:22Z"
}
{
  "code": "TRADING_CONFIG_INCOMPLETE",
  "details": {},
  "error": "Bad Request",
  "message": "Config incomplete or ESM credentials not set",
  "statusCode": 400
}
{
  "code": "UNAUTHORIZED",
  "details": {},
  "error": "Unauthorized",
  "message": "Unauthorized",
  "statusCode": 400
}
{
  "code": "FORBIDDEN",
  "details": {},
  "error": "Forbidden",
  "message": "Forbidden",
  "statusCode": 400
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "details": {},
  "error": "Internal Server Error",
  "message": "Internal server error",
  "statusCode": 400
}

Get AMQP connection details for partner integration

GET
/api/v1/trading/connection-details

Response Body

application/json

application/json

application/json

application/json

curl -X GET "https://loading/api/v1/trading/connection-details"
{
  "authInstructions": "string",
  "authMethod": "string",
  "exchange": "string",
  "host": "string",
  "port": 0,
  "queuePrefix": "string",
  "queues": [
    {
      "description": "string",
      "direction": "inbound",
      "name": "string",
      "routingKey": "string"
    }
  ],
  "vhost": "string"
}
{
  "code": "UNAUTHORIZED",
  "details": {},
  "error": "Unauthorized",
  "message": "Unauthorized",
  "statusCode": 400
}
{
  "code": "FORBIDDEN",
  "details": {},
  "error": "Forbidden",
  "message": "Forbidden",
  "statusCode": 400
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "details": {},
  "error": "Internal Server Error",
  "message": "Internal server error",
  "statusCode": 400
}

Force immediate plant sync from ESM

POST
/api/v1/trading/plants/sync

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://loading/api/v1/trading/plants/sync"
{
  "errors": 0,
  "synced": 0
}
{
  "code": "ESM_NOT_CONFIGURED",
  "details": {},
  "error": "Bad Request",
  "message": "ESM integration is not configured",
  "statusCode": 400
}
{
  "code": "UNAUTHORIZED",
  "details": {},
  "error": "Unauthorized",
  "message": "Unauthorized",
  "statusCode": 400
}
{
  "code": "FORBIDDEN",
  "details": {},
  "error": "Forbidden",
  "message": "Forbidden",
  "statusCode": 400
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "details": {},
  "error": "Internal Server Error",
  "message": "Internal server error",
  "statusCode": 400
}

ESM command relay audit trail

GET
/api/v1/trading/plants/{id}/command-log

Path Parameters

id*string

Query Parameters

commandType?string

Filter by command type

Value in"SITE_SETPOINT" | "DEVICE_COMMAND" | "EMERGENCY" | "MODE_CHANGE"
page?number

Page number (1-indexed)

Default1
Range1 <= value
limit?number

Items per page

Default20
Range1 <= value <= 100

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://loading/api/v1/trading/plants/string/command-log"
{
  "data": [
    {
      "ackStatus": "string",
      "commandType": "string",
      "correlationId": "string",
      "createdAt": "2019-08-24T14:15:22Z",
      "executedAt": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "messageId": "string",
      "organizationId": "7bc05553-4b68-44e8-b7bc-37be63c6d9e9",
      "payload": {},
      "rejectionReason": "string",
      "routingKey": "string",
      "siteId": "string",
      "status": "string"
    }
  ],
  "meta": {
    "limit": 0,
    "page": 0,
    "total": 0,
    "totalPages": 0
  }
}
{
  "code": "BAD_REQUEST",
  "details": {},
  "error": "Bad Request",
  "message": "Validation error or invalid UUID",
  "statusCode": 400
}
{
  "code": "UNAUTHORIZED",
  "details": {},
  "error": "Unauthorized",
  "message": "Unauthorized",
  "statusCode": 400
}
{
  "code": "FORBIDDEN",
  "details": {},
  "error": "Forbidden",
  "message": "Forbidden",
  "statusCode": 400
}
{
  "code": "PLANT_NOT_FOUND",
  "details": {},
  "error": "Not Found",
  "message": "Plant not found",
  "statusCode": 400
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "details": {},
  "error": "Internal Server Error",
  "message": "Internal server error",
  "statusCode": 400
}

Get current plant config from ESM

GET
/api/v1/trading/plants/{id}/config

Path Parameters

id*string

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://loading/api/v1/trading/plants/string/config"
{
  "configEnabled": true,
  "esiState": "string",
  "plantId": "string",
  "timeConfigs": [
    {
      "from": "00:00",
      "pBatMax": 0,
      "pBatMin": 0,
      "socMax": 0,
      "socMin": 0,
      "to": "06:00"
    }
  ],
  "version": 0
}
{
  "code": "BAD_REQUEST",
  "details": {},
  "error": "Bad Request",
  "message": "Invalid UUID or plant is not linked/configured for ESM",
  "statusCode": 400
}
{
  "code": "UNAUTHORIZED",
  "details": {},
  "error": "Unauthorized",
  "message": "Unauthorized",
  "statusCode": 400
}
{
  "code": "FORBIDDEN",
  "details": {},
  "error": "Forbidden",
  "message": "Forbidden",
  "statusCode": 400
}
{
  "code": "PLANT_NOT_FOUND",
  "details": {},
  "error": "Not Found",
  "message": "Plant not found",
  "statusCode": 400
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "details": {},
  "error": "Internal Server Error",
  "message": "Internal server error",
  "statusCode": 400
}

Update plant config via ESM

POST
/api/v1/trading/plants/{id}/config

Path Parameters

id*string

Request Body

application/json

timeConfigs*array<>

Time configuration blocks

Itemsitems <= 96
validateOnly?boolean

If true, validate only without applying

Defaultfalse

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://loading/api/v1/trading/plants/string/config" \  -H "Content-Type: application/json" \  -d '{    "timeConfigs": [      {        "from": "00:00",        "pBatMax": 0,        "pBatMin": 0,        "socMax": 0,        "socMin": 0,        "to": "06:00"      }    ]  }'
{
  "configSnapshot": {},
  "createdAt": "2019-08-24T14:15:22Z",
  "id": 0,
  "isError": true,
  "isTerminal": true,
  "message": "string",
  "plantId": "bb17678d-82fa-43da-92e5-df833ebe5344",
  "requestCode": "string",
  "requestedBy": "d834780c-1e92-44d4-9ca3-e84824c5c502",
  "respondedAt": "2019-08-24T14:15:22Z",
  "resultCode": "string",
  "sentAt": "2019-08-24T14:15:22Z",
  "validateOnly": true
}
{
  "code": "BAD_REQUEST",
  "details": {},
  "error": "Bad Request",
  "message": "Validation error, invalid UUID, or plant is not linked/configured for ESM",
  "statusCode": 400
}
{
  "code": "UNAUTHORIZED",
  "details": {},
  "error": "Unauthorized",
  "message": "Unauthorized",
  "statusCode": 400
}
{
  "code": "FORBIDDEN",
  "details": {},
  "error": "Forbidden",
  "message": "Forbidden",
  "statusCode": 400
}
{
  "code": "PLANT_NOT_FOUND",
  "details": {},
  "error": "Not Found",
  "message": "Plant not found",
  "statusCode": 400
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "details": {},
  "error": "Internal Server Error",
  "message": "Internal server error",
  "statusCode": 400
}

Config change audit trail

GET
/api/v1/trading/plants/{id}/config-log

Path Parameters

id*string

Query Parameters

page?number

Page number (1-indexed)

Default1
Range1 <= value
limit?number

Items per page

Default20
Range1 <= value <= 100

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://loading/api/v1/trading/plants/string/config-log"
{
  "data": [
    {
      "configSnapshot": {},
      "createdAt": "2019-08-24T14:15:22Z",
      "id": 0,
      "isError": true,
      "isTerminal": true,
      "message": "string",
      "plantId": "bb17678d-82fa-43da-92e5-df833ebe5344",
      "requestCode": "string",
      "requestedBy": "d834780c-1e92-44d4-9ca3-e84824c5c502",
      "respondedAt": "2019-08-24T14:15:22Z",
      "resultCode": "string",
      "sentAt": "2019-08-24T14:15:22Z",
      "validateOnly": true
    }
  ],
  "meta": {
    "limit": 0,
    "page": 0,
    "total": 0,
    "totalPages": 0
  }
}
{
  "code": "BAD_REQUEST",
  "details": {},
  "error": "Bad Request",
  "message": "Validation error or invalid UUID",
  "statusCode": 400
}
{
  "code": "UNAUTHORIZED",
  "details": {},
  "error": "Unauthorized",
  "message": "Unauthorized",
  "statusCode": 400
}
{
  "code": "FORBIDDEN",
  "details": {},
  "error": "Forbidden",
  "message": "Forbidden",
  "statusCode": 400
}
{
  "code": "PLANT_NOT_FOUND",
  "details": {},
  "error": "Not Found",
  "message": "Plant not found",
  "statusCode": 400
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "details": {},
  "error": "Internal Server Error",
  "message": "Internal server error",
  "statusCode": 400
}

Validate plant config (dry-run)

POST
/api/v1/trading/plants/{id}/config/validate

Path Parameters

id*string

Request Body

application/json

timeConfigs*array<>

Time configuration blocks

Itemsitems <= 96
validateOnly?boolean

If true, validate only without applying

Defaultfalse

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://loading/api/v1/trading/plants/string/config/validate" \  -H "Content-Type: application/json" \  -d '{    "timeConfigs": [      {        "from": "00:00",        "pBatMax": 0,        "pBatMin": 0,        "socMax": 0,        "socMin": 0,        "to": "06:00"      }    ]  }'
{
  "configSnapshot": {},
  "createdAt": "2019-08-24T14:15:22Z",
  "id": 0,
  "isError": true,
  "isTerminal": true,
  "message": "string",
  "plantId": "bb17678d-82fa-43da-92e5-df833ebe5344",
  "requestCode": "string",
  "requestedBy": "d834780c-1e92-44d4-9ca3-e84824c5c502",
  "respondedAt": "2019-08-24T14:15:22Z",
  "resultCode": "string",
  "sentAt": "2019-08-24T14:15:22Z",
  "validateOnly": true
}
{
  "code": "BAD_REQUEST",
  "details": {},
  "error": "Bad Request",
  "message": "Validation error, invalid UUID, or plant is not linked/configured for ESM",
  "statusCode": 400
}
{
  "code": "UNAUTHORIZED",
  "details": {},
  "error": "Unauthorized",
  "message": "Unauthorized",
  "statusCode": 400
}
{
  "code": "FORBIDDEN",
  "details": {},
  "error": "Forbidden",
  "message": "Forbidden",
  "statusCode": 400
}
{
  "code": "PLANT_NOT_FOUND",
  "details": {},
  "error": "Not Found",
  "message": "Plant not found",
  "statusCode": 400
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "details": {},
  "error": "Internal Server Error",
  "message": "Internal server error",
  "statusCode": 400
}

Query meter data

GET
/api/v1/trading/plants/{id}/meters

Path Parameters

id*string

Query Parameters

from?string

Start time (ISO 8601)

to?string

End time (ISO 8601)

bucketMinutes?number

Aggregation bucket size in minutes

Default5
Range1 <= value <= 60

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://loading/api/v1/trading/plants/string/meters"
[
  {
    "energy": 0,
    "interval": "string",
    "meter_id": "string",
    "plant_id": "8c2c37ff-79f6-40ba-b98d-a2bfedecc0a3",
    "time": "2019-08-24T14:15:22Z"
  }
]
{
  "code": "BAD_REQUEST",
  "details": {},
  "error": "Bad Request",
  "message": "Validation error or invalid UUID",
  "statusCode": 400
}
{
  "code": "UNAUTHORIZED",
  "details": {},
  "error": "Unauthorized",
  "message": "Unauthorized",
  "statusCode": 400
}
{
  "code": "FORBIDDEN",
  "details": {},
  "error": "Forbidden",
  "message": "Forbidden",
  "statusCode": 400
}
{
  "code": "PLANT_NOT_FOUND",
  "details": {},
  "error": "Not Found",
  "message": "Plant not found",
  "statusCode": 400
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "details": {},
  "error": "Internal Server Error",
  "message": "Internal server error",
  "statusCode": 400
}

Query trading telemetry (AMQP-sourced)

GET
/api/v1/trading/plants/{id}/telemetry

Path Parameters

id*string

Query Parameters

from?string

Start time (ISO 8601)

to?string

End time (ISO 8601)

bucketMinutes?number

Aggregation bucket size in minutes

Default5
Range1 <= value <= 60

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://loading/api/v1/trading/plants/string/telemetry"
[
  {
    "consumption": 0,
    "fve_power": 0,
    "fve_reg": 0,
    "grid_power": 0,
    "invertor_power": 0,
    "plant_id": "8c2c37ff-79f6-40ba-b98d-a2bfedecc0a3",
    "soc": 0,
    "time": "2019-08-24T14:15:22Z"
  }
]
{
  "code": "BAD_REQUEST",
  "details": {},
  "error": "Bad Request",
  "message": "Validation error or invalid UUID",
  "statusCode": 400
}
{
  "code": "UNAUTHORIZED",
  "details": {},
  "error": "Unauthorized",
  "message": "Unauthorized",
  "statusCode": 400
}
{
  "code": "FORBIDDEN",
  "details": {},
  "error": "Forbidden",
  "message": "Forbidden",
  "statusCode": 400
}
{
  "code": "PLANT_NOT_FOUND",
  "details": {},
  "error": "Not Found",
  "message": "Plant not found",
  "statusCode": 400
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "details": {},
  "error": "Internal Server Error",
  "message": "Internal server error",
  "statusCode": 400
}

Latest trading telemetry snapshot

GET
/api/v1/trading/plants/{id}/telemetry/latest

Path Parameters

id*string

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://loading/api/v1/trading/plants/string/telemetry/latest"
{
  "consumption": 0,
  "fve_power": 0,
  "fve_reg": 0,
  "grid_power": 0,
  "invertor_power": 0,
  "plant_id": "8c2c37ff-79f6-40ba-b98d-a2bfedecc0a3",
  "soc": 0,
  "time": "2019-08-24T14:15:22Z"
}
{
  "code": "INVALID_UUID",
  "details": {},
  "error": "Bad Request",
  "message": "Invalid plant UUID",
  "statusCode": 400
}
{
  "code": "UNAUTHORIZED",
  "details": {},
  "error": "Unauthorized",
  "message": "Unauthorized",
  "statusCode": 400
}
{
  "code": "FORBIDDEN",
  "details": {},
  "error": "Forbidden",
  "message": "Forbidden",
  "statusCode": 400
}
{
  "code": "PLANT_NOT_FOUND",
  "details": {},
  "error": "Not Found",
  "message": "Plant not found",
  "statusCode": 400
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "details": {},
  "error": "Internal Server Error",
  "message": "Internal server error",
  "statusCode": 400
}