18/02/2026
Pisys’ motto has always been “do one thing really well', in our case, building a Permit to Work (PTW) system that excels at controlling high-risk work through structured permits, approvals, and visibility of what’s happening right now.
In the real world, permits don’t live in isolation. Asset management platforms, especially IBM Maximo, often hold the operational “source of truth” for maintenance: work orders, locations, assets, job plans, planning status, and historical context.
For one of our clients, the requirement was to integrate Maximo with Pisys PTW so that both systems could provide deeper, more useful information about jobs in progress.
This post explains the problem statement, the integration approach, and a practical reference architecture you can adapt. It also includes an engineering appendix (API shapes, mapping, reliability and security patterns, and text-based sequence diagrams) so you can translate the concept into an implementation plan.
The operational problem we needed to solve
The client’s sites were managing permits across physical areas where multiple activities could be happening at the same time. Two key issues emerged:
1) PTW needed Maximo work-order context at the point of issuing permits
The brief was to allow the permit system to receive data on relevant work orders whenever a permit was raised in a specific area.
This mattered because areas often had multiple work orders in force, and permit issuers needed broad visibility of all activity to make better control-of-work decisions. (Pisys Limited | HSEQ Software)
2) Maximo users needed to see permits in force for the same area
From the Maximo side, when work orders were entered for a specific area, users needed to be able to see the permits in force to avoid conflicts, understand access constraints, and coordinate properly.
Integration strategy
Pisys PTW has a comprehensive API that allows external systems to leverage permit data, but in this case (and with the client’s cooperation), the Maximo API was able to obtain the required work-order data. The API was also able to write PTW related data back toe the required Maximo work order screen.
A Reference architecture
Even when the initial scope is simple (“show work orders in PTW” and “show permit link in Maximo”), the implementation benefits from a clean separation of concerns.
Logical components
- Pisys PTW: permit lifecycle, permit board/area model, approvals, handback/closure.
- IBM Maximo: work orders, locations/assets, planning, execution history.
- Integration layer (recommended): a small service (or iPaaS/ESB) that:
- queries Maximo
- maps identities (area ↔ location)
- applies business rules (what counts as “in force”)
- handles retries/backoff and failure modes
- optionally performs write-back (permit URL on WO)
You can integrate directly system-to-system, but an integration layer tends to reduce coupling and gives you a single place to manage authentication, mapping, observability, and change control.
Data modelling: aligning “Area” between PTW and Maximo
Most integration friction comes down to identity and scope.
Recommended mapping approaches
1. Location-based mapping (common)
- PTW “Area” ↔ Maximo “LOCATION” (and “SITEID” if relevant)
- Works well when Maximo location hierarchies reflect how operations talk about plant areas.
2. Asset-based mapping
- PTW “Area” ↔ one or more Maximo assets; derive location and related WOs from assets.
3. Hybrid mapping
- PTW "Area" maps to a Maximo location plus descendants (e.g., permit for “Boiler House” needs WOs from BH-100, BH-110, BH-120…)
Active/in-force definition
“Work orders in force” and “permits in force” sound obvious, but they require a configuration decision:
• Which Maximo WO statuses count as relevant for the PTW “other activity” view?
• Which permit states count as “in force” for Maximo visibility?
These should be configurable rules, not hard-coded assumptions.
Key integration flows
Flow A — PTW pulls Maximo work orders when a permit is raised in an area
Trigger: permit raised / area selected in PTW.
Outcome: PTW UI shows relevant work orders for that area so issuers have visibility of concurrent activity.
Typical steps:
1. PTW captures selected area.
2. PTW resolves area → Maximo scope key(s) (site + location; optionally include child locations).
3. Integration calls Maximo API to retrieve WOs filtered by scope and “active” statuses.
4. PTW displays a concise, fast list (WO number, description, status, priority, planned window, etc.)
Practical enhancement (high value, low complexity):
• sort by status and planned start time
• show “potential conflicts” indicators (e.g., overlapping windows in same area)
Flow B — Maximo shows permit context (permits in force + permit URL)
Trigger: work order entered/viewed in Maximo for an area.
Outcome: user sees the permit(s) currently in force and can click through to PTW.
• populate the Maximo WO screen with the URL of the specific permit relating to the work order area.
Engineering note: in many environments, a WO can relate to multiple permits over time (or multiple permits can be in force for an area). If that’s likely, consider a “permit links” related record list rather than a single URL field.
Flow C — Create/raise permit from Maximo work order
Two common patterns:
Pattern C1: UI launch (simple and robust)
• Maximo button → opens PTW “new permit” page with WO context passed as query parameters
• PTW pre-populates area, WO reference, description, planned dates
Pattern C2: server-side creation (more automation)
• Maximo/integration service calls PTW API to create a draft permit and returns the new permit URL
• useful if you need strict traceability and guaranteed linkage
Engineering appendix
Everything below is written to be implementation-friendly but also generic enough for a public post. Where exact endpoints differ, treat examples as illustrative.
A. Example API shapes (integration façade)
A1) Query active work orders for a PTW area
GET /areas/{areaId}/workorders?siteId=SITE01&location=BH-100&status=ACTIVE
Example response (projection—only what PTW needs for fast rendering):
{
"areaId": "PTW-AREA-0142",
"maximoScope": { "siteId": "SITE01", "location": "BH-100" },
"workOrders": [
{
"wonum": "152340",
"description": "Replace gland packing on feedwater pump",
"status": "INPRG",
"priority": 2,
"location": "BH-100",
"assetnum": "P-101A",
"schedStart": "2026-02-13T07:00:00Z",
"schedFinish": "2026-02-13T15:00:00Z"
}
],
"refreshedAt": "2026-02-13T09:12:10Z"
}
A2) Write back a permit deep-link to Maximo
POST /workorders/{wonum}/permit-link
Content-Type: application/json
{
"siteId": "SITE01",
"permitId": "PTW-000987",
"permitUrl": "https://ptw.example.com/permits/PTW-000987",
"relationship": "AREA_RELATED"
}
B. Maximo API call patterns (illustrative)
Maximo interfaces vary by deployment and configuration (REST/OSLC/MIF), but the patterns remain consistent:
B1) Work order query by site + location + status
GET /maximo/api/os/workorder
?oslc.where=siteid="SITE01" and location="BH-100" and status in ["APPR","INPRG"]
&oslc.select=wonum,description,status,priority,location,assetnum,schedstart,schedfinish
B2) Permit URL write-back (single field approach)
PATCH /maximo/api/os/workorder/{id}
Content-Type: application/json-patch+json
[
{ "op": "replace", "path": "/ptwurl", "value": "https://ptw.example.com/permits/PTW-000987" }
]
(Again: exact resource names and field identifiers depend on the client’s Maximo configuration.)
C. Field mapping (Maximo work order → PTW permit draft)
Maximo field PTW field Purpose
SITEID Site/Facility scope + tenancy
LOCATION Area primary linkage
ASSETNUM Asset ref (optional) context + isolations
WONUM External reference traceability
DESCRIPTION Work description permit header
SCHEDSTART / SCHEDFINISH Planned window concurrency checks
JOBPLAN / WORKTYPE (if used) Permit type suggestion routing/templates
D. Text sequence diagrams
D1) Permit raised → PTW fetches relevant work orders
PTW User -> PTW UI: Select Area / Start Permit
PTW UI -> PTW API: Save draft permit (area=BH-100)
PTW API -> Integration Service: GET /areas/{areaId}/workorders?status=ACTIVE
Integration Service -> Maximo API: Query WOs by site/location/status
Maximo API -> Integration Service: WO list
Integration Service -> PTW API: Projected WO list + refreshedAt
PTW API -> PTW UI: Render WO panel ("Other activity in this area")
D2) Permit created/issued → write back permit URL to Maximo
PTW API -> Integration Service: POST /workorders/{wonum}/permit-link (permitUrl)
Integration Service -> Maximo API: Update WO field/related record
Maximo API -> Integration Service: Success
Integration Service -> PTW API: Confirm linkage stored
D3) Create permit from work order (UI launch pattern)
Maximo User -> Maximo UI: Click "Create PTW Permit"
Maximo UI -> Browser: Open PTW /permits/new?wonum=152340&location=BH-100&site=SITE01
PTW UI -> PTW API: Create draft permit with prefilled fields
PTW UI -> User: Permit ready for issuer review/approval workflow
E. Security and access control
Because this integration affects control-of-work decisions, treat it as a production integration:
- Dedicated service account in Maximo with least privilege:
- read work orders/locations
- write only the specific link field(s) if required
- Strong credential handling:
- secrets in a vault/secret manager
- rotate keys/tokens
- Transport + network:
- TLS everywhere
- private networking or allow listing where feasible
- Audit + traceability:
- log who/what/when for each query and write-back
- include correlation IDs spanning PTW ↔ integration ↔ Maximo
F. Reliability Engineering: don’t let Maximo downtime block permits
Permits must remain usable even when an external system is degraded.
Recommended patterns:
- Timeouts and bounded latency (don’t let Maximo calls hang the permit UI)
- Retry with backoff for transient failures
- Circuit breaker to prevent cascading failures
- Graceful degradation in PTW:
- show “work order data currently unavailable”
- show the last successful refresh timestamp if cached
- Caching:
- short TTL per area to reduce query bursts during busy issuing windows
- Observability:
- dashboards for latency/error rates per endpoint
- alerting on sustained failure rates