REST API Basics
Logging in
To authorize ourselves with the optiCLOUD API, we send a POST request to the /api/noauth/authorization endpoint.
The request body must contain the following JSON fields:
username: Our username or email addresspassword: Our password
In return, we receive a list of tenants to which we have access.
Using the authorityID of the tenant we want to use, we send a POST request to the api/auth/login endpoint.
This time, the request body must contain both the username and password, as well as our selected authorityID as a field.
The endpoint then responds with our session key or token, which we must now use to authorize all actions.
In Python, this looks as follows:
import requests
import os
# enter information
BASEURL = "https://test.opticloud.io"
CREDENTIALS = {"username":"$YOUR_USERNAME$", "password":"\"$YOUR_PASSWORD$"}
TENANT = "$YOUR_TENANT$"
# leave empty
TENANT_INFO = None
TOKENS = None
HEADER = None
# Login to Tenant
def login(baseurl, credentials, tenant):
auth_response = requests.post(baseurl + "/api/noauth/authorization", json=credentials, verify=True)
auth_response.raise_for_status()
for i in auth_response.json():
try:
if i["tenant"]["name"] == tenant:
global TENANT_INFO
TENANT_INFO = i
credentials["authorityId"] = i["authorityId"]["id"]
except KeyError:
continue
if credentials["authorityId"]:
login_response = requests.post(baseurl + "/api/auth/login", json=credentials, verify=True)
login_response.raise_for_status()
global TOKENS
TOKENS = login_response.json()
global HEADER
HEADER = {"X-Authorization": f"Bearer {TOKENS['token']}"}
return True
else:
return False
Retrieve device list
The api/tenants/{tenant_id}/devices endpoint can be used to obtain a list of devices belonging to a tenant.
To do this, we simply send a GET request with the URL parameters page=0 and limit=-1.
This returns a list of all devices, including their IDs.
The whole thing in Python:
# Get Devices from Tenant
def get_devices(baseurl, header, tenant_id):
parameters = {
"page": 0,
"limit":-1
}
devices_response = requests.get(baseurl + f"/api/tenants/{tenant_id}/devices", headers=header, params=parameters, verify=True)
devices_response.raise_for_status()
devices_list = devices_response.json()["data"]
return devices_list
Querying OSF files for a device
Using a device-id from the previous step, we can list the OSF files for a device with a GET request from the api/devices/{device_id}/data-files/original endpoint.
To do this, we need to specify four URL parameters:
startTime: The start of the time range from which we want to list files. (Unix timestamp with millisecond accuracy)endTime: The end of the time range from which we want to list files. (Unix timestamp with millisecond accuracy)limit: The maximum number of files to be listed. (-1 for no limit)page=0
In Python, this works as follows:
# get processed osf files (data-files/original) works only if files were processed by OptiCloud
def get_processed_osf_files(baseurl,header, device_id, start_time, end_time):
parameters = {
"startTime": start_time,
"endTime": end_time,
"limit":-1,
"page": 0
}
osf_files_response = requests.get(baseurl + f"/api/devices/{device_id}/data-files/original", headers=header, params=parameters, verify=True)
osf_files_response.raise_for_status()
osf_file_list = osf_files_response.json()["data"]
return osf_file_list
Download OSF file
To download files from the list you just requested, we first need to send a POST request to the /api/device/{device_id}/data-files/CLIENT_SCOPE/download endpoint.
To do this, we send a JSON list with the name of the file we want to download in the body of the request.
In return, we receive a token that we can use to send a GET request to /api/device/{device_id}/data-files/CLIENT_SCOPE/token/{download_token} to retrieve our file as a byte string.
The whole thing implemented in Python:
def download_processed_osf_file(baseurl, header, device_id, filename, savedir):
prepared_filename = [filename]
download_response = requests.post(baseurl + f"/api/device/{device_id}/data-files/CLIENT_SCOPE/download", headers=header, json=prepared_filename, verify=True)
download_response.raise_for_status()
download_token = download_response.text
download_file_response = requests.get(baseurl + f"/api/device/{device_id}/data-files/CLIENT_SCOPE/token/{download_token}", headers=header, verify=True)
download_file_response.raise_for_status()
truncated_filename = str(filename).split("/")[-1]
save_path = os.path.join(savedir, truncated_filename)
with open(save_path, "wb") as f:
f.write(download_file_response.content)
return save_path
If multiple files have been requested, the downloaded byte string is not an .osfz file, but a Zip archive.
This must be unzipped before further processing.
Retrieving the latest telemetry data from a device
If we only need the latest data from a device, we can retrieve it with a GET request to the /api/plugins/telemetry/DEVICE/{device_id}/values/timeseries endpoint.
We also need to specify two URL parameters, startTs and endTs.
These are normally used to query telemetry data from a specific time period, but since we only need the latest values, we set both to the current time (as a Unix timestamp with millisecond accuracy).
After a successful request, the endpoint provides us with a list of all channels with their corresponding latest values and timestamps.
In Python, this can be implemented as follows, for example:
def get_latest_telemetry(baseurl, header, device_id):
parameters = {
"startTs": time.time(),
"endTs": time.time()
}
latest_telemetry = requests.get(baseurl + f"/api/plugins/telemetry/DEVICE/{device_id}/values/timeseries",
parameters, headers=header, verify=True)
latest_telemetry.raise_for_status()
return latest_telemetry.json()
Retrieving device communication
To retrieve the communication logs of optiMEAS devices (PING, ATTN, RETURN_FILE, etc.),
a GET request can be sent to the /api/devices/{deviceId}/communication/data endpoint.
We need to specify four URL parameters:
startTime: The start of the time range from which we want to list files. (Unix timestamp with millisecond accuracy)endTime: The end of the time range from which we want to list files. (Unix timestamp with millisecond accuracy)limit: The maximum number of files to be listed (maximum 2147483647).page: always 0
An example implementation in Python:
# Gets device communication between the given timestamps
def get_device_communication(baseurl, header, deviceId, startTs, endTs):
parameters = {
"startTime": startTs,
"endTime": endTs,
"limit": 2147483647,
"page": 0
}
communication_response = requests.get(baseurl + f"/api/devices/{deviceId}/communication/data", headers=header, params=parameters)
communication_response.raise_for_status()
return communication_response.json()
Communicating with a device
Requesting a file list (LIST_FILES)
To obtain a list of files stored on a device, we can send a POST request to the /api/devices/{deviceId}/request-list endpoint.
We must pass the following parameters in the request body:
startTime: Start of the file search period. Must be specified in ISO 8601 format (e.g.,2025-06-15 00:51+01:00).endTime: End of the file search period. To be specified in ISO 8601 format (e.g.,2026-04-26 23:59+01:00).tag: File tag that the device should search for (usuallypreview).
As an example in Python:
# Request a list of files on the target device
def request_list(baseurl, header, deviceId, startTime, endTime, tag):
request_body = {
"startTime": startTime,
"endTime": endTime,
"tag": tag
}
list_request_response = requests.post(baseurl + f"/api/devices/{deviceId}/request-list",
headers=header, json=request_body)
list_request_response.raise_for_status()
Request file upload (REQUEST_FILE)
If the LIST_FILES command finds files that are present on the device but not on the server,
the corresponding file can be requested using a POST request to the /api/devices/{deviceId}/request-file endpoint.
To do this, we simply need to pass the following parameters in the request body:
name: The name of the file, including the absolute path (e.g.,/sde/preview/20250615/20250615_133751.osfz)tag: The tag of the file (usuallypreview).
In Python, this can be implemented as follows:
# Request device to upload named file to server
def request_file(baseurl, header, deviceId, fileName, fileTag):
request_body = [{
"name": fileName,
"tag": fileTag
}]
file_request_response = requests.post(baseurl + f"/api/devices/{deviceId}/request-file",
headers=header, json=request_body)
file_request_response.raise_for_status()
Restart device (REBOOT)
We can give an optiMEAS device the command to restart by sending a POST request to the /api/devices/{deviceId}/reboot endpoint.
In Python, for example:
def reboot_device(baseurl, header, deviceId):
reboot_response = requests.post(baseurl + f"/api/devices/{deviceId}/reboot", headers=header)
reboot_response.raise_for_status()
Custom commands
Custom commands can be sent to the device using a POST request to the /api/devices/{deviceId}/commands endpoint.
This endpoint corresponds to the "Send command" button under the "Management" menu item.
Accordingly, in addition to the freely selectable body of the request, we must also pass the URL parameter method.
This can take the values SCPI_APP, SCPI_DEVICE_MANAGER, or BASH.
The following Python example sends a command to run the Unix program uptime on the device:
def send_uptime_command(baseurl, header, deviceId):
parameters = {
"method": "BASH"
}
request_body = "uptime"
uptime_response = requests.post(baseurl + f"/api/devices/{deviceId}/commands", params=parameters, json=request_body,
headers=header)
uptime_response.raise_for_status()
Logout
To log out at the end of the session, we simply need to call the /api/auth/logout endpoint as follows:
def logout(baseurl, header):
logout_response = requests.post(baseurl + "/api/auth/logout", headers=header, verify=True)
logout_response.raise_for_status()
return logout_response.status_code