This is the mapping of PlantPulse API REST endpoints and client methods. The base path is /api/v5.
Authentication: Since the api_key is automatically issued and managed when calling APIClient_V5.connect(), there are no authentication endpoints that users must call directly.
17.1 System
| HTTP | Endpoint | Method |
|---|
| GET | /api/v5/ping | client.system().ping() |
17.2 ID Issuance
| Method | Path | Description |
|---|
| POST | /api/v5/domain-ids | Pre-receive Domain ID (No client method) — ID Rules |
17.3 Site (6)
| HTTP | Endpoint | Method |
|---|
| POST | /api/v5/site | client.site().create(req) |
| PUT | /api/v5/site/{id} | client.site().update(id, req) |
| DELETE | /api/v5/site/{id} | client.site().delete(id) |
| GET | /api/v5/site/{id} | client.site().get(id) |
| GET | /api/v5/site | client.site().list() |
| GET | /api/v5/site/{id}/exists | client.site().exists(id) |
17.4 OPC (10)
| HTTP | Endpoint | Method |
|---|
| POST | /api/v5/opc | client.opc().create(req) |
| PUT | /api/v5/opc/{id} | client.opc().update(id, req) |
| DELETE | /api/v5/opc/{id} | client.opc().delete(id) |
| GET | /api/v5/opc/{id} | client.opc().get(id) |
| GET | /api/v5/opc | client.opc().list() |
| GET | /api/v5/opc?site_id={id} | client.opc().listBySite(siteId) |
| GET | /api/v5/opc?opc_source_type={type} | client.opc().listByType(sourceType) |
| GET | /api/v5/opc/{id}/exists | client.opc().exists(id) |
| GET | /api/v5/opc/count | client.opc().count() |
| GET | /api/v5/opc/count?site_id={id} | client.opc().countBySite(siteId) |
17.5 Asset (6)
| HTTP | Endpoint | Method |
|---|
| POST | /api/v5/asset | client.asset().create(req) |
| PUT | /api/v5/asset/{id} | client.asset().update(id, req) |
| DELETE | /api/v5/asset/{id} | client.asset().delete(id) |
| GET | /api/v5/asset/{id} | client.asset().get(id) |
| GET | /api/v5/asset | client.asset().list() |
| GET | /api/v5/asset/{id}/exists | client.asset().exists(id) |
Relationship Ontology (4)
These are distinct directional relationships separate from the hierarchy (parent-child). They are used to answer, "If this equipment stops, what else is affected?"
| HTTP | Endpoint | Function |
|---|
| POST | /api/v5/assets/{asset_id}/relations | Register relationship — Body {site_id, to_entity_type, to_entity_id, relation_type, description?} → 201 |
| GET | /api/v5/assets/{asset_id}/relations?type= | Direct relationship list (Inbound/Outbound) |
| DELETE | /api/v5/relations/{relation_id} | Delete relationship → 204 |
| GET | /api/v5/ontology/graph/{entity_id}?relation=&direction=DOWN&depth=2 | Graph traversal (BFS) |
| Relationship | Meaning | Direction |
|---|
FEEDS | Process flow | Asset → Asset |
DEPENDS_ON | Utility dependency (Power, Air, Cooling) | Asset → Asset |
PRODUCES | Production output | Asset → Product |
direction corresponds to UP, DOWN, BOTH (default DOWN), and depth is 1~5 (default 2).
- Relationships pointing to themselves are not stored, and relationships with the same combination are registered only once.
- Registration and deletion are considered changes, so ADMIN/API roles and audit logs are applied.
- When an AI assistant performs the same traversal, it is the
trace_asset_relations of MCP.
QR Label
| HTTP | Endpoint | Function |
|---|
| GET | /api/v5/asset/qr/{token} | Equipment associated with label token. Returns 404 if the token is invalid or an old re-issued token. |
The address contained in the label is the qr_payload of the GET /api/v5/asset/{id} response. Since this call does not create a token, it will be "" if the token does not exist or if there is no PP_UI_CONSOLE_URL. Public pages without login are provided by /qr/{token}, not V5 — QR Labels and Public Pages.
17.6 Tag (23)
CRUD + List
| HTTP | Endpoint | Method |
|---|
| POST | /api/v5/tag | client.tag().create(req) |
| PUT | /api/v5/tag/{id} | client.tag().update(id, req) |
| DELETE | /api/v5/tag/{id} | client.tag().delete(id) |
| GET | /api/v5/tag/{id} | client.tag().get(id) |
| GET | /api/v5/tag/{id}/exists | client.tag().exists(id) |
| GET | /api/v5/tag | client.tag().list() |
| GET | /api/v5/tag?site_id={id} | client.tag().listBySite(siteId) |
| GET | /api/v5/tag?opc_id={id} | client.tag().listByOpc(opcId) |
| GET | /api/v5/tag?asset_id={id} | client.tag().listByAsset(assetId) |
| GET | /api/v5/tag/count | client.tag().count() |
| GET | /api/v5/tag/count?site_id={id} | client.tag().countBySite(siteId) |
| GET | /api/v5/tag/count?opc_id={id} | client.tag().countByOpc(opcId) |
| GET | /api/v5/tag/count?asset_id={id} | client.tag().countByAsset(assetId) |
PATCH (10 — Partial updates by tab)
| HTTP | Endpoint | Method |
|---|
| PATCH | /api/v5/tag/{id}/basic | patchBasic(id, req) |
| PATCH | /api/v5/tag/{id}/alarm | patchAlarm(id, req) |
| PATCH | /api/v5/tag/{id}/metadata | patchMetadata(id, req) |
| PATCH | /api/v5/tag/{id}/calculation | patchCalculation(id, req) |
| PATCH | /api/v5/tag/{id}/sampling | patchSampling(id, req) |
| PATCH | /api/v5/tag/{id}/aggregation | patchAggregation(id, req) |
| PATCH | /api/v5/tag/{id}/ai | patchAi(id, req) |
| PATCH | /api/v5/tag/{id}/publish | patchPublish(id, req) |
| PATCH | /api/v5/tag/{id}/attribute | patchAttribute(id, req) |
| PATCH | /api/v5/tag/{id}/link | patchLink(id, req) |
17.7 Alarm (3)
| HTTP | Endpoint | Method |
|---|
| GET | /api/v5/alarm/{seq} | client.alarm().get(seq) |
| GET | /api/v5/alarm?limit={n} | client.alarm().list(limit) |
| GET | /api/v5/alarm/performance?scope_type=&scope_id= | Alarm system performance (No client method) |
/alarm/performance — scope_type are SITE, AREA, LINE, and scope_id is either the Site ID or Asset ID; both are required. The period is either days (1~31, default 7) or from + to (used together, up to 31 days), and from/to takes precedence over days. Only acknowledged occurrences are counted; those opened during hidden or suppressed states appear separately in suppression. Incorrect range or period will result in a 400 error. The same values are returned by MCP get_alarm_performance.
17.8 Order (11)
| HTTP | Endpoint | Method |
|---|
| POST | /api/v5/order | client.order().create(req) |
| PUT | /api/v5/order/{id} | client.order().update(id, req) |
| DELETE | /api/v5/order/{id} | client.order().delete(id) |
| GET | /api/v5/order/{id} | client.order().get(id) |
| GET | /api/v5/order | client.order().list() |
| GET | /api/v5/order/{id}/exists | client.order().exists(id) |
| POST | /api/v5/order/{id}/start | client.order().start(id) |
| POST | /api/v5/order/{id}/end | client.order().end(id) |
| POST | /api/v5/order/{id}/pause | client.order().pause(id) |
| POST | /api/v5/order/{id}/resume | client.order().resume(id) |
| POST | /api/v5/order/{id}/abort | client.order().abort(id) |
17.8.1 Maintenance Order
These are calls, repairs, and preventive maintenance tasks for equipment (ISA-95 maintenance work order). They are different objects from production work orders (/order) and are called via REST without client methods.
| HTTP | Endpoint | Function |
|---|
| GET | /api/v5/maintenance-orders | List. Filter by scope+scope_id(asset · line · area · site) · status_code · open · maintenance_kind_code · assignee_employee_id · failure_mode_code · maintainable_item_code · from/to · period_of · overdue · external_system · external_id. Page page · limit(default 50, max 500) · sort · order |
| GET | /api/v5/asset/{asset_id}/maintenance-orders | List for a single piece of equipment |
| POST | /api/v5/asset/{asset_id}/maintenance-orders | Add maintenance call |
| GET | /api/v5/maintenance-orders/{maintenance_order_id} | Single record |
| PATCH | /api/v5/maintenance-orders/{maintenance_order_id} | Edit content |
| POST | /api/v5/maintenance-orders/{maintenance_order_id}/transition | Move status (Received · Start · Complete · Cancel). Body status_code · version, cancel uses cancel_reason_code |
| GET | /api/v5/maintenance-orders/{maintenance_order_id}/revisions | Judgment history |
| GET | /api/v5/maintenance-orders/summary | Maintenance summary for range/period |
| GET | /api/v5/maintenance-orders/options | Valid types, statuses, and codes |
| GET | /api/v5/maintenance-orders/board | Maintenance dashboard for range |
| GET | /api/v5/maintenance-orders/changes | Change feed (cursor) for CMMS synchronization |
| GET · PUT | /api/v5/maintenance-orders/by-external/{system}/{external_id} | Find by external (CMMS) number · Idempotent write |
| GET · PUT | /api/v5/maintenance-orders/by-external?system=&external_id= | Same as above, when / exists for the number |
| POST · GET | /api/v5/maintenance-orders/{maintenance_order_id}/attachments | Upload photos · List |
| GET | /api/v5/maintenance-orders/{maintenance_order_id}/attachments/{maintenance_attachment_seq}/content | Photo content |
Maintenance Order Fields
Field names are consistent across responses, request bodies, and list queries.
| Field | Type | Meaning |
|---|
maintenance_order_id | String | MAINTENANCE_ORDER_000001. Old rows use numeric strings ("12") |
maintenance_kind_code | String | Maintenance type (CORRECTIVE …) |
status_code | String | Status (REQUESTED · ACCEPTED · IN_PROGRESS · COMPLETED · CANCELLED) |
cancel_reason_code | String | Cancellation reason |
failure_record_seq | Number | Linked failure record |
maintenance_plan_id · maintenance_plan_name | String | Preventive maintenance plan. MAINTENANCE_PLAN_000001 or old numeric string |
failure_mode_code · failure_mechanism_code · failure_cause_code · maintainable_item_code | String | ISO 14224 code. Display name uses _name instead of _code |
cause_code | String | Cause dictionary code (same dictionary as alarms) |
checklist_results[].maintenance_attachment_seq | Number | Photo of inspection item |
CMMS Webhook
If an address is entered in the configuration key PP_MAINTENANCE_WEBHOOK_URL, a JSON is sent via POST whenever the maintenance order status changes (Call · Received · Start · Complete · Cancel). It is not sent when only the content is edited; if left blank, it is disabled. If it fails, the diagnostics diagnostic.maintenance.webhook_failed turns on and turns off upon the next success; it is not resent.
| Key | Value |
|---|
text | Single sentence in installation language |
event | maintenance.requested · maintenance.accepted · maintenance.in_progress · maintenance.completed · maintenance.cancelled |
maintenance_order_id | Maintenance Order ID (String) |
asset_id · asset_name | Equipment |
maintenance_kind_code · status_code | Type · Status |
description · failure_mode_code | Description · Failure mode |
requested_by · accepted_by · assignee_employee_id | Personnel |
cancel_reason_code | Cancellation reason |
external_system · external_id · owner | External number and owner |
anomaly_found · checklist_results | Inspection anomaly status and answer (item_id · checked · value · maintenance_attachment_seq · out_of_range) |
maintenance_plan_id · plan_due_at | Preventive maintenance plan |
at · version | Time of status change (epoch ms) · Judgment |
Keys with unknown values are still included as null.
17.9 Calendar (6)
| HTTP | Endpoint | Method |
|---|
| POST | /api/v5/calendar | client.calendar().create(req) |
| PUT | /api/v5/calendar/{id} | client.calendar().update(id, req) |
| DELETE | /api/v5/calendar/{id} | client.calendar().delete(id) |
| GET | /api/v5/calendar/{id} | client.calendar().get(id) |
| GET | /api/v5/calendar | client.calendar().list() |
| GET | /api/v5/calendar/search?from={iso}&to={iso} | client.calendar().search(from, to) |
17.10 Customer (8)
| HTTP | Endpoint | Method |
|---|
| POST | /api/v5/customer | client.customer().create(req) |
| PUT | /api/v5/customer/{id} | client.customer().update(id, req) |
| DELETE | /api/v5/customer/{id} | client.customer().delete(id) |
| GET | /api/v5/customer/{id} | client.customer().get(id) |
| GET | /api/v5/customer | client.customer().list() |
| GET | /api/v5/customer?site_id={id} | client.customer().listBySite(siteId) |
| GET | /api/v5/customer/{id}/exists | client.customer().exists(id) |
| GET | /api/v5/customer/count | client.customer().count() |
17.11 Employee (7)
| HTTP | Endpoint | Method |
|---|
| POST | /api/v5/employee | client.employee().create(req) |
| PUT | /api/v5/employee/{id} | client.employee().update(id, req) |
| DELETE | /api/v5/employee/{id} | client.employee().delete(id) |
| GET | /api/v5/employee/{id} | client.employee().get(id) |
| GET | /api/v5/employee | client.employee().list() |
| GET | /api/v5/employee/{id}/exists | client.employee().exists(id) |
| GET | /api/v5/employee/count | client.employee().count() |
17.12 Product (7)
| HTTP | Endpoint | Method |
|---|
| POST | /api/v5/product | client.product().create(req) |
| PUT | /api/v5/product/{id} | client.product().update(id, req) |
| DELETE | /api/v5/product/{id} | client.product().delete(id) |
| GET | /api/v5/product/{id} | client.product().get(id) |
| GET | /api/v5/product | client.product().list() |
| GET | /api/v5/product/{id}/exists | client.product().exists(id) |
| GET | /api/v5/product/count | client.product().count() |
17.13 Path (2)
| HTTP | Endpoint | Method |
|---|
| GET | /api/v5/path/asset/{id} | client.path().getByAsset(assetId) |
| GET | /api/v5/path/tag/{id} | client.path().getByTag(tagId) |
17.14 Flow (3)
| HTTP | Endpoint | Method |
|---|
| GET | /api/v5/flow/{id} | client.flow().get(flowId) |
| GET | /api/v5/flow | client.flow().list() |
| GET | /api/v5/flow/{id}/node | client.flow().listNodes(flowId) |
17.15 Statistics
The numbers below count only paths that have plantpulse-api client methods.
| Domain | Endpoint Count |
|---|
| System | 1 |
| Site | 6 |
| OPC | 10 |
| Asset | 6 |
| Tag | 23 (CRUD 5 + List 7 + Count 4 + PATCH 10) |
| Alarm | 2 |
| Order | 11 (CRUD 6 + Lifecycle 5) |
| Calendar | 6 |
| Customer | 8 |
| Employee | 7 |
| Product | 7 |
| Path | 2 |
| Flow | 3 |
| Total | 92 (+Auth 1) |
17.16 HTTP Method Distribution
| HTTP | Count | Usage |
|---|
| GET | 56 | Query (Single/List/Existence/Count) |
| POST | 16 | Registration + Order Lifecycle |
| PUT | 10 | Full Update |
| PATCH | 10 | Tag partial update by tab |
| DELETE | 10 | Deletion |
17.17 Read List to End — Cursor
GET /api/v5/site, /product, /customer, and /employee use cursors for sequential reading. Page size limit is 100 by default, with a maximum of 1000 (values exceeding this are capped at 1000). Do not include cursor in the first call.
curl -H "X-API-Key: $TOKEN" "$BASE/api/v5/site?limit=500"
curl -H "X-API-Key: $TOKEN" "$BASE/api/v5/site?limit=500&cursor=<next_cursor>"
{
"data": [ ],
"meta": {
"status": "OK",
"pagination": { "limit": 500, "total": 1234 },
"cursor": { "next_cursor": "…", "has_more": true, "limit": 500 }
},
"errors": null
}
data is the array of rows for this page.
meta.pagination.total is the total count for the same filter.
- Pass
next_cursor exactly as is into the cursor of the next call until meta.cursor.has_more becomes false.
- Cursors are bound to that specific list and filter. Using a cursor from a different list or changing
site_id in the call will result in a 422 E1002 error.
- Customers, products, and employees are ordered by ID; sites are ordered by Name and ID. Rows are not missed even if modified during reading.
The list() of the Java client does not pass cursor and therefore returns only the first page. Use REST calls to read until the end.
17.18 Receive Only When Changed — ETag of /tag/export
GET /api/v5/tag/export provides tags for the site, connection, or the entire plant at once. Filter by site_id and opc_id; if include=config is used, configurations are included for each row (eliminating the need to call settings for every tag). The response is data = {tags: [...], count: N}.
Store the ETag of the response and return it as If-None-Match during the next read.
curl -i -H "X-API-Key: $TOKEN" "$BASE/api/v5/tag/export?site_id=SITE_000001&include=config"
curl -i -H "X-API-Key: $TOKEN" -H 'If-None-Match: "<SHA-256>"' \
"$BASE/api/v5/tag/export?site_id=SITE_000001&include=config"
ETag is the SHA-256 of the exported data. The value changes if anything visible in this response changes — such as changes to tags or settings, addition/deletion of tags, or a connection moving to another site — regardless of who made the change. If unchanged, the value remains the same even after a restart or when read from a different node.
- Weak formats
W/"…" and * added by proxies are also accepted.
- 304 only saves transmission and parsing; it does not save the read operation. The server reads all rows to calculate the value. Do not call more frequently than the required data update cycle.
KOPENS All rights reserved.