Obtain detail programmatically with our application programming interface
Obtaining an API Key
- 7SIGNAL utilizes OAuth 2.0, the industry-standard protocol for authorization. Obtain an API key and secret by first navigating to the Users icon in the unified login interface (https://start.7signal.com).
- Then click the API Keys menu item along the left, and then the + Add button.
- Select your Primary Organization, Role, Sapphire Group and click submit.
- Copy, paste and save your API client ID and secret. You will use it in the token exchange request/response process to connect to the API (see example below).
Public Link to Online Documentation
Our Swagger document provides an interactive interface to visualize and interact with the API's resources. It allows you to test endpoints directly from the documentation.
https://api-v2.7signal.com/swagger-ui/index.html#/
Tips for Getting Sensor Performance Data
Requests for performance data will require an "id" for networks, locations, service areas and access points. Use the GET requests below.
https://api-v2.7signal.com/networks/sensors
https://api-v2.7signal.com/topologies/sensors/locations
https://api-v2.7signal.com/topologies/sensors/serviceAreas
https://api-v2.7signal.com/topologies/sensors/accessPoints
After retrieving the information above, you can leverage it to construct queries that will access performance data. You can find Key Performance Indicator (KPI) codes here: https://www.7signal.com/info/kpi-list.
This is a sample query for obtaining Upload Throughput Speed (QUAP009) from a location.
https://api-v2.7signal.com/kpis/sensors/locations/119?kpiCodes=QUAP009&networkId=310&band=5&averaging=DAY&timelimit=ONEDAY
Below is a sample response.
{
"range": {
"to": 1734444869525,
"toAsDateString": "2024-12-17T14:14:29.525Z[UTC]",
"from": 1734358469525,
"fromAsDateString": "2024-12-16T14:14:29.525Z[UTC]",
"total": 1,
"duration": 86400000,
"durationAsString": "1 day"
},
"results": [
{
"kpiCode": "QUAP009",
"ordinal": 3,
"name": "HTTP UL throughput",
"description": "Measures uplink throughput in an HTTP transfer. The direction is uplink, that is, the wireless Eye-client sends data to a test-server. The default transfer time is 5 seconds, which value an administrator can modify in Carat management user interface.",
"measurements24GHz": [],
"measurements5GHz": [
{
"slaValue": 100,
"kpiValue": 163.13457878005877,
"status": "OK",
"samples": 1364,
"targetValue": 5,
"created_at": "2024-12-17T00:00:00.000-05:00"
}
],
"measurements6GHz": [],
"units": "Mbit/s",
"slaTargetValue": 5,
"included": true,
"topologyObject": {
"description": "",
"slaGroupResource": {
"slaGroupId": 41,
"groupName": "Default SLA (created by Setup Wizard)",
"inheritedFrom": null,
"inheritedName": null
},
"parentOrganizationId": 47,
"parentLocationId": 120,
"topologyType": "LOCATION",
"band": null,
"name": "Main Office",
"id": 119
},
"reportedWirelessNetwork": {
"description": "",
"slaGroupResource": {
"slaGroupId": null,
"groupName": null,
"inheritedFrom": null,
"inheritedName": null
},
"encryptionProperties": [
{
"type": 1,
"group_ciphers": [
5
],
"pairwise_ciphers": [
5
],
"auth_suites": [
2
],
"version": 0,
"preauth_supported": false
}
],
"hasActiveAccessPoints": true,
"topologyType": "WIRELESSNETWORK",
"name": "WiFiConnect",
"id": 310
},
"slaParameters": {
"thresholdMap": {
"GREEN": 90,
"YELLOW": 80,
"RED": 0
},
"targetValue": 5,
"targetEditable": true,
"comparator": "GREATER_THAN",
"comparatorOperator": ">="
},
"status": "OK"
}
]
}
The following table provides an explanation of some of the key-value pairs you will encounter in the results. If you need more assistance, please reach out to 7SIGNAL Support.
slaValue | Percentage of samples exceeding the targetValue. Expressed as a percentage, max is 100. |
kpiValue | Average result of all tests for the duration selected. Refer to the "units" key for a description of the value. |
status | Indicates whether the kpiValue exceeds the targetValue. Expressed as one of three values: OK, WARN or CRITICAL. |
samples | Number of tests taken in the time period or duration selected. |
targetValue | The performance target that defines acceptable service levels. This value can be customized using the Configurator interface. Refer to the "units" key for a description of the value. |
Sample Code (Python)
This program will authenticate, then get a list of Sapphire and Mobile Eyes purchased and deployed. It will flatten the JSON data and export it to a csv file.
import requests
import csv
eye_url = 'https://api-v2.7signal.com/eyes'
org_url = 'https://api-v2.7signal.com/organizations'
organizationId = '8c5e9699-ba76-4926-aeb3-fxxxxxxxyyzz'
file_name = 'globalcorp_eyes.csv'
auth_data = {
"client_id": "6zvuUxxxxxxxxxxyyyyyzzzzz6NnXUKH",
"client_secret": "KGzWXje9Inwzle2V7eGxM5kfrGrqnCrVucVExxxxxxxxxxxxyyyyyzzzzzzzJqPa",
"grant_type": "client_credentials"
}
auth_headers = {
"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded"
}
# Make the POST request to get token
token_exch_response = requests.post('https://api-v2.7signal.com/oauth2/token', data=auth_data, headers=auth_headers)
if token_exch_response.status_code == 200:
token_exch_json_response = token_exch_response.json()
token = token_exch_json_response.get("access_token")
if token:
# Headers for the eyes and org endpoints
headers_eyes = {
"Accept": "application/json",
"Authorization": f"Bearer {token}"
}
# Make GET requests for both eye and org data
eye_response = requests.get(f"{eye_url}?organizationId={organizationId}", headers=headers_eyes)
org_response = requests.get(org_url, headers=headers_eyes)
if eye_response.status_code == 200 and org_response.status_code == 200:
eye_data = eye_response.json()
org_data = org_response.json()
# Flatten the eye data
flattened_eye_data = {
"agents_organizationName": eye_data.get("agents", {}).get("organizationName", "N/A"),
"agents_deviceCount": eye_data.get("agents", {}).get("deviceCount", 0),
"agents_licenseSummary_packageName": eye_data.get("agents", {}).get("licenseSummary", {}).get("packageName", "N/A"),
"agents_licenseSummary_totalLicenses": eye_data.get("agents", {}).get("licenseSummary", {}).get("totalLicenses", 0),
"agents_licenseSummary_usedLicenses": eye_data.get("agents", {}).get("licenseSummary", {}).get("usedLicenses", 0),
"agents_licenseSummary_freeLicenses": eye_data.get("agents", {}).get("licenseSummary", {}).get("freeLicenses", 0),
"sensors_deviceCount": eye_data.get("sensors", {}).get("deviceCount", 0),
"sensors_deviceStatusSummary_offline": eye_data.get("sensors", {}).get("deviceStatusSummary", {}).get("offline", 0),
"sensors_deviceStatusSummary_stopped": eye_data.get("sensors", {}).get("deviceStatusSummary", {}).get("stopped", 0),
"sensors_deviceStatusSummary_idle": eye_data.get("sensors", {}).get("deviceStatusSummary", {}).get("idle", 0),
"sensors_deviceStatusSummary_purchased": eye_data.get("sensors", {}).get("deviceStatusSummary", {}).get("purchased", 0),
"sensors_deviceStatusSummary_active": eye_data.get("sensors", {}).get("deviceStatusSummary", {}).get("active", 0),
"sensors_deviceStatusSummary_maintenance": eye_data.get("sensors", {}).get("deviceStatusSummary", {}).get("maintenance", 0),
"sensors_modelSummary_eye6300": eye_data.get("sensors", {}).get("modelSummary", {}).get("eye 6300", 0),
"sensors_modelSummary_eye6200": eye_data.get("sensors", {}).get("modelSummary", {}).get("eye 6200", 0),
"sensors_modelSummary_eye2200": eye_data.get("sensors", {}).get("modelSummary", {}).get("eye 2200", 0),
"sensors_modelSummary_eye250": eye_data.get("sensors", {}).get("modelSummary", {}).get("eye 250", 0),
}
# Flatten the org data and merge with eye data
combined_data = []
for result in org_data.get("results", []):
merged_data = flattened_eye_data.copy()
merged_data.update({
"pagination_perPage": org_data.get("pagination", {}).get("perPage", "N/A"),
"pagination_page": org_data.get("pagination", {}).get("page", "N/A"),
"pagination_total": org_data.get("pagination", {}).get("total", "N/A"),
"pagination_pages": org_data.get("pagination", {}).get("pages", "N/A"),
"result_connection_id": result.get("connection", {}).get("id", "N/A"),
"result_id": result.get("id", "N/A"),
"result_name": result.get("name", "N/A"),
"result_mobileEyeOrgCode": result.get("mobileEyeOrgCode", "N/A")
})
combined_data.append(merged_data)
# Generate fieldnames dynamically
fieldnames = set(flattened_eye_data.keys()).union(*[fd.keys() for fd in combined_data])
# Write combined data to a CSV file
csv_file_name = file_name
with open(csv_file_name, mode='w', newline='') as file:
writer = csv.DictWriter(file, fieldnames=sorted(fieldnames))
writer.writeheader()
writer.writerows(combined_data)
print(f"Flattened data has been written to {csv_file_name}")
else:
print("Error fetching data from eyes or organizations endpoints.")
else:
print("Error fetching authentication token.")