PIWebAPI 1.0.0

dotnet add package PIWebAPI --version 1.0.0
                    
NuGet\Install-Package PIWebAPI -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PIWebAPI" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PIWebAPI" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="PIWebAPI" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PIWebAPI --version 1.0.0
                    
#r "nuget: PIWebAPI, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PIWebAPI@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PIWebAPI&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=PIWebAPI&version=1.0.0
                    
Install as a Cake Tool

PIWebAPI - REST API Documentation

A .NET Framework 4.8 REST API for accessing OSIsoft PI System data via the AF SDK.

Base URL: http://{host}:{port}/api


Table of Contents

  1. Authentication
  2. Common Concepts
  3. Points API
  4. Streams API
  5. StreamSets API
  6. AF Hierarchy API
  7. Event Frames API
  8. Health API
  9. Data Models
  10. Error Handling

Authentication

The API uses Windows Integrated Authentication (NTLM/Kerberos). Clients must provide valid Windows credentials that have appropriate permissions on the PI Data Archive and AF Server.


Common Concepts

WebId

All resources are identified by a WebId - a Base64-encoded identifier with a type prefix:

Prefix Type
P PI Point
E AF Element
A AF Attribute
D AF Database
F Event Frame

Time Syntax

The API supports both ISO 8601 and PI time syntax:

Syntax Description Example
* or now Current time *
*-{n}{unit} Relative past *-1h, *-7d
*+{n}{unit} Relative future *+30m
t or today Start of today (midnight) t
y or yesterday Start of yesterday y
ISO 8601 Absolute timestamp 2024-01-15T10:00:00Z

Interval Syntax

Time intervals use the format {n}{unit}:

Unit Description
ms Milliseconds
s Seconds
m Minutes
h Hours
d Days
w Weeks

Examples: 500ms, 30s, 5m, 1h, 1d, 1w

Summary Types

Available summary/aggregate types:

  • Average - Time-weighted average
  • Total - Sum of values
  • Minimum - Minimum value
  • Maximum - Maximum value
  • Count - Number of values
  • Range - Max minus Min
  • StdDev - Standard deviation
  • PopulationStdDev - Population standard deviation
  • PercentGood - Percentage of good quality values

Points API

Endpoints for PI Points (tags) in the PI Data Archive.

Search Points

GET /api/points?nameFilter={pattern}&maxResults={n}
Parameter Type Default Description
nameFilter string * Name pattern with wildcards
maxResults int 100 Maximum results (1-10000)

Response: PointDto[]


Get Point

GET /api/points/{webId}

Response: PointDto


Get Current Value

GET /api/points/{webId}/value

Response: TimeSeriesValueDto


Update Current Value

PUT /api/points/{webId}/value
Content-Type: application/json

{
  "timestamp": "2024-01-15T10:00:00Z",
  "value": 42.5,
  "good": true
}

Get Recorded Values

GET /api/points/{webId}/recorded?startTime={start}&endTime={end}&maxCount={n}
Parameter Type Default Description
startTime string *-1h Start time
endTime string * End time
maxCount int 10000 Maximum values (1-1000000)

Response: TimeSeriesValueDto[]


Get Recorded Values with Filter

GET /api/points/{webId}/recordedfiltered?startTime={start}&endTime={end}&filterExpression={expr}
Parameter Type Default Description
startTime string *-1h Start time
endTime string * End time
boundaryType string Inside Inside, Outside, Interpolated
filterExpression string - PI expression filter
includeFilteredValues bool false Include filtered values
maxCount int 10000 Maximum values

Response: TimeSeriesValueDto[]


Get Recorded Values by Count

GET /api/points/{webId}/recordedbycount?time={time}&count={n}&direction={dir}
Parameter Type Default Description
time string * Reference time
count int 100 Number of values (1-100000)
direction string Backward Forward or Backward

Response: TimeSeriesValueDto[]


Get Recorded Values at Times

GET /api/points/{webId}/recordedattimes?times={timestamps}&retrievalMode={mode}
Parameter Type Default Description
times string - Comma-separated timestamps
retrievalMode string Auto Auto, AtOrBefore, AtOrAfter, Exact

Response: TimeSeriesValueDto[]


Get Interpolated Values

GET /api/points/{webId}/interpolated?startTime={start}&endTime={end}&interval={interval}
Parameter Type Default Description
startTime string *-1h Start time
endTime string * End time
interval string 1h Interpolation interval

Response: TimeSeriesValueDto[]


Get Interpolated Values at Times

GET /api/points/{webId}/interpolatedattimes?times={timestamps}
Parameter Type Description
times string Comma-separated timestamps

Response: TimeSeriesValueDto[]


Get Plot Values

Optimized for visualization - returns significant values that capture data shape.

GET /api/points/{webId}/plot?startTime={start}&endTime={end}&intervals={n}
Parameter Type Default Description
startTime string *-8h Start time
endTime string * End time
intervals int 640 Number of intervals (1-10000)

Response: TimeSeriesValueDto[]


Get Summary

GET /api/points/{webId}/summary?startTime={start}&endTime={end}&summaryType={type}
Parameter Type Default Description
startTime string *-1d Start time
endTime string * End time
summaryType string Average Summary type
summaryDuration string - Duration per summary period

Response: SummaryDto[]


Get Multiple Summaries

GET /api/points/{webId}/summaries?startTime={start}&endTime={end}&summaryTypes={types}
Parameter Type Default Description
startTime string *-1d Start time
endTime string * End time
summaryTypes string Average,Minimum,Maximum,Total Comma-separated types
summaryDuration string - Duration per period
calculationBasis string TimeWeighted TimeWeighted or EventWeighted

Response: Dictionary<string, SummaryDto[]>


Get Percent Good

GET /api/points/{webId}/percentgood?startTime={start}&endTime={end}

Response: PercentGoodDto


Get Time-Weighted Value

GET /api/points/{webId}/timeweightedvalue?startTime={start}&endTime={end}

Response: TimeSeriesValueDto


Get End of Stream

GET /api/points/{webId}/end

Response: TimeSeriesValueDto


Write Values

POST /api/points/{webId}/recorded?updateOption={option}&bufferOption={buffer}
Content-Type: application/json

[
  { "timestamp": "2024-01-15T10:00:00Z", "value": 42.5, "good": true },
  { "timestamp": "2024-01-15T10:01:00Z", "value": 43.2, "good": true }
]
Parameter Type Default Description
updateOption string Replace Replace, Insert, NoReplace, ReplaceOnly, InsertNoCompression, Remove
bufferOption string BufferIfPossible BufferIfPossible, DoNotBuffer, Buffer

Response: WriteResultDto


Replace Values in Range

PUT /api/points/{webId}/recorded?startTime={start}&endTime={end}
Content-Type: application/json

[
  { "timestamp": "2024-01-15T10:00:00Z", "value": 42.5, "good": true }
]

Response: WriteResultDto


Delete Values in Range

DELETE /api/points/{webId}/recorded?startTime={start}&endTime={end}

Response: { "deletedCount": 5 }


Get Point Attributes

GET /api/points/{webId}/attributes

Response: Dictionary<string, object>


Update Point Attributes

PUT /api/points/{webId}/attributes
Content-Type: application/json

{
  "descriptor": "Updated description",
  "engunits": "degC"
}

Get Annotations

GET /api/points/{webId}/annotations?time={timestamp}

Response: AnnotationDto[]


Create Annotation

POST /api/points/{webId}/annotations?time={timestamp}
Content-Type: application/json

{
  "name": "Operator Note",
  "value": "Sensor calibrated"
}

Streams API

Unified data access for both PI Points and AF Attributes.

Get Value

GET /api/streams/{webId}/value

Works with both PI Point (P prefix) and AF Attribute (A prefix) WebIds.

Response: TimeSeriesValueDto


Update Value

PUT /api/streams/{webId}/value
Content-Type: application/json

{
  "timestamp": "2024-01-15T10:00:00Z",
  "value": 42.5,
  "good": true
}

Get Recorded Values

GET /api/streams/{webId}/recorded?startTime={start}&endTime={end}&maxCount={n}

Response: TimeSeriesValueDto[]


Get Interpolated Values

GET /api/streams/{webId}/interpolated?startTime={start}&endTime={end}&interval={interval}

Response: TimeSeriesValueDto[]


Get Plot Values

GET /api/streams/{webId}/plot?startTime={start}&endTime={end}&intervals={n}

Response: TimeSeriesValueDto[]


Get Summary

GET /api/streams/{webId}/summary?startTime={start}&endTime={end}&summaryType={type}

Response: SummaryDto[]


Get Multiple Summaries

GET /api/streams/{webId}/summaries?startTime={start}&endTime={end}&summaryTypes={types}

Response: Dictionary<string, SummaryDto[]>


Get Multiple Values

GET /api/streams/values?webIds={id1},{id2},{id3}
Parameter Type Description
webIds string Comma-separated WebIds (max 100)

Response: Dictionary<string, TimeSeriesValueDto>


Write Values

POST /api/streams/{webId}/recorded?updateOption={option}&bufferOption={buffer}
Content-Type: application/json

[
  { "timestamp": "2024-01-15T10:00:00Z", "value": 42.5, "good": true }
]

Response: WriteResultDto


StreamSets API

Bulk operations on multiple streams for efficient data retrieval.

Get Current Values (GET)

GET /api/streamsets/value?webIds={id1},{id2},{id3}
Parameter Type Description
webIds string Comma-separated WebIds (max 1000)

Response: Dictionary<string, TimeSeriesValueDto>


Get Current Values (POST)

POST /api/streamsets/value
Content-Type: application/json

{
  "webIds": ["P...", "P...", "A..."]
}

Response: Dictionary<string, TimeSeriesValueDto>


Get Recorded Values

GET /api/streamsets/recorded?webIds={ids}&startTime={start}&endTime={end}&maxCount={n}
Parameter Type Default Description
webIds string - Comma-separated WebIds (max 100)
startTime string *-1h Start time
endTime string * End time
maxCount int 1000 Max values per stream

Response: Dictionary<string, TimeSeriesValueDto[]>


Get Interpolated Values

GET /api/streamsets/interpolated?webIds={ids}&startTime={start}&endTime={end}&interval={interval}

Response: Dictionary<string, TimeSeriesValueDto[]>


Get Plot Values

GET /api/streamsets/plot?webIds={ids}&startTime={start}&endTime={end}&intervals={n}

Response: Dictionary<string, TimeSeriesValueDto[]>


Get Summary Values

GET /api/streamsets/summary?webIds={ids}&startTime={start}&endTime={end}&summaryTypes={types}

Response: Dictionary<string, Dictionary<string, SummaryDto[]>>


Get End of Stream Values

GET /api/streamsets/end?webIds={ids}

Response: Dictionary<string, TimeSeriesValueDto>


Batch Write Values

POST /api/streamsets/recorded/batch
Content-Type: application/json

{
  "updateOption": "Replace",
  "bufferOption": "BufferIfPossible",
  "items": [
    {
      "webId": "P...",
      "values": [
        { "timestamp": "2024-01-15T10:00:00Z", "value": 42.5, "good": true }
      ]
    },
    {
      "webId": "P...",
      "values": [
        { "timestamp": "2024-01-15T10:00:00Z", "value": 100.0, "good": true }
      ]
    }
  ]
}

Response: Dictionary<string, WriteResultDto>


AF Hierarchy API

Endpoints for navigating the Asset Framework hierarchy.

List Databases

GET /api/af/databases

Response: AFDatabaseDto[]


Get Database

GET /api/af/databases/{webId}

Response: AFDatabaseDto


Get Database Elements

GET /api/af/databases/{webId}/elements?depth={n}
Parameter Type Default Description
depth int 0 Hierarchy depth (0-10)

Response: AFElementDto[]


Get Elements

GET /api/af/elements?path={path}&depth={n}
Parameter Type Default Description
path string - AF path (e.g., \\Server\Database\Element)
depth int 0 Hierarchy depth (0-10)

Response: AFElementDto[]


Get Element

GET /api/af/elements/{webId}

Response: AFElementDto


Get Child Elements

GET /api/af/elements/{webId}/children

Response: AFElementDto[]


Get Element Attributes

GET /api/af/elements/{webId}/attributes

Response: AFAttributeDto[]


Get Attribute

GET /api/af/attributes/{webId}

Response: AFAttributeDto


Get Attribute Value

GET /api/af/attributes/{webId}/value

Response: TimeSeriesValueDto


Search AF Hierarchy

GET /api/af/search?query={query}&scope={scope}&maxResults={n}
Parameter Type Default Description
query string - AF search query
scope string Elements Elements or Attributes
maxResults int 100 Maximum results (1-10000)

Response: AFElementDto[]


Event Frames API

Endpoints for AF Event Frames.

Search Event Frames

GET /api/eventframes?startTime={start}&endTime={end}&nameFilter={filter}
Parameter Type Default Description
startTime string *-1d Start time
endTime string * End time
nameFilter string * Name pattern with wildcards
templateName string - Template name filter
referencedElementWebId string - Element WebId to search within
searchMode string Overlapped Overlapped, StartInRange, EndInRange, InProgress
maxCount int 1000 Maximum results

Response: EventFrameDto[]


Get Event Frame

GET /api/eventframes/{webId}

Response: EventFrameDto


Get Event Frames for Element

GET /api/eventframes/element/{elementWebId}?startTime={start}&endTime={end}

Response: EventFrameDto[]


Create Event Frame

POST /api/eventframes
Content-Type: application/json

{
  "name": "Equipment Failure",
  "description": "Pump P-101 tripped",
  "startTime": "2024-01-15T10:00:00Z",
  "templateName": "Equipment Alarm",
  "refElementWebIds": ["E..."]
}

Response: EventFrameDto


Update Event Frame

PUT /api/eventframes/{webId}
Content-Type: application/json

{
  "name": "Updated Name",
  "description": "Updated description"
}

End Event Frame

POST /api/eventframes/{webId}/end?endTime={time}
Parameter Type Default Description
endTime string * (now) End time

Delete Event Frame

DELETE /api/eventframes/{webId}

Acknowledge Event Frame

POST /api/eventframes/{webId}/acknowledge

Get Event Frame Attributes

GET /api/eventframes/{webId}/attributes

Response: AFAttributeDto[]


Capture Values

POST /api/eventframes/{webId}/capturevalues

Health API

Endpoints for monitoring API and connection health.

Overall Health

GET /api/health

Response:

{
  "status": "Healthy",
  "version": "1.0.0",
  "components": [
    {
      "status": "Healthy",
      "component": "PI Data Archive",
      "details": { ... }
    },
    {
      "status": "Healthy",
      "component": "AF Server",
      "details": { ... }
    }
  ]
}

PI Data Archive Health

GET /api/health/pi

Response: HealthDto


AF Server Health

GET /api/health/af

Response: HealthDto


Liveness Check

GET /api/health/live

Response:

{
  "status": "alive",
  "timestamp": "2024-01-15T10:00:00Z"
}

Readiness Check

GET /api/health/ready

Returns 200 OK if ready, 503 Service Unavailable if not.

Response:

{
  "status": "ready",
  "timestamp": "2024-01-15T10:00:00Z",
  "pi": "Healthy",
  "af": "Healthy"
}

Data Models

TimeSeriesValueDto

{
  "timestamp": "2024-01-15T10:00:00Z",
  "value": 42.5,
  "good": true,
  "questionable": false,
  "substituted": false,
  "annotated": false
}
Field Type Description
timestamp DateTime UTC timestamp
value object Value (numeric, string, or digital state)
good bool Good quality flag
questionable bool Questionable quality flag
substituted bool Value was substituted
annotated bool Has annotations

PointDto

{
  "webId": "P...",
  "name": "SINUSOID",
  "description": "12 Hour Sine Wave",
  "pointType": "Float32",
  "engineeringUnits": "degC",
  "pointClass": "classic",
  "digitalSetName": null,
  "future": false,
  "step": false,
  "zero": 0.0,
  "span": 100.0,
  "serverName": "PI-SERVER"
}

SummaryDto

{
  "type": "Average",
  "timestamp": "2024-01-15T10:00:00Z",
  "value": 42.5,
  "good": true
}

AFElementDto

{
  "webId": "E...",
  "name": "Pump-101",
  "description": "Main cooling pump",
  "path": "\\\\Server\\Database\\Plant\\Pump-101",
  "templateName": "Pump",
  "categoryNames": ["Critical Equipment"],
  "hasChildren": true,
  "attributes": [ ... ],
  "children": [ ... ]
}

AFAttributeDto

{
  "webId": "A...",
  "name": "Temperature",
  "description": "Process temperature",
  "path": "\\\\Server\\Database\\Plant\\Pump-101|Temperature",
  "type": "Double",
  "defaultUOM": "degC",
  "dataReferencePlugIn": "PI Point",
  "configString": "\\\\PI-SERVER\\PUMP101.TEMP",
  "hasChildren": false
}

EventFrameDto

{
  "webId": "F...",
  "name": "Equipment Failure",
  "description": "Pump tripped due to high temperature",
  "path": "\\\\Server\\Database\\EventFrames\\Equipment Failure",
  "startTime": "2024-01-15T10:00:00Z",
  "endTime": "2024-01-15T11:30:00Z",
  "duration": "01:30:00",
  "templateName": "Equipment Alarm",
  "categoryNames": ["Alarms", "Critical"],
  "severity": "High",
  "isAcknowledged": true,
  "acknowledgedBy": "DOMAIN\\operator",
  "acknowledgedDate": "2024-01-15T10:05:00Z",
  "refElementWebIds": ["E..."],
  "attributes": [ ... ]
}

WriteResultDto

{
  "success": true,
  "affectedCount": 5,
  "errors": []
}

HealthDto

{
  "status": "Healthy",
  "component": "PI Data Archive",
  "details": {
    "serverName": "PI-SERVER",
    "serverVersion": "2018 SP3",
    "connected": true,
    "pointCount": 50000
  }
}

Error Handling

All errors return a consistent JSON structure:

{
  "error": {
    "code": "NotFound",
    "message": "PI Point with WebId 'P...' not found.",
    "details": null
  }
}

HTTP Status Codes

Code Description
200 Success
201 Created (POST)
400 Bad Request - Invalid parameters
401 Unauthorized - Authentication required
403 Forbidden - Insufficient permissions
404 Not Found - Resource doesn't exist
500 Internal Server Error
503 Service Unavailable - PI/AF connection failed

Examples

Get Last Hour of Data for a Point

curl -X GET "http://localhost/api/points/P.../recorded?startTime=*-1h&endTime=*" \
  --ntlm -u :

Get Current Values for Multiple Points

curl -X GET "http://localhost/api/streamsets/value?webIds=P...,P...,P..." \
  --ntlm -u :

Write Values to a Point

curl -X POST "http://localhost/api/points/P.../recorded" \
  -H "Content-Type: application/json" \
  --ntlm -u : \
  -d '[
    {"timestamp": "2024-01-15T10:00:00Z", "value": 42.5, "good": true},
    {"timestamp": "2024-01-15T10:01:00Z", "value": 43.2, "good": true}
  ]'

Create an Event Frame

curl -X POST "http://localhost/api/eventframes" \
  -H "Content-Type: application/json" \
  --ntlm -u : \
  -d '{
    "name": "Maintenance Window",
    "description": "Scheduled pump maintenance",
    "startTime": "2024-01-15T08:00:00Z",
    "refElementWebIds": ["E..."]
  }'

Swagger UI

Interactive API documentation is available at:

http://{host}:{port}/swagger
Product Compatible and additional computed target framework versions.
.NET Framework net48 is compatible.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 136 12/22/2025

## v1.0.0
- Initial release
- Full PI Points data access (recorded, interpolated, plot, summary)
- AF hierarchy navigation (databases, elements, attributes)
- Streams API for unified PI Point and AF Attribute access
- StreamSets API for bulk operations
- Event Frames CRUD operations
- Calculation/expression evaluation
- Templates and Tables support
- Unit of Measure conversions
- Health check endpoints