IFS Cloud is a unified cloud ERP platform purpose-built for asset-intensive industries: aerospace and defense, energy and utilities, construction, and manufacturing. Unlike traditional ERP systems that bolt on industry modules, IFS was architecturally designed around complex asset management, MRO (maintenance, repair, and overhaul), and field service management from the ground up. The REST API is built on top of the IFS OData Provider, which exposes business entities through "projections" — groupings of entity sets, actions, and functions deployed as OData v4 services. This card covers IFS Cloud releases 24R2 and 25R1. [src1, src4, src6]
| Property | Value |
|---|---|
| Vendor | IFS |
| System | IFS Cloud 24R2 / 25R1 |
| API Surface | REST (OData v4 Projections) |
| Current API Version | Release-based (24R2, 25R1) |
| Editions Covered | Single unified platform (all modules) |
| Deployment | Cloud (SaaS) / Customer-Managed Cloud |
| API Docs | IFS Cloud API Explorer |
| Status | GA |
| API Surface | Protocol | Best For | Max Records/Request | Rate Limit | Real-time? | Bulk? |
|---|---|---|---|---|---|---|
| OData Projections (REST) | HTTPS/JSON (OData v4) | CRUD operations, queries, actions on business entities | Configurable via $top (server-enforced max varies) | Fair-use throttling (not published) | Yes | Partial (paged) |
| Premium APIs | HTTPS/JSON (OData v4) | Stable integration endpoints with compatibility guarantees | Same as projections | Shared with projections | Yes | Partial (paged) |
| Entity Service APIs | HTTPS/JSON (OData v4) | Simplified CRUD on core business entities (24R2+) | Same as projections | Shared with projections | Yes | Partial (paged) |
| IFS Connect (Service Bus) | SOAP/XML, REST | Event-driven outbound, message routing, transformation | N/A (message-based) | Configuration-dependent | Async | Yes (batched messages) |
| SOAP (Legacy) | SOAP/XML | Legacy integrations, BPEL workflows | N/A | Shared | Yes | No |
| File-based (EDI/Flat files) | Various | Bulk data import/export, EDI transactions | N/A | N/A | No | Yes |
| Limit Type | Value | Applies To | Notes |
|---|---|---|---|
| Max records per query page | Server-enforced (typically 1,000-5,000) | OData Projections | Use $top and $skip for pagination; server may cap $top lower than requested |
| Max request body size | Infrastructure-dependent (typically 10-50 MB) | REST API | Governed by IIS/reverse proxy configuration |
| Max $expand depth | 2-3 levels (projection-dependent) | OData Projections | Deep expansions degrade performance; prefer multiple targeted queries |
| Max $filter complexity | No documented limit | OData Projections | Complex filters with many OR conditions may timeout |
| OData $batch support | Supported | OData Projections | Batch multiple operations in a single HTTP request |
| Limit Type | Value | Window | Edition Differences |
|---|---|---|---|
| API request rate | Fair-use throttling (not publicly documented) | Per-session / per-tenant | No edition differences — single platform |
| Concurrent API sessions | Not publicly documented | Per-tenant | Managed by IFS IAM |
| IFS Connect message throughput | Configuration-dependent | Per-instance | Depends on message queue sizing |
| Session timeout | Configurable (default varies by flow) | Per-session | OAuth tokens have configurable expiry |
IFS Cloud exclusively uses OAuth 2.0 via IFS Identity and Access Manager (IFS IAM). No API keys, basic authentication, or other methods are supported. [src3]
| Flow | Use When | Token Lifetime | Refresh? | Notes |
|---|---|---|---|---|
| OAuth 2.0 Client Credentials | Server-to-server integrations, no user context | Configurable (typically 1-2h) | New token per expiry cycle | Recommended for all automated integrations; uses service account |
| OAuth 2.0 Authorization Code | User-context operations, interactive integrations | Configurable (typically 1-2h) | Yes (with offline_access scope) | User authenticates via IFS IAM login page; requires redirect URI |
| OAuth 2.0 ROPC | Legacy integrations that cannot redirect to browser | Configurable | Yes | Highly discouraged — sends credentials directly; no MFA support |
START — User needs to integrate with IFS Cloud
|-- What's the integration pattern?
| |-- Real-time (individual records, <1s)
| | |-- Data volume < 500 records/operation?
| | | |-- YES --> OData Projection REST API: direct CRUD
| | | |-- NO --> OData $batch + chunking with rate limit handling
| | |-- Need to execute business logic (release WO, approve PO)?
| | | |-- YES --> OData Actions on projection endpoints
| | | |-- NO --> Standard CRUD (GET/POST/PUT/PATCH/DELETE)
| | |-- Need real-time change notifications?
| | |-- YES --> IFS Connect outbound messages + subscriber
| | |-- NO --> Polling with $filter on OBJVERSION or timestamp
| |-- Batch/Bulk (scheduled, high volume)
| | |-- > 100,000 records/day?
| | | |-- YES --> File-based import (EDI/flat files) + IFS Connect
| | | |-- NO --> OData $batch requests with pagination
| | |-- Need delta sync?
| | |-- YES --> Filter by OBJVERSION or modification timestamp
| | |-- NO --> Full extract with $top/$skip pagination
| |-- Event-driven (outbound notifications)
| | |-- Need guaranteed delivery?
| | | |-- YES --> IFS Connect with store-and-forward + acknowledgment
| | | |-- NO --> IFS Connect fire-and-forget with retry configuration
| |-- File-based (EDI/CSV/XML)
| |-- Use IFS Connect file adapters for inbound file processing
| |-- Use data export functionality for outbound flat files
|-- Which direction?
| |-- Inbound (writing to IFS) --> POST/PUT/PATCH via OData
| |-- Outbound (reading from IFS) --> GET with $filter + pagination
| |-- Bidirectional --> Use OBJVERSION for conflict detection + IFS Connect
|-- Error tolerance?
|-- Zero-loss --> IFS Connect store-and-forward + dead letter queue
|-- Best-effort --> Direct OData calls with retry on 429/5xx
| Operation | Method | Endpoint | Payload | Notes |
|---|---|---|---|---|
| List entity sets in projection | GET | /ifsapplications/projection/v1/{ProjectionName} | N/A | Returns OData service document |
| Query records | GET | /ifsapplications/projection/v1/{ProjectionName}/{EntitySet} | N/A | Use $filter, $select, $expand, $top, $skip, $orderby |
| Get single record by key | GET | /ifsapplications/projection/v1/{ProjectionName}/{EntitySet}({keys}) | N/A | Composite keys: (Key1='val1',Key2='val2') |
| Create record | POST | /ifsapplications/projection/v1/{ProjectionName}/{EntitySet} | JSON | Standard OData v4 format |
| Update record (full) | PUT | /ifsapplications/projection/v1/{ProjectionName}/{EntitySet}({keys}) | JSON | Replaces entire entity |
| Update record (partial) | PATCH | /ifsapplications/projection/v1/{ProjectionName}/{EntitySet}({keys}) | JSON | Only include changed fields |
| Delete record | DELETE | /ifsapplications/projection/v1/{ProjectionName}/{EntitySet}({keys}) | N/A | Not all entity sets support delete |
| Execute action | POST | /ifsapplications/projection/v1/{ProjectionName}/{Action} | JSON (action params) | Bound and unbound actions |
| Execute function | GET | /ifsapplications/projection/v1/{ProjectionName}/{Function}(params) | N/A | Read-only operations |
| Batch request | POST | /ifsapplications/projection/v1/{ProjectionName}/$batch | Multipart/mixed | Bundle multiple operations |
| Get API metadata | GET | /ifsapplications/projection/v1/{ProjectionName}/$metadata | N/A | Returns OData EDMX schema |
Navigate to Solution Manager > Integration > API Explorer in IFS Cloud. Filter projections by Category = "Integration" or API Class = "Premium" to find stable integration endpoints. [src2]
Steps in IFS Cloud:
1. Navigate to Solution Manager > Integration > API Explorer
2. Click Settings icon > Column Chooser > add "API Class" column
3. Filter: Categories eq 'Integration' (for integration-specific projections)
4. OR filter: API Class eq 'Premium' (for backward-compatible APIs)
5. Select your target projection (e.g., WorkOrderHandling, PurchaseOrderHandling)
6. Click "OpenAPI v3" to download the specification
7. Note the projection name — this forms the endpoint URL
Verify: The API Explorer shows the projection with available entity sets, actions, and functions listed.
Create a service account in IFS IAM for your integration. Register an OAuth 2.0 client application with Client Credentials grant type. [src3]
Steps in IFS Cloud:
1. Navigate to IFS IAM Administration
2. Create a new Service Account (e.g., "MRO_Integration_SA")
3. Navigate to User Administration > Permission Sets
4. Create or assign a permission set that includes required projections
5. Assign the permission set to the service account
6. Navigate to IFS IAM > Clients > Create new client
7. Select grant type: "Client Credentials"
8. Copy Client ID and generate Client Secret
9. Store credentials securely (vault, environment variables)
Verify: The service account appears in IFS IAM with the correct permission sets assigned.
Use the OpenID Connect discovery endpoint to find the token URL, then request an access token using Client Credentials flow. [src3]
# Step 1: Discover token endpoint
DISCOVERY_URL="https://yourinstance.ifs.cloud/auth/realms/YourRealm/.well-known/openid-configuration"
TOKEN_URL=$(curl -s "$DISCOVERY_URL" | python3 -c "import sys,json;print(json.load(sys.stdin)['token_endpoint'])")
# Step 2: Request access token
curl -X POST "$TOKEN_URL" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=openid"
Verify: The response contains an access_token field. Decode the JWT to confirm the service account identity.
Use GET with OData v4 query parameters to retrieve records. [src1, src4]
# Get first 100 active work orders
curl -X GET "https://yourinstance.ifs.cloud/ifsapplications/projection/v1/WorkOrderHandling/ActiveSeparateSet?\$filter=WoStatusDbVal eq 'RELEASED'&\$top=100&\$skip=0&\$select=WoNo,Description,WoStatusDbVal,MchCode&\$orderby=WoNo desc" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Accept: application/json" \
-H "OData-Version: 4.0"
Verify: Response is a JSON object with value array. If value length < $top, you have reached the last page.
Use POST to create new records and PATCH for partial updates. IFS uses standard OData v4 format. [src1]
# Create a new purchase order line
curl -X POST "https://yourinstance.ifs.cloud/ifsapplications/projection/v1/PurchaseOrderHandling/PurchaseOrderLineSet" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "OData-Version: 4.0" \
-d '{
"OrderNo": "PO-2026-001",
"LineNo": "1",
"PartNo": "TURBINE-BLADE-A320",
"BuyQtyDue": 25,
"WantedReceiptDate": "2026-04-15"
}'
Verify: GET the record and confirm the fields have been updated. Check the OBJVERSION field to confirm a new version was created.
Use POST to invoke business actions defined on projections — e.g., releasing work orders, approving purchase requisitions. [src1, src4]
# Release a work order
curl -X POST "https://yourinstance.ifs.cloud/ifsapplications/projection/v1/WorkOrderHandling/ActiveSeparateSet(WoNo=12345)/Release" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "OData-Version: 4.0" \
-d '{}'
Verify: GET the entity again and confirm the status has changed (e.g., from "PLANNED" to "RELEASED").
Parse OData error responses and implement exponential backoff for rate limiting (429) and server errors (5xx). [src1, src3]
import requests, time, json
def ifs_api_request(method, url, token, data=None, max_retries=5):
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"Accept": "application/json",
"OData-Version": "4.0"
}
for attempt in range(max_retries):
response = requests.request(method, url, headers=headers, json=data)
if response.status_code in (200, 201, 204):
return response.json() if response.content else None
if response.status_code == 429:
retry_after = response.headers.get("Retry-After", None)
wait = int(retry_after) if retry_after else min(2 ** attempt * 2, 120)
time.sleep(wait)
continue
if response.status_code in (500, 502, 503):
time.sleep(min(2 ** attempt * 3, 120))
continue
error_body = response.json()
error_msg = error_body.get("error", {}).get("message", "Unknown")
raise Exception(f"IFS API error {response.status_code}: {error_msg}")
raise Exception("Max retries exceeded")
Verify: Test with an invalid projection name to confirm 404 error parsing returns a readable message.
# Input: IFS Cloud instance URL, access token
# Output: List of all released work orders across all pages
import requests
def get_all_work_orders(instance_url, token, status="RELEASED", page_size=200):
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/json",
"OData-Version": "4.0"
}
all_orders = []
skip = 0
base_url = f"{instance_url}/ifsapplications/projection/v1/WorkOrderHandling"
while True:
url = (f"{base_url}/ActiveSeparateSet"
f"?$filter=WoStatusDbVal eq '{status}'"
f"&$top={page_size}&$skip={skip}"
f"&$select=WoNo,Description,WoStatusDbVal,MchCode"
f"&$orderby=WoNo desc")
resp = requests.get(url, headers=headers)
resp.raise_for_status()
records = resp.json().get("value", [])
if not records:
break
all_orders.extend(records)
if len(records) < page_size:
break
skip += page_size
return all_orders
// Input: IFS Cloud instance URL, access token, asset data
// Output: Created asset record or error details
// npm install [email protected]
const axios = require("axios");
async function createAsset(instanceUrl, token, assetData) {
const url = `${instanceUrl}/ifsapplications/projection/v1/EquipmentObjectHandling/EquipmentObjectSet`;
try {
const response = await axios.post(url, assetData, {
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
Accept: "application/json",
"OData-Version": "4.0",
},
});
console.log("Asset created:", response.data.MchCode);
return response.data;
} catch (error) {
if (error.response?.status === 403) {
console.error("Permission denied — check service account permission sets");
} else if (error.response?.status === 429) {
console.error("Rate limited — implement exponential backoff");
}
throw error;
}
}
# Step 1: Get token endpoint from OpenID discovery
REALM="YourRealm"
DISCOVERY="https://yourinstance.ifs.cloud/auth/realms/$REALM/.well-known/openid-configuration"
TOKEN_URL=$(curl -s "$DISCOVERY" | python3 -c "import sys,json;print(json.load(sys.stdin)['token_endpoint'])")
# Step 2: Authenticate
TOKEN=$(curl -s -X POST "$TOKEN_URL" \
-d "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&scope=openid" \
| python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
# Step 3: Query a few work orders
curl -s "https://yourinstance.ifs.cloud/ifsapplications/projection/v1/WorkOrderHandling/ActiveSeparateSet?\$top=5" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json" \
-H "OData-Version: 4.0" | python3 -m json.tool
| IFS Cloud Field | API Representation | Type | Transform | Gotcha |
|---|---|---|---|---|
| MchCode (Equipment Object) | "MchCode": "PUMP-001" | String (key) | Direct | Case-sensitive in some projections |
| WoNo (Work Order Number) | "WoNo": 12345 | Integer (key) | Direct | Auto-generated on create; do not provide for new records |
| WoStatusDbVal | "WoStatusDbVal": "RELEASED" | String (enum) | Use DB value, not display | Values: PREPARE, RELEASED, STARTED, WORKDONE, REPORTED, FINISHED |
| PlannedStartDate | "PlannedStartDate": "2026-03-03T08:00:00Z" | DateTimeOffset | ISO 8601 with timezone | IFS stores in server timezone; API returns with offset |
| Contract (Site) | "Contract": "PLANT01" | String (key) | Direct | Required for most entities; determines data partition |
| OBJVERSION | "Objversion": "20260303120000" | String (timestamp) | Concurrency token | Include in PATCH/PUT for optimistic locking |
| Detail lines | Nested in $expand | Array of objects | Navigation property | Use $expand=Operations to include child records |
| Custom fields (CFV) | "Cf$_CustomField": "value" | Varies | Prefixed with Cf$_ | Custom fields from customization projects use naming convention |
EntitySet(Key1='val1',Key2=123). String keys must be single-quoted; numeric keys are unquoted. [src1]| Code | Meaning | Cause | Resolution |
|---|---|---|---|
| 400 | Validation error | Missing required field, wrong data type, invalid enum | Parse OData error body for field-level details |
| 401 | Token invalid or expired | OAuth token expired, revoked, or malformed | Request new token from IFS IAM; check expiry claim |
| 403 | Insufficient permissions | Service account lacks permission set for projection | Verify permission sets in IFS IAM |
| 404 | Projection or entity not found | Misspelled projection name or wrong instance URL | Check projection name in API Explorer |
| 412 | Concurrency conflict | Another process modified the record since last read | Re-read entity for fresh OBJVERSION, then retry |
| 429 | Rate limit exceeded | Too many requests in too short a period | Exponential backoff; check Retry-After header |
| 500 | Server-side error | PL/SQL business logic exception or DB constraint | Check IFS server logs; may require support ticket |
Check token expiry claim before each batch chunk and re-authenticate if within 5 minutes of expiry. [src3]Always use Premium or Integration-category projections for production. Test in sandbox after each upgrade. [src2, src4]Set up monitoring on IFS Connect message queues. Implement heartbeat/health checks for subscriber endpoints. [src7]Implement retry-on-412 logic: re-read entity, merge changes, re-submit with fresh OBJVERSION. Use PATCH for field-level updates. [src1]Maintain documented permission matrix. Test all API operations in staging with production service account's exact permission set. [src3]// BAD — Standard projections are designed for the Aurena UI and may change
// between IFS Cloud releases without compatibility guarantees.
// Endpoint: /ifsapplications/projection/v1/SomeAurenaPageHandling/EntitySet
// GOOD — Premium APIs have compatibility guarantees and comprehensive documentation.
// Filter by Categories eq 'Integration' or API Class eq 'Premium' in API Explorer.
// Endpoint: /ifsapplications/projection/v1/PremiumIntegrationProjection/EntitySet
# BAD — token endpoint varies by deployment, realm, and IAM configuration
token_url = "https://myinstance.ifs.cloud/auth/realms/default/protocol/openid-connect/token"
# GOOD — dynamically discover token endpoint from well-known configuration
import requests
discovery_url = f"{instance_url}/auth/realms/{realm}/.well-known/openid-configuration"
config = requests.get(discovery_url).json()
token_url = config["token_endpoint"]
# BAD — updating without OBJVERSION skips optimistic concurrency check
requests.patch(
f"{url}/WorkOrderHandling/ActiveSeparateSet(WoNo=12345)",
json={"Description": "Updated description"},
headers=headers
)
# GOOD — include OBJVERSION to detect concurrent modifications
record = requests.get(
f"{url}/WorkOrderHandling/ActiveSeparateSet(WoNo=12345)",
headers=headers
).json()
requests.patch(
f"{url}/WorkOrderHandling/ActiveSeparateSet(WoNo=12345)",
json={"Description": "Updated description"},
headers={**headers, "If-Match": record.get("@odata.etag", "*")}
)
Check the projection's $metadata or API Explorer for supported operations. [src2, src4]Always use $select to request only the fields you need — reduces response size by 80-90%. [src1]Test each OData feature against your specific projection. Consult $metadata for supported capabilities. [src4, src5]Always include Contract in $filter or ensure the service account's permission set restricts to correct company/site. [src1]Check if returned record count equals $top. If less, you have reached the last page. [src1]Use Client Credentials for service accounts or Authorization Code for user-context operations. [src3]# Discover OpenID Connect configuration (find token endpoint)
curl -s "https://yourinstance.ifs.cloud/auth/realms/YourRealm/.well-known/openid-configuration" | python3 -m json.tool
# Test authentication (obtain token)
curl -s -X POST "$TOKEN_URL" \
-d "grant_type=client_credentials&client_id=CLIENT_ID&client_secret=SECRET&scope=openid" \
| python3 -c "import sys,json;d=json.load(sys.stdin);print('Token OK' if 'access_token' in d else f'Error: {d}')"
# Verify projection accessibility (get metadata)
curl -s "https://yourinstance.ifs.cloud/ifsapplications/projection/v1/WorkOrderHandling/\$metadata" \
-H "Authorization: Bearer $TOKEN" -H "Accept: application/xml" | head -30
# Test a basic query (first 5 work orders)
curl -s "https://yourinstance.ifs.cloud/ifsapplications/projection/v1/WorkOrderHandling/ActiveSeparateSet?\$top=5" \
-H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -H "OData-Version: 4.0" | python3 -m json.tool
| IFS Cloud Release | Release Date | Status | Key API Changes | Migration Notes |
|---|---|---|---|---|
| 25R1 | 2025-05 | Current | API Explorer enhancements; expanded Premium API catalog; Depot Repair APIs | New projections added; existing projections stable |
| 24R2 | 2024-11 | Supported | Entity Service APIs introduced; enhanced API documentation | New integration surface option; projections unchanged |
| 24R1 | 2024-05 | Supported | Premium API class introduced; expanded API Explorer filtering | Filter by API Class to find stable endpoints |
| 23R2 | 2023-11 | Supported | OData v4 improvements; additional MRO and FSM projections | Standard projection catalog expanded |
| 23R1 | 2023-05 | End of Support | Foundation for current OData provider; projection framework matured | Minimum version for modern integration patterns |
| 22R2 | 2022-11 | EOL | Aurena-based API Explorer first introduced | Upgrade required; projections may differ significantly |
| Use When | Don't Use When | Use Instead |
|---|---|---|
| CRUD operations on IFS business entities (work orders, assets, purchase orders) | High-volume event streaming (>1,000 events/second) | IFS Connect for event-driven patterns |
| Querying MRO, asset management, or field service data in real-time | Bulk data migration of >100K records | File-based import via IFS Connect file adapters |
| Building integrations with stable, documented Premium endpoints | Need direct database access or custom SQL queries | N/A — never bypass the API layer in IFS Cloud |
| Aerospace/defense MRO work order automation | Simple reporting or BI dashboards | IFS Lobby/dashboard APIs or BI connector tools |
| Server-to-server integration requiring OAuth 2.0 authentication | Legacy SOAP-based integrations | IFS Connect SOAP endpoints (maintained for compatibility) |