Authentication and first call

To call the API you need an access token, which you obtain with your client_id and client_secret. The token is valid for one hour: request it once and reuse it for every call.

Obtaining a token

curl -X POST https://k8s.prod.cloud.energyincloud.com/webapp/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=$CLIENT_ID" \
  -d "client_secret=$CLIENT_SECRET"

The response:

{
  "access_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "read:plants read:telemetry read:energy read:alarms read:controls"
}
  • HTTP Basic authentication (-u "$CLIENT_ID:$CLIENT_SECRET") is accepted as an alternative to the form fields.
  • The optional scope parameter requests a subset of your scopes.
  • Errors of this endpoint follow the OAuth 2.0 format, for example {"error": "invalid_client"}.

Token lifetime

The access token is valid for 1 hour (expires_in, seconds). There is no refresh token: request a new token with the same credentials shortly before expiry, and reuse the token for every call until then. Do not request one per call.

The first call

Pass the token in the Authorization header and list the plants your client sees:

curl "https://api.cloud.energyincloud.com/v1/plants?limit=2" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
{
  "data": [
    { "plant_id": "7b0728a9-853c-4b31-8446-a4eb00607566", "name": "Plant A",
      "country": "Italy", "timezone": "Europe/Rome", "created_at": "2025-07-03T09:12:44Z" },
    { "plant_id": "f15d7665-49c5-416b-828d-e4244d222b6f", "name": "Plant B",
      "country": "Italy", "timezone": "Europe/Rome", "created_at": "2025-09-18T14:05:10Z" }
  ],
  "pagination": { "next_cursor": "eyJpZCI6ImYxNWQ3NjY1In0=", "has_more": true }
}

What the response contains:

Field Meaning
plant_id stable identifier (UUID) of the plant, to use in every other call
country country name as registered; empty when not set
timezone IANA time zone of the plant: energy windows are computed in this zone
pagination when has_more is true, repeat the call passing next_cursor as the cursor parameter

limit ranges from 1 to 200, default 50. The plant detail, GET /v1/plants/{plant_id}, adds location, a free-text address: display it, do not parse it.

If the call fails

  • 401: the token is missing, expired or invalid. Request a new token.
  • 403: your client lacks the required scope. Contact zeroCO2.
  • Every other code is in the table of "Limits, errors and support".