> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nexalis.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Real-Time API

Nexalis Cloud exposes a powerful real-time API which allows users to query and fetch high-frequency sensor data using WarpScript, a stack-based language designed for time-series analysis.

***

## Quick Start Examples

* **[Nexalis Macros](./nexalis-macros)** - Learn how to use Nexalis custom macros for simplified queries
* **[Python Examples](./python-examples)** - Integrate the API into your Python data pipelines
* **[PowerBI Examples](./powerbi-examples)** - Create dashboards with time-series data

***

## API Endpoint

The Nexalis real-time API is accessible via your dedicated endpoint:

```
https://yourcompany.app.nexalis.io/api/v0/exec
```

Replace `yourcompany` with your organization's name. All requests must be sent via HTTP POST with WarpScript code in the request body.

***

## Authentication

All API requests require authentication using a READ token.

> Contact [contact@nexalis.io](mailto:contact@nexalis.io) to obtain your READ token.

***

## Data Structure

A tag is stored as a **Geo Time Series (GTS)**. Each GTS is uniquely identified across all your data with its **labels**, namely:

* `siteName` - site where the device is located
* `deviceModel` - manufacturer and model
* `deviceID` - unique identifier of the device
* `dataPoint` - device‑specific identifier (e.g., Modbus register, OPC UA tag)

Each GTS also has **attributes** which add context and describe a tag, such as:

* `description` - manufacturer‑provided description
* `protocol` - communication protocol used

### Standardized Tags

Nexalis standardizes some tags by contextualizing and translating them to the **Nexalis data model**, which is based on IEC 61850. Standardized tags will have additional attribute columns:

* `assetType` - standardized device type (e.g., Solar inverter, Storage inverter, Meteo station, Meter, Wind turbine, etc.)
* `subDeviceID` - distinguishes devices when connected via proxy/gateway
* `logicalNode` - standardized function type (e.g., MMDC: DC Measurements)
* `dataObject` - standardized tag (e.g., PhV: phase voltage)
* `subDataObject` - finer breakdown (e.g., phsA: phase A)
* `engUnits` - standardized engineering units
* `multiplier` - scaling multiplier for unit conversion (from scada unit to Nexalis `engUnits`)
* `adder` - scaling offset for unit conversion (from scada unit to Nexalis `engUnits`)
* `measurementType` - Analog or Discrete

<Note>
  **Field Availability**: Nexalis API only returns non-empty labels and attributes. While labels are always present for identification, standardized attributes (such as `assetType`, `logicalNode`, `dataObject`) are only included for tags that have been mapped to the Nexalis data model. Additionally, unit-related attributes (`engUnits`, `adder`, `multiplier`) are typically omitted for discrete measurement types, as these data points generally do not have a unit.
</Note>

***

## Core Query Functions

The API uses WarpScript, a stack-based language for time-series operations. Two main functions are available:

### FIND - Discover Available Metrics

Search for time-series matching specific criteria without fetching values. Useful for exploring what data is available.

Example query:

```warpscript theme={null}
{
  'token' 'YOUR_READ_TOKEN'
  'class' 'nx.value'
  'labels' { 'assetType' 'INV' 'dataObject' 'TotW' }
} FIND
```

Output:

```
[[{"c":"nx.value",
"l":{"siteName":"TX_001","deviceModel":"Satcon",".app":"nexalis","deviceID":"01234","dataPoint":"42"},
"a":{"dataObject":"TotW","subDataObject":"","protocol":"modbus_tcp","multiplier":"0.1","logicalNode":"MMXU","measurementType":"Analog","description":"AC Power, Generated = Export, from Inverter","engUnits":"kW","adder":"0","nx-agent-id":"v1.1.5#xxxx","assetType":"INV","subDeviceID":"BLK_001_23"},
"la":0,
"v":[]}]]
```

FIND returns class (`"c":{...}`), labels (`"l":{...}`), attributes (`"a":{...}`), and an empty value field (`"v":[]`).

[How to do it in python](./python-examples)

***

### FETCH - Retrieve Time-Series Data

Fetch actual values for specific time ranges and metrics.

Example query:

```warpscript theme={null}
{
  'token' 'YOUR_READ_TOKEN'
  'class' 'nx.value'
  'labels' { 'assetType' 'INV' 'dataObject' 'TotW' }
  'start' '2026-01-15T00:00:00Z'
  'end' '2026-01-15T01:00:00Z'
} FETCH
```

Output:

```
[[{"c":"nx.value",
"l":{"siteName":"TX_001","deviceModel":"Satcon",".app":"nexalis","deviceID":"01234","dataPoint":"42"},
"a":{"dataObject":"TotW","subDataObject":"","protocol":"modbus_tcp","multiplier":"0.1","logicalNode":"MMXU","measurementType":"Analog","description":"AC Power, Generated = Export, from Inverter","engUnits":"kW","adder":"0","nx-agent-id":"v1.1.5#xxxx","assetType":"INV","subDeviceID":"BLK_001_23"},
"la":0,
"v":[[1768438794869000,0,348],[1768438790168000,0,346],[1768438784989000,0,350], ... ,[1768435210217000,0,405],[1768435200214000,0,386]]}]]
```

Here, each sub-list in the "v" (value) field is a measurement, where the first element is the microseconds unix timestamp, and the last element is the actual value.

[How to do it in python](./python-examples)

***

Both FIND and FETCH functions support:

* **Regular expressions** for pattern matching (prefix with `~`)
* **Multiple filters** on labels and attributes (both passed in the "labels" field)

Additionally, FETCH supports:

* **Flexible time ranges** with ISO8601 strings or microseconds unix time

***

## Best Practices

### FIND first, then FETCH per tag

When querying multiple tags, always **discover before you fetch**:

1. Use **FIND** with label filters to get the list of matching tags and their exact identifiers
2. **FETCH each tag individually** using `deviceID` + `dataPoint` from the FIND results

```python theme={null}
import requests

ENDPOINT = "https://yourcompany.app.nexalis.io/api/v0/exec"
READ_TOKEN = "YOUR_READ_TOKEN"

# Step 1: discover all matching tags
find_query = f"""
{{
  'token' '{READ_TOKEN}'
  'class' 'nx.value'
  'labels' {{ 'siteName' 'TX_001' 'assetType' 'INV' 'dataObject' 'TotW' }}
}} FIND
"""
tags = requests.post(
    ENDPOINT,
    headers={{"Content-Type": "text/plain; charset=UTF-8"}},
    data=find_query
).json()[0]

# Step 2: fetch each tag individually over the full time range
for gts in tags:
    l = gts["l"]
    fetch_query = f"""
    {{
      'token' '{READ_TOKEN}'
      'class' 'nx.value'
      'labels' {{ 'deviceID' '{l["deviceID"]}' 'dataPoint' '{l["dataPoint"]}' }}
      'start' '2026-01-01T00:00:00Z'
      'end' '2026-02-01T00:00:00Z'
    }} FETCH
    @nexalis/scale
    """
    data = requests.post(
        ENDPOINT,
        headers={{"Content-Type": "text/plain; charset=UTF-8"}},
        data=fetch_query
    ).json()
    # process data...
```

<Note>
  This pattern keeps each request small and predictable. If a single tag fails, the others are unaffected. For concurrent fetching, wrap the loop in a `ThreadPoolExecutor`.
</Note>

### Go deep, not wide

Timeseries databases are optimized for long reads on a single tag. **One tag over a long period is always faster than many tags at once.**

| Avoid                                            | Prefer                                        |
| ------------------------------------------------ | --------------------------------------------- |
| Fetch 50 tags over 1 month in one request        | Fetch 1 tag over 1 month, repeat for each tag |
| Broad FETCH with only `assetType` + `dataObject` | Narrow FETCH with `deviceID` + `dataPoint`    |

### Filter as specifically as possible

Every label you add reduces the number of series the API needs to scan. Always include `siteName` when targeting a specific site, and add `deviceID` or `dataPoint` when you know them.

***

## Nexalis Custom Macros

Nexalis provides ready-to-use macros that simplify common time-series operations:

* **`@nexalis/scale`** - Apply unit conversions and calibrations
* **`@nexalis/fetch_trapezoidal_averages`** - Fetch and compute trapezoidal averages for irregularly-sampled data

For detailed examples of using these macros, see the [Nexalis Macros guide](./nexalis-macros).

### Custom Macros

You can also build your own WarpScript macros to encapsulate complex logic and reuse common query patterns across your organization.

***

## Filtering Data

The `labels` parameter in both FIND and FETCH queries accepts filters on both labels and attributes, allowing you to precisely target the data you need.

### Basic Filtering

Filter by exact matches on any label or attribute field:

```warpscript theme={null}
{
  'token' 'YOUR_READ_TOKEN'
  'class' 'nx.value'
  'labels' { 
    'siteName' 'TX_001'
    'assetType' 'INV'
    'dataObject' 'TotW'
  }
} FIND
```

### Regular Expression Filtering

Prefix filter values with `~` to use regular expressions for pattern matching:

```warpscript theme={null}
{
  'token' 'YOUR_READ_TOKEN'
  'class' 'nx.value'
  'labels' { 
    'siteName' '~TX_.*'           // Match any site starting with TX_
    'deviceID' '~INV-(1|2|3)'     // Match INV-1, INV-2, or INV-3
    'dataObject' '~(.*W$|.*Tmp.*)'         // Match any dataObject ending with W or containing Tmp
  }
} FIND
```

### Common Regex Patterns

| Pattern         | Description               | Example                       |
| --------------- | ------------------------- | ----------------------------- |
| `~.*`           | Match anything (wildcard) | `'siteName' '~.*'`            |
| `~^TX_`         | Starts with "TX\_"        | `'siteName' '~^TX_'`          |
| `~.*_001$`      | Ends with "\_001"         | `'deviceID' '~.*_001$'`       |
| `~(INV\|METER)` | Match multiple values     | `'assetType' '~(INV\|METER)'` |

<Note>
  Remember to escape special regex characters when needed. The tilde (`~`) prefix indicates that the value should be interpreted as a regular expression rather than an exact string match.
</Note>

***

## API Integration

The Nexalis real-time API can be queried from any tool or programming language that supports HTTP requests. Simply send a POST request with:

* **URL**: Your endpoint (`https://yourcompany.app.nexalis.io/api/v0/exec`)
* **Headers**: `X-Warp10-Token: YOUR_READ_TOKEN`
* **Body**: WarpScript code (plain text)

This works seamlessly with cURL, Python, PowerBI, and any other HTTP-capable tool.

***

## Learn More

* **[Nexalis Macros Examples](./nexalis-macros)** - Detailed macro usage and patterns
* **[Python Integration](./python-examples)** - Build data pipelines with Python
* **[PowerBI Integration](./powerbi-examples)** - Create live dashboards

For API access and support, contact [contact@nexalis.io](mailto:contact@nexalis.io)
