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

# AVEVA PI Web API

> Client-mode REST API connector for AVEVA PI Web API (PI System / FactoryTalk Historian): stream value/recorded, streamset recorded, ad-hoc bulk write, and batch

Technical Preview

## Overview

A client-mode connector for a **curated** slice of the [AVEVA PI Web API](https://docs.aveva.com/bundle/pi-web-api/page/topics/getting-started.html) (PI System / FactoryTalk Historian) under your customer host `https://{host}/piwebapi`:

| Catalog connector event | Entity / path | Notes |
| - | - | - |
| (smoke) | `GET /system/status` | Uptime / system state |
| GET streams/\{webId}/value | `GET /streams/{webId}/value` | Current or time-specified value |
| (supporting) stream recorded | `GET /streams/{webId}/recorded` | `startTime` / `endTime` / `maxCount` |
| GET streamsets/\{webId}/recorded | `GET /streamsets/{webId}/recorded` | Catalog: `?startTime=` |
| POST streamsets/recorded | `POST /streamsets/recorded` | Ad-hoc bulk write MQTT → PI points |
| POST batch | `POST /batch` | Multi-request dictionary |

`BASE_ADDRESS` is `https://YOUR_PI_HOST/piwebapi` (no trailing slash; endpoints start with `/`). Topics use `historian/aveva-pi-web-api/<object>/<verb>`. Pass stream / element **WebIds** on each MQTT payload.

See the base guide: [REST API Connectors](/latest/lot-language/routes/rest-api-routes).

> [!NOTE]
>
> **Customer-hosted.** There is no public PI Web API sandbox. Replace `YOUR_PI_HOST` and supply Basic, Kerberos, or Bearer (OIDC) credentials configured on your instance. Prefer Hub secrets.

> [!NOTE]
>
> **Channels (WebSocket)** for live value change streams are out of scope. This package is **client REST only**. Use host Swagger at `https://{host}/piwebapi/help` for the full controller surface.

> [!NOTE]
>
> Prefer Hub secrets for tokens / passwords. This template has not been verified against a live PI Web API host. Queue status remains **blocked** until an authenticated live smoke succeeds.

## Basic Syntax

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
# Coreflux REST_API template — AVEVA PI Web API
# Auth: Bearer {value.json.api_token} (or Basic via USERNAME/PASSWORD secrets)
# BASE_ADDRESS: https://YOUR_PI_HOST/piwebapi

DEFINE ROUTE AvevaPiWebApiRestApi WITH TYPE REST_API
    ADD REST_API_CONFIG
        WITH BASE_ADDRESS "https://YOUR_PI_HOST/piwebapi"
        WITH ENABLE_CLIENT "true"
        WITH USE_SSL "true"
        WITH REQUEST_TIMEOUT '60'
        WITH DEFAULT_CONTENT_TYPE "application/json"
    ADD EVENT GetSystemStatus
        WITH SOURCE_TOPIC "historian/aveva-pi-web-api/system/status"
        WITH DESTINATION_TOPIC "historian/aveva-pi-web-api/system/status/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/system/status"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "Bearer {value.json.api_token}"
    ADD EVENT GetStreamValue
        WITH SOURCE_TOPIC "historian/aveva-pi-web-api/streams/value"
        WITH DESTINATION_TOPIC "historian/aveva-pi-web-api/streams/value/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/streams/{value.json.webId}/value"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "Bearer {value.json.api_token}"
    ADD EVENT GetStreamRecorded
        WITH SOURCE_TOPIC "historian/aveva-pi-web-api/streams/recorded"
        WITH DESTINATION_TOPIC "historian/aveva-pi-web-api/streams/recorded/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/streams/{value.json.webId}/recorded?startTime={value.json.startTime}&endTime={value.json.endTime}&maxCount={value.json.maxCount}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "Bearer {value.json.api_token}"
    ADD EVENT GetStreamSetRecorded
        WITH SOURCE_TOPIC "historian/aveva-pi-web-api/streamsets/recorded"
        WITH DESTINATION_TOPIC "historian/aveva-pi-web-api/streamsets/recorded/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/streamsets/{value.json.webId}/recorded?startTime={value.json.startTime}&endTime={value.json.endTime}&maxCount={value.json.maxCount}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Authorization" "Bearer {value.json.api_token}"
    ADD EVENT PostStreamSetsRecorded
        WITH SOURCE_TOPIC "historian/aveva-pi-web-api/streamsets/write"
        WITH DESTINATION_TOPIC "historian/aveva-pi-web-api/streamsets/write/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/streamsets/recorded"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "Authorization" "Bearer {value.json.api_token}"
        WITH BODY "{payload}"
    ADD EVENT PostBatch
        WITH SOURCE_TOPIC "historian/aveva-pi-web-api/batch/execute"
        WITH DESTINATION_TOPIC "historian/aveva-pi-web-api/batch/execute/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/batch"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "Authorization" "Bearer {value.json.api_token}"
        WITH BODY "{payload}"
```

## Events

| Event | Method | Endpoint | Request topic | Response topic |
| - | - | - | - | - |
| GetSystemStatus | GET | `/system/status` | `historian/aveva-pi-web-api/system/status` | `.../response` |
| GetStreamValue | GET | `/streams/{webId}/value` | `historian/aveva-pi-web-api/streams/value` | `.../response` |
| GetStreamRecorded | GET | `/streams/{webId}/recorded?startTime=&endTime=&maxCount=` | `historian/aveva-pi-web-api/streams/recorded` | `.../response` |
| GetStreamSetRecorded | GET | `/streamsets/{webId}/recorded?startTime=&endTime=&maxCount=` | `historian/aveva-pi-web-api/streamsets/recorded` | `.../response` |
| PostStreamSetsRecorded | POST | `/streamsets/recorded` | `historian/aveva-pi-web-api/streamsets/write` | `.../response` |
| PostBatch | POST | `/batch` | `historian/aveva-pi-web-api/batch/execute` | `.../response` |

## Auth

**Bearer (OIDC) — default in the template:**

1. Obtain an access token from your PI Web API OpenID Connect / identity provider configuration.
2. Pass `api_token` on the MQTT request payload so headers resolve:
   * `Authorization: Bearer {value.json.api_token}`
3. Store the token in Hub secrets / `GET SECRET "PI_WEB_API_TOKEN"`. Never commit real credentials.

**Basic (optional):**

1. Uncomment `WITH USERNAME` / `WITH PASSWORD GET SECRET "PI_WEB_API_PASSWORD"` on `REST_API_CONFIG`, **or** send `Authorization: Basic <base64(user:pass)>` by adjusting the header scheme and payload field.
2. Map the identity to a PI / AF identity with read/write rights for the target points.

Kerberos is supported by PI Web API deployments but is not expressed in this MQTT client template.

## Example payloads

**System status:**

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{ "api_token": "YOUR_OIDC_OR_BEARER_TOKEN" }
```

**Stream value:**

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "api_token": "YOUR_OIDC_OR_BEARER_TOKEN",
  "webId": "YOUR_POINT_OR_ATTRIBUTE_WEBID"
}
```

**Stream set recorded:**

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "api_token": "YOUR_OIDC_OR_BEARER_TOKEN",
  "webId": "YOUR_ELEMENT_WEBID",
  "startTime": "*-1h",
  "endTime": "*",
  "maxCount": "1000"
}
```

**Ad-hoc write (`PostStreamSetsRecorded`):**

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "api_token": "YOUR_OIDC_OR_BEARER_TOKEN",
  "Items": [
    {
      "WebId": "YOUR_POINT_WEBID",
      "Items": [
        { "Timestamp": "*", "Value": 42.5 }
      ]
    }
  ]
}
```

The HTTP body is the full MQTT `{payload}` (include only fields PI Web API expects).

## Deploy notes

* Deployable file: `AvevaPiWebApiRestApi.lot` — **no** `ADD METADATA`.
* Hub catalog sidecar: `hub-metadata.lot` (`WITH STATUS "beta"`, icon, doclink).
* Replace `YOUR_PI_HOST` before use. TLS: keep `USE_SSL "true"` for HTTPS hosts.
* Obtain WebIds via Points / Attributes / Elements search on your host (or batch step 1) before stream calls.

## Related

* [REST API Connectors](/latest/lot-language/routes/rest-api-routes)
* [REST API app catalog](/latest/lot-language/routes/rest-api-apps)
* [AVEVA PI Web API getting started](https://docs.aveva.com/bundle/pi-web-api/page/topics/getting-started.html)
* [Stream controller](https://docs.aveva.com/bundle/pi-web-api-reference/page/help/controllers/stream.html)
* [StreamSet controller](https://docs.aveva.com/bundle/pi-web-api-reference/page/help/controllers/streamset.html)
* [Batch controller](https://docs.aveva.com/bundle/pi-web-api-reference/page/help/controllers/batch.html)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.