Edge-Cloud Authentication
Edge-cloud authentication uses Basic Authentication with site specific credentials. This method is ideal for edge devices that need to communicate directly to the Powernaut platform.
Getting Credentials​
You can obtain edge credentials for a site in two ways:
- During site creation
- Starting a new rotation
When creating a new site, the API response includes initial credentials:
- Python
- JavaScript
- Java
- Go
- C#
- cURL
import requests
import json
url = "https://api.powernaut.io/v1/connect/sites"
payload = json.dumps({
"location": {
"address": "Dok Noord, Gent, Belgium"
},
"supply_points": [
{
"grid_identifier": "EAN1234567890",
"direction": "bidirectional"
}
]
})
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer <token>'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Accept", "application/json");
myHeaders.append("Authorization", "Bearer <token>");
const raw = JSON.stringify({
"location": {
"address": "Dok Noord, Gent, Belgium"
},
"supply_points": [
{
"grid_identifier": "EAN1234567890",
"direction": "bidirectional"
}
]
});
const requestOptions = {
method: "POST",
headers: myHeaders,
body: raw,
redirect: "follow"
};
fetch("https://api.powernaut.io/v1/connect/sites", requestOptions)
.then((response) => response.text())
.then((result) => console.log(result))
.catch((error) => console.error(error));
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"location\":{\"address\":\"Dok Noord, Gent, Belgium\"},\"supply_points\":[{\"grid_identifier\":\"EAN1234567890\",\"direction\":\"bidirectional\"}]}");
Request request = new Request.Builder()
.url("https://api.powernaut.io/v1/connect/sites")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer <token>")
.build();
Response response = client.newCall(request).execute();
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://api.powernaut.io/v1/connect/sites"
method := "POST"
payload := strings.NewReader(`{"location":{"address":"Dok Noord, Gent, Belgium"},"supply_points":[{"grid_identifier":"EAN1234567890","direction":"bidirectional"}]}`)
client := &http.Client {
}
req, err := http.NewRequest(method, url, payload)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Accept", "application/json")
req.Header.Add("Authorization", "Bearer <token>")
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.powernaut.io/v1/connect/sites");
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization", "Bearer <token>");
var content = new StringContent("{\"location\":{\"address\":\"Dok Noord, Gent, Belgium\"},\"supply_points\":[{\"grid_identifier\":\"EAN1234567890\",\"direction\":\"bidirectional\"}]}", null, "application/json");
request.Content = content;
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
curl --location 'https://api.powernaut.io/v1/connect/sites' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <token>' \
--data '{"location":{"address":"Dok Noord, Gent, Belgium"},"supply_points":[{"grid_identifier":"EAN1234567890","direction":"bidirectional"}]}'
The response includes both the site details and its credentials.
{
id: "<uuid>",
// ... other site details
credentials: {
key: "<key>",
secret: "<secret>",
},
}
You can also perform this process directly in the Powernaut Portal. This provides a user-friendly interface for managing your sites and their credentials.
Using the Credentials​
Use Basic Authentication by including the credentials in the Authorization header.
Concatenate the key and secret, from the response above, with a colon (:) and encode with Base64:
Authorization: Basic <base64(key:secret)>
Rotating Credentials​
The credential rotation process allows you to safely update credentials without service interruption:
- Start Rotation: Get new credentials while keeping existing ones active
- Complete Rotation: Deactivate old credentials once migration is complete
- (Optional) Cancel Rotation: Cancel the rotation process if needed
During the rotation process, both the old and new credentials remain valid until the rotation is either completed or cancelled.
Credentials that stop being valid — after completing a rotation, or after being revoked — can still be accepted for up to 30 seconds. Verified credentials are cached briefly, so treat a rotation as finished only once that window has passed rather than immediately after the call returns.
Starting Rotation​
To initiate a credential rotation, use the following endpoint:
- Python
- JavaScript
- Java
- Go
- C#
- cURL
import requests
url = "https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate?name=<string>"
payload = {}
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer <token>'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
const myHeaders = new Headers();
myHeaders.append("Accept", "application/json");
myHeaders.append("Authorization", "Bearer <token>");
const requestOptions = {
method: "POST",
headers: myHeaders,
redirect: "follow"
};
fetch("https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate?name=<string>", requestOptions)
.then((response) => response.text())
.then((result) => console.log(result))
.catch((error) => console.error(error));
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
.url("https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate?name=<string>")
.method("POST", body)
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer <token>")
.build();
Response response = client.newCall(request).execute();
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate?name=%3Cstring%3E"
method := "POST"
client := &http.Client {
}
req, err := http.NewRequest(method, url, nil)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Accept", "application/json")
req.Header.Add("Authorization", "Bearer <token>")
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate?name=<string>");
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization", "Bearer <token>");
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
curl --location --request POST 'https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate?name=%3Cstring%3E' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <token>'
Completing Rotation​
Once you've updated your systems with the new credentials, complete the rotation to deactivate the old ones:
- Python
- JavaScript
- Java
- Go
- C#
- cURL
import requests
url = "https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate/complete?name=<string>"
payload = {}
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer <token>'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
const myHeaders = new Headers();
myHeaders.append("Accept", "application/json");
myHeaders.append("Authorization", "Bearer <token>");
const requestOptions = {
method: "POST",
headers: myHeaders,
redirect: "follow"
};
fetch("https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate/complete?name=<string>", requestOptions)
.then((response) => response.text())
.then((result) => console.log(result))
.catch((error) => console.error(error));
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
.url("https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate/complete?name=<string>")
.method("POST", body)
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer <token>")
.build();
Response response = client.newCall(request).execute();
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate/complete?name=%3Cstring%3E"
method := "POST"
client := &http.Client {
}
req, err := http.NewRequest(method, url, nil)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Accept", "application/json")
req.Header.Add("Authorization", "Bearer <token>")
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate/complete?name=<string>");
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization", "Bearer <token>");
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
curl --location --request POST 'https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate/complete?name=%3Cstring%3E' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <token>'
Cancelling Rotation​
If needed, you can cancel an ongoing rotation to keep using the original credentials:
- Python
- JavaScript
- Java
- Go
- C#
- cURL
import requests
url = "https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate/cancel?name=<string>"
payload = {}
headers = {
'Accept': 'application/json',
'Authorization': 'Bearer <token>'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
const myHeaders = new Headers();
myHeaders.append("Accept", "application/json");
myHeaders.append("Authorization", "Bearer <token>");
const requestOptions = {
method: "POST",
headers: myHeaders,
redirect: "follow"
};
fetch("https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate/cancel?name=<string>", requestOptions)
.then((response) => response.text())
.then((result) => console.log(result))
.catch((error) => console.error(error));
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
.url("https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate/cancel?name=<string>")
.method("POST", body)
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer <token>")
.build();
Response response = client.newCall(request).execute();
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate/cancel?name=%3Cstring%3E"
method := "POST"
client := &http.Client {
}
req, err := http.NewRequest(method, url, nil)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Accept", "application/json")
req.Header.Add("Authorization", "Bearer <token>")
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate/cancel?name=<string>");
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization", "Bearer <token>");
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
curl --location --request POST 'https://api.powernaut.io/v1/connect/sites/<uuid>/credentials/rotate/cancel?name=%3Cstring%3E' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <token>'