Infor EAM REST API Development: Asset CRUD Operations, Work Order Creation, and Custom Field Extensions
If you are building integrations, automations, or lightweight applications on top of Infor EAM (now rebranded as HxGN EAM), you are working with a platform that has a reasonably mature REST API surface but one that carries some quirks rooted in its legacy SOAP history. This post is written for developers and technical consultants who are already inside the EAM ecosystem and need a clear, honest picture of how the REST API is structured, what the common failure points are, and how to work with custom field extensions without running into the walls that catch most people the first time.
Understanding the EAM API Landscape Before You Write a Single Line of Code
Infor EAM exposes its data through two web service interfaces: a SOAP-based XML interface and a REST-based JSON interface. Both sit on top of what Infor calls the Web Services Facade, which is essentially a middleware layer that translates HTTP requests into the same internal business logic that the EAM application itself uses when a user clicks through the UI.
This architecture means that what the API can and cannot do is constrained by what EAM’s internal screen logic allows. The REST API does not bypass the application’s rules, validations, or required field checks. If a field is mandatory in the EAM user interface for a given screen, it is typically mandatory in the API request for that same entity. This is a critical design point. Developers who come from other REST APIs and expect to POST a minimal JSON body and have the system fill in defaults will run into persistent 400 errors until they understand this.
The REST API is defined in OpenAPI 3 standard. Each endpoint has four distinct parts: the URL, the URL parameters, the request body, and the response. The Swagger UI interface available within your EAM environment lets you explore and test endpoints interactively, which is a useful starting point before you write integration code.
The entity identifier pattern throughout the EAM REST API uses the format entitycode#organizationcode. So an equipment record with code PUMP-001 in the MAINT organization would be referenced as PUMP-001#MAINT in the {id} path parameter. If you miss the organization code, you will get either a 404 or a result from the wrong organization, and this is one of the most common mistakes in early integration development against EAM.
Struggling with Infor EAM REST API quirks, asset CRUD errors, work order creation, or custom field access?
Sama delivers expert REST API development, authentication setup, Dataspy handling, bulk operations, and UDF extensions—ensuring smooth, reliable integrations without frustrating 400s or failures.
Authentication: What Changed and Why It Matters
For cloud deployments of EAM through Infor OS, authentication runs through the ION API Gateway using OAuth 2.0. For backend service integrations, the correct grant type is the Resource Owner (Password Credentials) grant, not the Authorization Code grant. The Authorization Code flow requires a user in a browser to authenticate interactively, which does not work for automated backend processes.
To set up a backend integration, you need to register an Authorized App in Infor ION API, generate a service account, and download the credentials file. That credentials file is a JSON object that contains the following fields you actually need at runtime: the base ION API URL (iu), the SSO token endpoint (pu + ot combined), the OAuth client ID (ci), the client secret (cs), the service account access key (saak), and the service account secret key (sask).
The token request is a standard HTTP POST to the token endpoint with Content-Type set to application/x-www-form-urlencoded. The form body includes grant_type, client_id, client_secret, username (the saak value), and password (the sask value). A successful response gives you an access_token along with an expires_in value. The default token lifetime is two hours, though this can be configured per authorized app in the ION API administration settings.
Once you have the token, every subsequent request to EAM through the ION API Gateway includes the token in the Authorization header as a Bearer token. If the token expires mid-session, you use the refresh_token to obtain a new access_token without requiring the service account credentials again. If no refresh token was issued, you re-authenticate from scratch.
For on-premises EAM deployments where the ION API Gateway is not in the picture, authentication uses a session-based mechanism. You pass username and password in the initial request headers, the server returns a session ID, and you include that session ID in the header of subsequent requests using the session header parameter. The keepSession header parameter, when set to true, keeps the session alive and returns the session ID in each response so you can reuse it.
Part 1: Asset (Equipment) CRUD Operations
The Equipment Endpoint Structure
Equipment records in EAM are the central entity around which everything else is organised. The REST endpoints for equipment follow a consistent pattern:
GET /equipment/{code} retrieves a single equipment record by its code and organization. GET /equipment/list retrieves multiple equipment records, typically used with filter parameters. POST /equipment creates a new equipment record. PUT /equipment/{code} updates an existing record. DELETE /equipment/{code} removes a record.
There is also a separate /equipmentstructure endpoint for managing parent-child equipment hierarchies. POST to /equipmentstructure attaches a child equipment to a parent, and PUT to /equipmentstructure updates an existing structural relationship.
Creating an Equipment Record
When you POST to create a new equipment record, the request body needs to satisfy the field requirements of the default Dataspy associated with the equipment screen. This is one of the genuinely unusual aspects of the EAM API: the Dataspy configuration in the application affects which fields the web service considers required or available. The default Dataspy controls both the fields the web service processes and what it validates. If your EAM administrator has a default Dataspy that includes custom columns, those fields may need to be present in your API request.
The minimum required fields for a standard equipment POST include the equipment code, the organization, the equipment category (the type classification such as A for asset, P for position, S for system, and so on), and the description. The category code drives which subsidiary tabs and fields are relevant for the equipment, which is why you cannot create a meaningful equipment record without it.
A typical minimal POST body for equipment creation in JSON format includes the equipment code as a string, the organization code, the equipment type code, a description, and the class code if your EAM environment has classes configured as required. Department and location codes are commonly required depending on your organisation’s EAM configuration.
The response for a successful equipment creation returns a 200 status code with a result body that includes a ResultStatus, a ResultMessage element, and a ResultData element containing the created record’s details. If the ResultStatus is not null and indicates an error, the transaction did not complete. If ResultMessage contains a question string rather than an error, it means EAM needs confirmation to proceed, and you need to resubmit the request with a confirm flag set to true.
Reading Equipment Records
GET /equipment/{code} with the entity ID in the format EQUIPCODE#ORGCODE returns the full record for a single equipment item. The response follows the same three-part structure: ResultStatus, ResultMessage, and ResultData containing the equipment fields.
For bulk retrieval, GET /equipment/list supports filter and sorting parameters. The list endpoint returns a collection of records, and like all list operations in EAM, it supports pagination through cursor position and row count parameters. The cursor position starts at 1. If you want to page through results in batches of 50, you set rowCount to 50 and cursor to 1 for the first batch, then cursor to 51 for the next, and so on.
One thing to plan for in advance: the EAM REST API list endpoints return the columns that are in the default Dataspy for the associated grid, not all available fields. If you need a field that is not in the default Dataspy, either the EAM administrator needs to add it to the default Dataspy, or you need to use a Grid Request to query the data through the grid web service instead.
Updating Equipment Records
PUT /equipment/{code} updates an existing equipment record. The request body for an update follows the same structure as creation, but you only need to include the fields you want to change, along with the entity identifier and organization. Fields not included in the PUT body retain their existing values. This is different from some REST APIs where a PUT is a full replacement. In EAM’s REST implementation, PUT behaves more like a PATCH in that it only updates the fields you provide.
One practical issue worth noting: if an equipment record has revision control activated, the PUT endpoint will not allow direct updates. In that case, changes must go through the equipment revision workflow, which requires creating a revision record, making changes through the revision entity, and submitting the revision for approval before changes take effect. This is a workflow consideration that needs to be built into your integration logic if revision control is in use in your environment.
Deleting Equipment Records
DELETE /equipment/{code} removes an equipment record. EAM enforces referential integrity checks before allowing deletion. If the equipment has associated work orders, PM schedules, parts, or other linked records that are not in a closed or cancelled status, the delete request will return an error indicating the equipment cannot be removed due to existing dependencies. This means your integration code needs to handle the deletion dependency scenario explicitly, either by checking for active linked records first or by handling the error gracefully and routing it to a process that resolves those dependencies before retrying.
Struggling with Infor EAM REST API quirks, asset CRUD errors, work order creation, or custom field access?
Sama delivers expert REST API development, authentication setup, Dataspy handling, bulk operations, and UDF extensions—ensuring smooth, reliable integrations without frustrating 400s or failures.
Part 2: Work Order Creation
Work Order Endpoint Overview
The work order endpoints in EAM are more complex than the equipment endpoints because work orders have several related entities: activities, labor bookings, parts, and costs, all of which are managed through separate but related endpoints.
The primary endpoint structure for work orders:
POST /workorders creates a new work order. GET /workorders/{number} retrieves a single work order. PUT /workorders/{number} updates a work order. DELETE /workorders/{number} deletes a work order.
Bulk operations exist at /workorders/list for all four methods, allowing you to process multiple work orders in a single API call.
For activities within a work order: GET, POST, and PUT at /workorders/activities/{number} manage activity lines. For labor bookings: GET and POST at /workorders/laborbookings/{number} manage labor time entries.
Fields Required for Work Order Creation
Creating a work order through the API follows the same logic as creating one in the application. At minimum, you need the work order organization, the work order type (corrective, preventive, and so on), the status code, the description, and the equipment code with its organization. The department and reported by fields are typically required as well, depending on your EAM configuration.
The status code on creation deserves attention. Most EAM environments are configured so that newly created work orders start in a specific status such as R (Requested) or D (Draft) before moving through an approval or scheduling workflow. If you POST a work order with a status that requires additional fields, the request will fail. It is common to create work orders via API in the R status and let the EAM workflow handle subsequent status transitions.
The work order type code determines which fields are applicable. A corrective maintenance work order, a preventive maintenance work order, and an inspection work order each carry different required and optional fields. Sending a field that is not applicable for a given work order type does not necessarily cause an error, but it may be silently ignored, which can create confusion during troubleshooting.
Creating Work Order Activities
Activities are the task lines within a work order. Once a work order is created, you POST to /workorders/activities/{number} to add activity lines. Each activity requires the work order number, the activity number (a sequential integer within that work order), a description, and the trade or craft code that will perform the activity.
Activities are how EAM tracks labor requirements and actual labor time against a work order. The estimated hours field on an activity establishes the planned labour cost, while the actual hours are recorded through labor bookings. If your integration needs to close out work orders programmatically, activities typically need to be completed before the work order status can move to a completed state.
Creating Labor Bookings
Labor bookings are posted to /workorders/laborbookings/{number} and represent actual time charged to a work order activity. Each booking requires the work order number, the activity number, the employee or crew code, the trade code, the date the work was performed, and the hours booked.
In environments using Infor EAM with time-and-attendance integrations or external maintenance scheduling systems, labor bookings are the primary data point that flows back into EAM from those systems. Automating labor booking creation through the API eliminates the manual entry that otherwise requires technicians to log back into EAM after completing work.
Bulk Work Order Creation
POST /workorders/list allows you to create multiple work orders in a single request. The request body is an array of work order objects, each with the same structure as a single creation request. This is significantly more efficient than sequential single-record creates when you are generating planned maintenance work orders from an external scheduling system or migrating historical work orders from a legacy system.
Bulk requests in EAM do not follow all-or-nothing transaction semantics. A request with ten work orders where three fail will create the seven that were valid and return error details for the three that failed. Your integration logic needs to handle partial success by inspecting the response array and routing the failed records to an error queue or retry mechanism.
Part 3: Custom Field Extensions
How EAM Handles Custom Fields
Infor EAM provides two distinct mechanisms for extending record structures with organisation-specific data: User Defined Fields (UDFs) and custom fields configured through the Screen Designer.
User Defined Fields are pre-allocated columns in EAM’s underlying database tables. These are fixed columns with names like UDF1, UDF2, and so on, which can be relabelled and configured through the EAM administration interface. The Enable UDF for Add-ons checkbox on each UDF configuration makes those fields accessible to external systems including the REST API. The Print UDF on Supported Reports checkbox makes them available in report templates.
The fact that UDFs are fixed database columns rather than dynamically added columns has a practical implication for API development: UDF values are retrieved and updated in the same API request as the standard fields, not in separate calls. This makes integrations simpler to build compared to platforms where custom attributes are managed as key-value pairs in a separate API call.
Reading UDF Values Through the REST API
When you retrieve an equipment record or work order through GET, the response includes UDF fields in the same ResultData object as the standard fields, provided those fields are included in the default Dataspy for the relevant screen. If a UDF field is not appearing in your GET response, the first thing to check is whether it is included in the default Dataspy, not whether the API supports it.
The internal names of UDF fields in the API request and response bodies correspond to the column names in the EAM database, not the display labels configured in the UI. An administrator may have relabelled UDF1 as “Safety Classification” in the user interface, but in your API request body and response, it will still appear as the underlying UDF field identifier. You can identify the correct API field names by using the EAM Swagger interface to inspect the schema of the endpoint response, or by working with an EAM administrator who has access to the screen configuration.
Writing UDF Values
To set UDF values when creating or updating a record, include the UDF field in the standard request body alongside the core fields. The write behaviour follows the same rules as standard fields: for a PUT request, only the fields you include are updated. For a POST, any UDFs you do not include will default to their configured default values or remain empty.
UDF fields configured with a dropdown list of options validate that the value you submit is in the allowed list. Submitting a value not in the list returns a 400 error with a message indicating the invalid value. If you are integrating data from an external system where the option values may not match exactly, you need to implement a mapping layer that translates external codes to EAM’s allowed UDF values before the API call.
Grid Requests as an Alternative for Complex Queries
When you need to query records using UDF values as filter criteria, the standard GET endpoints may not be flexible enough. This is where EAM’s Grid Request capability becomes important. Grid Requests allow you to query any EAM grid with filters, sorting, pagination, and field selection configured programmatically.
A Grid Request is a POST to /grids/{gridName}/data where the request body includes the grid name, the Dataspy ID to use (or omit to use the default), filter conditions, sort specifications, and pagination parameters.
Filters in a Grid Request use the internal column name, an operator, and a value. The internal column name for a UDF field is the field’s database column name, the same identifier used in the standard endpoints. The available filter operators include equals, contains, starts with, ends with, is empty, is not empty, and comparison operators for numeric and date fields.
Pagination in Grid Requests uses rowCount to set the page size and cursorPosition to set the starting row. The first page is cursor position 1. After receiving a page of results, the next call uses cursor position 1 plus the rowCount of the previous page. This cursor-based pagination is not offset-based in the traditional sense; the cursor position in EAM represents the row number in the result set, and you need to track it explicitly in your integration code.
Screen Designer and Custom Tabs
Beyond UDFs, EAM’s Screen Designer allows administrators to add custom tabs to equipment, work order, and other screens. These custom tabs can hold fields that map to columns in custom database tables created specifically for your organisation. The REST API exposure of custom tab data depends on whether those tabs and their fields have been configured through the EAM add-on framework, which requires the Enable UDF for Add-ons configuration at the field level.
Not all Screen Designer customisations are automatically available through the REST API. If your EAM environment has custom screens or tabs that you need to integrate with externally, the safest approach is to use the Grid Request interface to query the data from those custom screens’ underlying grids rather than assuming the standard CRUD endpoints will include those fields. This is the approach that organisations like CERN have used when extending EAM for highly customised environments: use the standard API for standard entities and Grid Requests for everything that falls outside the default field set.
Struggling with Infor EAM REST API quirks, asset CRUD errors, work order creation, or custom field access?
Sama delivers expert REST API development, authentication setup, Dataspy handling, bulk operations, and UDF extensions—ensuring smooth, reliable integrations without frustrating 400s or failures.
Error Handling and Response Codes
The EAM REST API returns four status codes: 200 for success, 400 for a request error (bad input, missing required fields, validation failure), 404 for a record not found, and 500 for a server-side error.
The 200 response does not always mean the transaction completed successfully. EAM uses the ResultStatus field within the response body to communicate outcome. A null ResultStatus means the transaction completed without issues. A non-null ResultStatus with an error message means the request was understood but rejected by the application logic. A non-null ResultMessage with a question string means the operation needs confirmation to proceed.
This confirmation mechanism catches many developers off guard. For example, deleting an equipment record that has historical work orders may return a question asking you to confirm that you want to proceed despite the history. Your integration code needs to detect this pattern, where ResultMessage contains a question and ResultStatus is null, and resubmit the request with the confirmation parameter set to true.
Error messages in EAM’s REST responses are plain text strings that match what a user would see in the application UI. They are descriptive enough to understand what validation failed, but they are not structured error codes. You cannot reliably parse them programmatically with a finite list of known codes the way you can with some other enterprise APIs. Write your error handling to log the full ResultMessage for diagnosis rather than branching on specific message content.
Integration Architecture Considerations
When building integrations against EAM’s REST API for production use, a few architectural decisions matter more than the individual API calls themselves.
Session management for high-volume integrations is the first consideration. If your integration makes hundreds of API calls during a batch window, managing tokens and sessions efficiently matters. For cloud deployments, use the OAuth refresh token mechanism rather than re-authenticating on every call. For on-premises deployments with session-based auth, use the keepSession flag and reuse session IDs across a batch to avoid the overhead of repeated authentication handshakes.
The EAM Dataspy dependency is the second consideration. Any integration that depends on specific fields being returned in list or grid responses is implicitly dependent on the Dataspy configuration in the EAM environment. This means a change to the default Dataspy by an EAM administrator can break an integration that was working correctly. Either document and lock the Dataspy configurations your integrations depend on, or build your integrations to use the single-record GET endpoint which returns a more complete field set rather than the list endpoint whose fields vary with Dataspy.
Bulk operations versus single record operations is the third consideration. For data migration, historical record loading, or any scenario where you are creating or updating hundreds or thousands of records, use the bulk /list endpoints rather than looping over single-record endpoints. The performance difference is substantial, and bulk endpoints are specifically designed for this workload. That said, plan for partial success handling because bulk requests do not roll back on partial failure.
If your organisation runs both Infor EAM and Infor CloudSuite or Infor LN, integrating them through Infor ION using BOD-based messaging is typically more maintainable than direct REST-to-REST calls between systems for core data like assets and maintenance records. ION provides a reliable message queue with retry logic, whereas direct REST calls require you to implement that resilience yourself. The REST API is better suited for real-time lookups, mobile applications, or external system integrations where ION is not available or appropriate.
What the Deprecated Endpoints Mean for Your Environment
Infor has been gradually deprecating older endpoint patterns in the EAM web services with each major release. If you are running an EAM environment that has custom integrations built several years ago, it is worth auditing which endpoints those integrations use. The Swagger interface in your environment marks deprecated endpoints clearly. Deprecated endpoints remain in the Swagger interface for backward compatibility but Infor explicitly recommends against building new functionality against them.
On the ION API side, the EAM ION API Swagger documentation (accessible through the Hexagon documentation portal) provides a separate API surface that is structured differently from the native EAM web services. The ION API version of EAM endpoints is the preferred path for integrations running through Infor OS, as it handles authentication, throttling, and routing through the gateway rather than going directly to the EAM application server.
Practical Starting Points
The most efficient way to validate your API setup before writing integration code is to use Postman. With the IONAPI credentials file from your EAM authorized app registration, you can configure a Postman environment with the token endpoint and credentials, set up OAuth 2.0 authentication with the password credentials grant type, and make your first EAM REST calls within an hour. CERN’s open-source EAM Web Services Hub, published under GPL v3 on GitHub, is also worth reviewing if your environment has heavy customisation needs. It provides a developer-friendly REST and SOAP layer on top of the standard EAM API that simplifies some of the complexities around Dataspy dependencies and session management for developers who are building applications rather than one-off integrations.
For organisations running Infor EAM / HxGN EAM alongside other Infor products, our team at SAMA has hands-on experience building and troubleshooting integrations across the full Infor stack. Whether the challenge is a bulk data migration, a real-time mobile field application, or a bi-directional sync between EAM and a third-party SCADA or GIS system, the patterns described here are the foundation for all of it. If you have specific integration scenarios to work through, get in touch with us and we can walk through the right approach for your environment.