---
# === IDENTITY ===
id: business/erp-integration/ifs-rest-api/2026
canonical_question: "What are the IFS REST API capabilities for aerospace, defense, and energy integrations?"
aliases:
  - "IFS Cloud OData REST API endpoints, projections, and rate limits"
  - "How to integrate with IFS Cloud ERP using the projection-based REST API"
  - "IFS Cloud API authentication with OAuth 2.0 and IFS IAM"
  - "IFS REST API capabilities for MRO, asset management, and field service integrations"
entity_type: erp_integration
domain: business > erp-integration > ifs-rest-api
region: global
jurisdiction: global
temporal_scope: 2024-2026

# === SYSTEM PROFILE ===
systems:
  - name: "IFS Cloud"
    vendor: "IFS"
    version: "IFS Cloud 24R2 / 25R1"
    edition: "All editions (single unified platform)"
    deployment: "cloud"
    api_surface: "REST (OData v4 Projections)"

# === VERIFICATION ===
last_verified: 2026-03-03
confidence: 0.85
version: 1.0
first_published: 2026-03-03

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: volatile
  last_breaking_change: "IFS Cloud 24R2 — Entity Service APIs introduced as new integration surface alongside projections"
  next_review: 2026-08-30
  change_sensitivity: high

# === CONSTRAINTS ===
constraints:
  - "Rate limits are not publicly documented — IFS uses fair-use throttling managed at the infrastructure level; excessive request volumes trigger HTTP 429 responses"
  - "Only OAuth 2.0 authentication is supported in IFS Cloud — no API keys, no basic auth; all integrations must use IFS IAM tokens"
  - "Projections are the API unit, not tables — approximately 5,800 projections exist in the main cluster, but not all expose all fields or support all CRUD operations"
  - "Premium APIs have compatibility guarantees; Standard APIs (designed for Aurena UI) may change between releases without notice"
  - "Custom projections require IFS Developer Studio and deployment to the IFS Cloud instance — they do not transfer between environments automatically"
  - "IFS Connect (service bus) is required for outbound event-driven integrations — direct webhook support is limited compared to modern event platforms"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "User needs IFS Applications 10 or earlier (on-premise legacy)"
    use_instead: "N/A — see IFS Apps 10 Integration Guide for PL/SQL-based APIs"
  - condition: "User needs SAP S/4HANA integration for aerospace/defense"
    use_instead: "business/erp-integration/sap-s4hana-rest-api/2026"
  - condition: "User needs Oracle ERP Cloud for energy/utilities"
    use_instead: "business/erp-integration/oracle-erp-cloud-rest-api/2026"

# === AGENT HINTS ===
inputs_needed:
  - key: integration_pattern
    question: "What integration pattern do you need?"
    type: choice
    options:
      - "real-time sync (individual records, <1s latency)"
      - "batch/bulk (scheduled, high volume)"
      - "event-driven (IFS Connect, business events)"
      - "file-based (CSV/XML import/export)"
  - key: data_volume
    question: "What's your daily data volume?"
    type: choice
    options:
      - "< 1,000 records/day"
      - "1,000-100,000 records/day"
      - "> 100,000 records/day"
  - key: direction
    question: "What's the data flow direction?"
    type: choice
    options:
      - "inbound (writing to IFS Cloud)"
      - "outbound (reading from IFS Cloud)"
      - "bidirectional sync"

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/business/erp-integration/ifs-rest-api/2026"
suggested_citation: "Source: knowledgelib.io — AI Knowledge Library (verified 2026-03-03)"

# === RELATED UNITS ===
related_kos:
  depends_on: []
  related_to:
    - id: "business/erp-integration/ifs-connect-integration/2026"
      label: "IFS Connect service bus for event-driven and outbound integrations"
  solves:
    - id: "business/erp-integration/ifs-sap-migration/2026"
      label: "IFS to SAP migration playbook for aerospace organizations"
  alternative_to:
    - id: "business/erp-integration/sap-s4hana-rest-api/2026"
      label: "SAP S/4HANA OData API for aerospace and defense ERP integration"
  often_confused_with:
    - id: "business/erp-integration/ifs-connect-integration/2026"
      label: "IFS Connect (service bus/messaging) vs IFS REST API (direct OData access)"

# === SOURCES ===
sources:
  - id: src1
    title: "IFS RESTful APIs — Technical Documentation"
    author: IFS
    url: https://docs.ifs.com/techdocs/Foundation1/010_overview/240_integration/400_rest_apis/
    type: official_docs
    published: 2025-01-15
    reliability: authoritative
  - id: src2
    title: "API Explorer Overview — IFS Cloud 25R1 Technical Documentation"
    author: IFS
    url: https://docs.ifs.com/techdocs/25r1/040_tailoring/300_extensibility/020_api_explorer/
    type: official_docs
    published: 2025-05-29
    reliability: authoritative
  - id: src3
    title: "Authentication in IFS Cloud"
    author: DSJ (IFS Technical Blog)
    url: https://dsj23.me/2022/11/10/authentication-in-ifs-cloud/
    type: technical_blog
    published: 2022-11-10
    reliability: moderate_high
  - id: src4
    title: "Projections and OData Provider — IFS Cloud Technical Documentation"
    author: IFS
    url: https://docs.ifs.com/techdocs/23r1/040_tailoring/300_extensibility/100_odata_provider/200_projections_and_odp/
    type: official_docs
    published: 2023-06-01
    reliability: authoritative
  - id: src5
    title: "IFS Cloud OData Connector — Novacura"
    author: Novacura
    url: https://www.novacura.com/blog-ifs-odata-connector/
    type: technical_blog
    published: 2024-09-15
    reliability: moderate_high
  - id: src6
    title: "IFS Applications Review 2026 — ERP Research"
    author: ERP Research
    url: https://www.erpresearch.com/pages/en-us/ifs-applications-overview
    type: industry_report
    published: 2026-01-10
    reliability: moderate_high
  - id: src7
    title: "The Ultimate Guide to IFS Integration — Boomi"
    author: Boomi (IFS Partner)
    url: https://www.ifs.com/assets/partner/the-ultimate-guide-to-ifs-integration
    type: technical_blog
    published: 2024-06-01
    reliability: moderate_high
  - id: src8
    title: "Custom Projections — Flow IFS Cloud Development Guidelines"
    author: Novacura
    url: https://docs.novacura.com/flow-ifs-cloud-development-guidelines/flow-development-with-odata/configuration/configuring-projections-in-ifs/custom-projections
    type: technical_blog
    published: 2024-11-01
    reliability: moderate_high
---

# IFS Cloud REST API: OData Projections, Capabilities, and Integration Guide for Aerospace, Defense, and Energy

## TL;DR

- **Bottom line**: IFS Cloud exposes its business logic through ~5,800 OData v4 projections served as REST APIs. Use Premium/Integration projections for stable, documented integration endpoints; avoid building against Standard (Aurena UI) projections as they may change between releases without notice. [src1, src2]
- **Key limit**: Rate limits are not publicly documented — IFS uses infrastructure-level fair-use throttling. No self-service configuration; excessive requests trigger 429 responses. Plan for conservative throughput (~50-100 requests/second as safe baseline) and implement backoff. [src1, src7]
- **Watch out for**: Not all projections support all CRUD operations — many are read-only or lack certain entity sets. Always check the API Explorer for the specific projection's capabilities before designing your integration. [src2, src4]
- **Best for**: Aerospace MRO work order management, defense asset lifecycle tracking, energy plant maintenance scheduling, and field service dispatch — IFS's core vertical strengths with deep domain-specific projections. [src6, src7]
- **Authentication**: OAuth 2.0 only via IFS Identity and Access Manager (IFS IAM). Use Client Credentials flow for server-to-server integrations; Authorization Code flow for user-context operations. No API keys supported. [src3]

## System Profile

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. IFS Cloud does not have separate editions; it is a single unified platform where functionality is unlocked through licensing. [src1, src4, src6]

This card covers IFS Cloud releases 24R2 and 25R1. It does not cover IFS Applications 10 or earlier on-premise versions, which use a different PL/SQL-based integration architecture. IFS Cloud is available as SaaS (managed cloud) or on customer-managed infrastructure.

| 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 URL** | [IFS Cloud API Explorer](https://docs.ifs.com/techdocs/25r1/040_tailoring/300_extensibility/020_api_explorer/) |
| **Status** | GA |

## API Surfaces & Capabilities

IFS Cloud provides multiple integration surfaces. The OData projection-based REST API is the primary and recommended surface for new integrations. IFS Connect provides message-based integration for event-driven and asynchronous patterns. [src1, src4, src7]

| 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 |

[src1, src2, src7]

## Rate Limits & Quotas

### Per-Request Limits

| Limit Type | Value | Applies To | Notes |
|---|---|---|---|
| Max records per query page | Server-enforced (varies by projection, typically 1,000-5,000) | OData Projections | Use $top and $skip for pagination; server may cap $top lower than requested [src1] |
| Max request body size | Infrastructure-dependent (typically 10-50 MB) | REST API | Governed by IIS/reverse proxy configuration in the IFS Cloud deployment [src1] |
| Max $expand depth | 2-3 levels (projection-dependent) | OData Projections | Deep expansions degrade performance; prefer multiple targeted queries [src4] |
| Max $filter complexity | No documented limit | OData Projections | Complex filters with many OR conditions may timeout; IFS recommends simpler filters with multiple requests [src1] |
| OData $batch support | Supported | OData Projections | Batch multiple operations in a single HTTP request to reduce overhead [src1] |

[src1, src4]

### Rolling / Daily Limits

| Limit Type | Value | Window | Edition Differences |
|---|---|---|---|
| API request rate | Fair-use throttling (not publicly documented) | Per-session / per-tenant | No edition differences — single platform; throttling enforced at infrastructure level [src1] |
| Concurrent API sessions | Not publicly documented | Per-tenant | Managed by IFS IAM; service accounts can have multiple concurrent sessions [src3] |
| IFS Connect message throughput | Configuration-dependent | Per-instance | Depends on message queue sizing and processing node capacity [src7] |
| Session timeout | Configurable (default varies by flow) | Per-session | OAuth tokens have configurable expiry; IAM session timeout is admin-configurable [src3] |

[src1, src3, src7]

## Authentication

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. IFS IAM can delegate to external identity providers (Azure AD, Okta, etc.) for end users, but service accounts must use IFS IAM's internal registry. [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 [src3] |
| 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 [src3] |
| OAuth 2.0 Resource Owner Password (ROPC) | Legacy integrations that cannot redirect to browser | Configurable | Yes | Highly discouraged by IFS — sends credentials directly; no MFA support [src3] |

[src3]

### Authentication Gotchas

- **Service accounts cannot use external identity providers**: If your organization uses Azure AD for SSO, service accounts for API integrations must still be created in IFS IAM's internal user registry. External IdP delegation only works for end-user (interactive) authentication. [src3]
- **OAuth token scope determines projection access**: The IFS IAM client configuration and associated permission sets control which projections a service account can access. A missing permission set results in 403 errors even with a valid token. [src3]
- **OpenID Connect discovery endpoint required for configuration**: You must fetch the well-known OpenID configuration from `https://{instance}/auth/realms/{realm}/.well-known/openid-configuration` to obtain token endpoints, supported grant types, and signing keys. Do not hardcode token URLs — they vary by deployment. [src3]
- **Session management across clusters**: IFS Cloud runs on Kubernetes with multiple pods. OAuth tokens are validated centrally by IAM, but session state may not persist across pod restarts. Always validate tokens before use rather than assuming session persistence. [src3]

## Constraints

- **No publicly documented rate limits** — unlike Salesforce (100K/24h) or NetSuite (governance units), IFS does not publish specific API rate limits. You must design for fair-use throttling and implement 429 retry logic from day one. [src1, src7]
- **Projection stability varies by API Class** — Standard projections (designed for Aurena UI) can change between IFS releases without compatibility guarantees. Only Premium and Integration-category projections promise backward compatibility and migration guidance. [src2, src4]
- **Custom projections require IFS Developer Studio** — extending or creating projections requires the IFS development toolchain, which is not a lightweight operation. Custom projections must be deployed as part of a customization package. [src8]
- **IFS Connect required for outbound events** — there is no native webhook or platform event system comparable to Salesforce Platform Events or SAP Business Events. Outbound event-driven integrations must use IFS Connect's service bus architecture. [src7]
- **Complex business logic cannot live in OData** — the OData API provides data access, but IFS business logic runs in the PL/SQL layer. Unlike Salesforce Apex or NetSuite SuiteScript, you cannot embed complex integration logic in the API layer itself. [src5]
- **Tenant isolation in multi-tenant deployments** — API access is scoped to a single IFS Cloud tenant. Cross-tenant queries or data sharing requires separate authentication and explicit data movement. [src3]

## Integration Pattern Decision Tree

```
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 [src1]
|   |   |   |-- NO --> OData $batch + chunking with rate limit handling
|   |   |-- Need to execute business logic (release WO, approve PO)?
|   |   |   |-- YES --> OData Actions on projection endpoints [src1, src4]
|   |   |   |-- NO --> Standard CRUD (GET/POST/PUT/PATCH/DELETE)
|   |   |-- Need real-time change notifications?
|   |       |-- YES --> IFS Connect outbound messages + subscriber [src7]
|   |       |-- 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 [src7]
|   |   |   |-- NO --> OData $batch requests with pagination
|   |   |-- Need delta sync?
|   |       |-- YES --> Filter by OBJVERSION or modification timestamp [src1]
|   |       |-- NO --> Full extract with $top/$skip pagination
|   |-- Event-driven (outbound notifications)
|   |   |-- Need guaranteed delivery?
|   |   |   |-- YES --> IFS Connect with store-and-forward + acknowledgment [src7]
|   |   |   |-- NO --> IFS Connect fire-and-forget with retry configuration
|   |   |-- Need message transformation?
|   |       |-- YES --> IFS Connect XSLT mapping + content-based routing [src7]
|   |       |-- NO --> Direct IFS Connect message pass-through
|   |-- 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; validate via API Explorer
|   |-- Outbound (reading from IFS) --> GET with $filter + pagination
|   |-- Bidirectional --> Use OBJVERSION for conflict detection + IFS Connect for events
|-- Error tolerance?
    |-- Zero-loss --> IFS Connect store-and-forward + dead letter queue pattern
    |-- Best-effort --> Direct OData calls with retry on 429/5xx
```

## Quick Reference

| Operation | Method | Endpoint | Payload | Notes |
|---|---|---|---|---|
| List entity sets in projection | GET | `/ifsapplications/projection/v1/{ProjectionName}` | N/A | Returns OData service document [src1] |
| Query records | GET | `/ifsapplications/projection/v1/{ProjectionName}/{EntitySet}` | N/A | Use $filter, $select, $expand, $top, $skip, $orderby [src1] |
| Get single record by key | GET | `/ifsapplications/projection/v1/{ProjectionName}/{EntitySet}({keys})` | N/A | Composite keys: `(Key1='val1',Key2='val2')` [src1] |
| Create record | POST | `/ifsapplications/projection/v1/{ProjectionName}/{EntitySet}` | JSON | OData v4 format — no value wrapping needed [src1] |
| Update record (full) | PUT | `/ifsapplications/projection/v1/{ProjectionName}/{EntitySet}({keys})` | JSON | Replaces entire entity; include all required fields [src1] |
| Update record (partial) | PATCH | `/ifsapplications/projection/v1/{ProjectionName}/{EntitySet}({keys})` | JSON | Only include changed fields [src1] |
| Delete record | DELETE | `/ifsapplications/projection/v1/{ProjectionName}/{EntitySet}({keys})` | N/A | Not all entity sets support delete [src1] |
| Execute action | POST | `/ifsapplications/projection/v1/{ProjectionName}/{Action}` | JSON (action params) | Bound and unbound actions; check projection metadata [src1, src4] |
| Execute function | GET | `/ifsapplications/projection/v1/{ProjectionName}/{Function}(params)` | N/A | Read-only operations [src1] |
| Batch request | POST | `/ifsapplications/projection/v1/{ProjectionName}/$batch` | Multipart/mixed | Bundle multiple operations in one HTTP request [src1] |
| Get API metadata | GET | `/ifsapplications/projection/v1/{ProjectionName}/$metadata` | N/A | Returns OData EDMX schema for the projection [src1] |
| API Explorer (UI) | Browser | Solution Manager > Integration > API Explorer | N/A | Browse all projections, filter by category (Integration, Premium) [src2] |

## Step-by-Step Integration Guide

### 1. Discover available projections via API Explorer

Navigate to Solution Manager > Integration > API Explorer in IFS Cloud. Filter projections by Category = "Integration" or API Class = "Premium" to find stable integration endpoints. Export the OpenAPI v3 or OData service document for your target projection. [src2]

```plaintext
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. Click "OData Service Document" to view entity sets and operations
8. Note the projection name — this forms the endpoint URL
```

**Verify**: The API Explorer shows the projection with available entity sets, actions, and functions listed.

### 2. Configure IFS IAM service account and OAuth client

Create a service account in IFS IAM for your integration. Assign appropriate permission sets that grant access to the required projections. Register an OAuth 2.0 client application with Client Credentials grant type. [src3]

```plaintext
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 (e.g., WorkOrderHandling, ShopOrderHandling)
   - Required company/site access
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.

### 3. Authenticate and obtain access token

Use the OpenID Connect discovery endpoint to find the token URL, then request an access token using Client Credentials flow. [src3]

```bash
# Input:  IFS Cloud instance URL, client_id, client_secret, realm name
# Output: OAuth 2.0 access token

# 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'])")
echo "Token endpoint: $TOKEN_URL"

# 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"

# Response:
# {
#   "access_token": "eyJ...",
#   "expires_in": 3600,
#   "token_type": "Bearer",
#   "scope": "openid"
# }
```

**Verify**: The response contains an `access_token` field. Decode the JWT to confirm the service account identity and scope claims.

### 4. Query records with OData filtering and pagination

Use GET with OData v4 query parameters to retrieve records. IFS supports $filter, $select, $expand, $top, $skip, $orderby, and $count. [src1, src4]

```bash
# Input:  Access token, projection name, entity set
# Output: JSON array of matching records

# Get first 100 active work orders with expand on operations
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,MchCodeContract&\$orderby=WoNo desc" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "OData-Version: 4.0"

# Next page:
curl -X GET "https://yourinstance.ifs.cloud/ifsapplications/projection/v1/WorkOrderHandling/ActiveSeparateSet?\$filter=WoStatusDbVal eq 'RELEASED'&\$top=100&\$skip=100" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Accept: application/json"
```

**Verify**: Response is a JSON object with `value` array containing matching records. If `value` length < `$top`, you have reached the last page.

### 5. Create and update records

Use POST to create new records and PATCH for partial updates. IFS uses standard OData v4 format — no value wrapping required (unlike Acumatica). [src1]

```bash
# Input:  Access token, entity data
# Output: Created/updated record

# 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"
  }'

# Partial update (PATCH) — update quantity only
curl -X PATCH "https://yourinstance.ifs.cloud/ifsapplications/projection/v1/PurchaseOrderHandling/PurchaseOrderLineSet(OrderNo='PO-2026-001',LineNo='1')" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "OData-Version: 4.0" \
  -d '{
    "BuyQtyDue": 50
  }'
```

**Verify**: GET the record and confirm the fields have been updated. Check the OBJVERSION field to confirm a new version was created.

### 6. Execute business actions

Use POST to invoke business actions defined on projections, such as releasing work orders, approving purchase requisitions, or completing maintenance tasks. [src1, src4]

```bash
# Input:  Access token, action name, action parameters
# Output: Action result

# 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 '{}'

# Complete a maintenance task with reporting
curl -X POST "https://yourinstance.ifs.cloud/ifsapplications/projection/v1/TaskReporting/WorkTaskSet(TaskSeq=67890)/ReportComplete" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "OData-Version: 4.0" \
  -d '{
    "CompletionDate": "2026-03-03T14:30:00Z",
    "ActualHours": 4.5,
    "Notes": "Turbine blade inspection completed per MRO spec AD-2026-042"
  }'
```

**Verify**: GET the entity again and confirm the status has changed (e.g., from "PLANNED" to "RELEASED" or "COMPLETED").

### 7. Implement error handling and rate limit retries

Parse OData error responses and implement exponential backoff for rate limiting (429) and server errors (5xx). [src1, src3]

```python
# Input:  IFS Cloud instance URL, access token, request parameters
# Output: Successful response or structured error information

import requests
import time
import json

def ifs_api_request(method, url, token, data=None, max_retries=5):
    """Make an IFS Cloud REST API request with retry logic."""
    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:
            # Rate limited — exponential backoff
            retry_after = response.headers.get("Retry-After", None)
            wait = int(retry_after) if retry_after else min(2 ** attempt * 2, 120)
            print(f"Rate limited. Waiting {wait}s (attempt {attempt + 1})")
            time.sleep(wait)
            continue

        if response.status_code == 401:
            raise Exception("Authentication failed — token expired or invalid. "
                            "Request a new token from IFS IAM.")

        if response.status_code == 403:
            raise Exception("Forbidden — service account lacks permission set "
                            "for this projection. Check IFS IAM configuration.")

        if response.status_code in (500, 502, 503):
            wait = min(2 ** attempt * 3, 120)
            print(f"Server error {response.status_code}. Retrying in {wait}s")
            time.sleep(wait)
            continue

        if response.status_code == 404:
            raise Exception(
                "Projection or entity set not found — verify projection name "
                "spelling and that the projection is deployed on this instance."
            )

        # Parse OData error response
        try:
            error_body = response.json()
            error_msg = error_body.get("error", {}).get("message", "Unknown")
            raise Exception(f"IFS API error {response.status_code}: {error_msg}")
        except (json.JSONDecodeError, KeyError):
            raise Exception(f"IFS API error {response.status_code}: {response.text}")

    raise Exception("Max retries exceeded — rate limit or server issue not cleared")
```

**Verify**: Test with an invalid projection name to confirm 404 error parsing returns a readable message.

## Code Examples

### Python: Query and paginate work orders for MRO

```python
# 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):
    """Paginate through all work orders matching a status filter."""
    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,MchCodeContract"
            f"&$orderby=WoNo desc"
        )
        resp = requests.get(url, headers=headers)
        resp.raise_for_status()
        data = resp.json()
        records = data.get("value", [])

        if not records:
            break

        all_orders.extend(records)
        if len(records) < page_size:
            break  # Last page
        skip += page_size

    return all_orders

# Usage:
# orders = get_all_work_orders("https://myinstance.ifs.cloud", token)
# print(f"Total released work orders: {len(orders)}")
```

### JavaScript/Node.js: Create asset object with error handling

```javascript
// Input:  IFS Cloud instance URL, access token, asset data
// Output: Created asset record or error details

// npm install axios@1.x
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");
    } else if (error.response?.status === 400) {
      const msg = error.response.data?.error?.message || "Validation error";
      console.error("Validation failed:", msg);
    }
    throw error;
  }
}

// Usage:
// createAsset("https://myinstance.ifs.cloud", token, {
//   MchCode: "TURBINE-GEN-001",
//   MchName: "Gas Turbine Generator Unit 1",
//   Contract: "PLANT01",
//   MchType: "GENERATOR",
//   ObjLevel: "OBJECT"
// });
```

### cURL: Quick API connectivity test

```bash
# Input:  IFS Cloud instance URL, client credentials
# Output: Token and projection list

# 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" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "scope=openid" \
  | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
echo "Token obtained: ${TOKEN:0:20}..."

# Step 3: List available projections (via a known projection)
curl -s "https://yourinstance.ifs.cloud/ifsapplications/projection/v1/WorkOrderHandling/\$metadata" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/xml" | head -50

# Step 4: 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
```

## Data Mapping

### Field Mapping Reference

| IFS Cloud Field Pattern | API Representation | Type | Transform | Gotcha |
|---|---|---|---|---|
| MchCode (Equipment Object) | `"MchCode": "PUMP-001"` | String (key) | Direct — no value wrapping | Case-sensitive in some projections [src1] |
| WoNo (Work Order Number) | `"WoNo": 12345` | Integer (key) | Direct | Auto-generated on create; do not provide for new records [src1] |
| WoStatusDbVal (Work Order Status) | `"WoStatusDbVal": "RELEASED"` | String (enum) | Use DB value, not display value | Values: PREPARE, RELEASED, STARTED, WORKDONE, REPORTED, FINISHED [src1] |
| PlannedStartDate | `"PlannedStartDate": "2026-03-03T08:00:00Z"` | DateTimeOffset | ISO 8601 with timezone | IFS stores in server timezone; API returns with offset [src1] |
| Contract (Site) | `"Contract": "PLANT01"` | String (key) | Direct | Required for most entities; determines data partition [src1] |
| OBJVERSION (Optimistic Locking) | `"Objversion": "20260303120000"` | String (timestamp) | Used for conflict detection | Include in PATCH/PUT for optimistic concurrency control [src1, src4] |
| Detail lines (e.g., WO Operations) | Nested in $expand | Array of objects | Access via navigation property | Use $expand=Operations to include child records [src4] |
| Custom fields (CFV) | `"Cf$_CustomField": "value"` | Varies | Prefixed with Cf$_ | Custom fields from customization projects use naming convention [src8] |

### Data Type Gotchas

- **OBJVERSION is a concurrency token, not a timestamp**: While it looks like a timestamp, OBJVERSION is an opaque string used for optimistic locking. Include it in update requests (PUT/PATCH) to detect concurrent modifications. If a conflict occurs, IFS returns 412 Precondition Failed. [src1]
- **Enum fields use DB values, not display labels**: Status fields like WoStatusDbVal use internal database values (e.g., "RELEASED") which differ from the display labels shown in IFS Aurena (e.g., "Released"). Always use DB values in API requests. [src1, src4]
- **DateTimeOffset vs Date**: IFS projections use DateTimeOffset (with timezone) for timestamp fields but plain Date for date-only fields. Sending a DateTime to a Date field may cause unexpected timezone conversions. [src1]
- **Composite keys require parenthesized format**: Multi-field keys in OData use the format `EntitySet(Key1='val1',Key2=123)`. String keys must be single-quoted; numeric keys are unquoted. Getting this wrong returns 400 or 404. [src1]

## Error Handling & Failure Points

### Common Error Codes

| Code | Meaning | Cause | Resolution |
|---|---|---|---|
| 400 Bad Request | Validation error | Missing required field, wrong data type, invalid enum value | Parse OData error body for field-level validation details [src1] |
| 401 Unauthorized | Token invalid or expired | OAuth token expired, revoked, or malformed | Request a new token from IFS IAM; check token expiry claim [src3] |
| 403 Forbidden | Insufficient permissions | Service account lacks permission set for this projection or company | Verify permission sets in IFS IAM; check company/site access [src3] |
| 404 Not Found | Projection, entity set, or record not found | Misspelled projection name, entity does not exist, or wrong instance URL | Check projection name in API Explorer; verify instance URL [src2] |
| 412 Precondition Failed | Optimistic concurrency conflict | Another user/process modified the record since you last read it | Re-read the entity to get fresh OBJVERSION, then retry the update [src1] |
| 429 Too Many Requests | Rate limit exceeded | Too many requests in too short a period | Implement exponential backoff; check Retry-After header if present [src1] |
| 500 Internal Server Error | Server-side error | PL/SQL business logic exception, database constraint violation | Check IFS application server logs; may require IFS support ticket |

[src1, src3]

### Failure Points in Production

- **Token expiry during long-running batch operations**: OAuth tokens typically expire in 1-2 hours. Batch jobs processing thousands of records may outlast the token. Fix: `Implement proactive token refresh — check token expiry claim before each batch chunk and re-authenticate if within 5 minutes of expiry.` [src3]
- **Projection changes after IFS Cloud upgrade**: Standard (non-Premium) projections may add, rename, or remove entity sets between IFS Cloud releases. An upgrade from 24R1 to 24R2 can break integrations built against Standard projections. Fix: `Always use Premium or Integration-category projections for production integrations. Test all integrations in a sandbox after each IFS upgrade.` [src2, src4]
- **IFS Connect message delivery failures are not immediately visible**: If an IFS Connect outbound message subscriber is down, messages queue in the service bus but there is no proactive alerting unless configured. Fix: `Set up monitoring on IFS Connect message queues. Implement a heartbeat/health check for subscriber endpoints. Use IFS Connect's store-and-forward with configured retry policies.` [src7]
- **Concurrent update conflicts on high-contention entities**: Work orders and asset records in MRO scenarios are frequently updated by multiple users and systems simultaneously, triggering 412 Precondition Failed errors. Fix: `Implement retry-on-412 logic: re-read the entity, merge changes, re-submit with fresh OBJVERSION. Consider field-level rather than record-level updates using PATCH.` [src1]
- **Permission set gaps discovered late**: Integration service accounts are often configured with minimal permissions initially. When new entity sets or projections are needed, 403 errors appear in production. Fix: `Maintain a documented permission matrix. Test all API operations in a staging environment with the production service account's exact permission set.` [src3]

## Anti-Patterns

### Wrong: Building against Standard (Aurena UI) projections for integration

```plaintext
// 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
```

### Correct: Use Premium or Integration-category projections

```plaintext
// 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
```

### Wrong: Hardcoding the token endpoint URL

```python
# BAD — token endpoint varies by deployment, realm, and IAM configuration
token_url = "https://myinstance.ifs.cloud/auth/realms/default/protocol/openid-connect/token"
```

### Correct: Use OpenID Connect discovery to find the token endpoint

```python
# 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"]
```

### Wrong: Ignoring OBJVERSION for updates (risking silent data overwrites)

```python
# BAD — updating without OBJVERSION skips optimistic concurrency check
requests.patch(
    f"{url}/WorkOrderHandling/ActiveSeparateSet(WoNo=12345)",
    json={"Description": "Updated description"},
    headers=headers
)
```

### Correct: Include OBJVERSION for optimistic concurrency control

```python
# GOOD — include OBJVERSION to detect concurrent modifications
# First, read the current record
record = requests.get(
    f"{url}/WorkOrderHandling/ActiveSeparateSet(WoNo=12345)",
    headers=headers
).json()

# Then update with the OBJVERSION
requests.patch(
    f"{url}/WorkOrderHandling/ActiveSeparateSet(WoNo=12345)",
    json={"Description": "Updated description"},
    headers={**headers, "If-Match": record.get("@odata.etag", "*")}
)
```

## Common Pitfalls

- **Assuming all projections support write operations**: Many IFS projections are read-only, exposing only GET operations. Attempting POST/PUT/PATCH on a read-only projection returns 405 Method Not Allowed. Fix: `Check the projection's metadata ($metadata) or API Explorer documentation for supported operations before designing your integration.` [src2, src4]
- **Not using $select to limit response payload**: IFS projections can return entities with 50+ fields. Fetching all fields for every record wastes bandwidth and increases latency, especially over slow connections to remote field service operations. Fix: `Always use $select to request only the fields your integration needs. This can reduce response size by 80-90%.` [src1]
- **Treating IFS OData as fully OData v4 compliant**: While IFS implements OData v4, not all OData features are supported on every projection. Features like cross-join, complex type inheritance, and certain $filter functions may not work. Fix: `Test each OData feature against your specific projection. Consult the projection's metadata for supported capabilities.` [src4, src5]
- **Forgetting company/site (Contract) context**: Most IFS entities are partitioned by company and site. Queries without proper Contract context may return unexpected results or empty data sets. Fix: `Always include Contract in $filter for entity queries, or ensure the service account's permission set restricts to the correct company/site.` [src1]
- **Not handling pagination termination correctly**: IFS does not always include an `@odata.nextLink` property. Relying solely on nextLink to determine pagination completion can cause premature termination. Fix: `Check if the returned record count equals $top. If less than $top, you have reached the last page. Also handle the case where the response includes exactly $top records but there are no more.` [src1]
- **Using ROPC (Resource Owner Password) flow in production**: While technically supported, ROPC sends user credentials directly and does not support MFA. It is intended only for legacy migration scenarios. Fix: `Use Client Credentials flow for service accounts or Authorization Code flow for user-context operations.` [src3]

## Diagnostic Commands

```bash
# 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

# Check entity set availability in a projection
curl -s "https://yourinstance.ifs.cloud/ifsapplications/projection/v1/WorkOrderHandling" \
  -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" | python3 -m json.tool

# 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

# Check IFS Cloud version (accessible without specific projection)
curl -s "https://yourinstance.ifs.cloud/ifsapplications/projection/v1/" \
  -H "Authorization: Bearer $TOKEN" -H "Accept: application/json"
```

## Version History & Compatibility

| 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 [src2] |
| 24R2 | 2024-11 | Supported | Entity Service APIs introduced (simplified CRUD surface); enhanced API documentation | New integration surface option; projections unchanged [src2] |
| 24R1 | 2024-05 | Supported | Premium API class introduced; expanded API Explorer filtering | Filter by API Class to find stable integration 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 [src4] |
| 22R2 | 2022-11 | EOL | Aurena-based API Explorer first introduced | Upgrade required; projections may differ significantly |

[src2, src4, src6]

### Deprecation Policy

IFS follows a release-based deprecation model. Premium APIs maintain backward compatibility across releases, with changes communicated through release notes and migration guides. Standard projections may change without notice between releases. IFS Cloud releases follow a biannual cadence (R1 in spring, R2 in fall), with each release supported for approximately 2 years. IFS recommends upgrading within one release of the current version to maintain support eligibility. [src2, src6]

## When to Use / When Not to Use

| 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 [src7] |
| 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 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 and asset lifecycle management | Simple reporting or BI dashboards with read-only access | 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 backward compatibility) [src7] |

## Important Caveats

- IFS does not publicly document specific API rate limits or quota numbers. Unlike Salesforce, Oracle, or SAP, there are no published requests-per-day or requests-per-minute figures. Design your integration with conservative throughput assumptions and robust 429 retry logic. [src1, src7]
- The distinction between Premium/Integration projections and Standard (Aurena) projections is critical for production stability. Standard projections are the majority of the ~5,800 available, but they lack backward compatibility guarantees. Always use the API Explorer to verify the API Class before building against a projection. [src2, src4]
- IFS Cloud is a single unified platform without separate editions (unlike Salesforce Enterprise vs. Unlimited or SAP S/4HANA Cloud vs. Private Cloud). API capabilities are the same for all customers; functionality differences come from module licensing, not API tiers. [src6]
- IFS's strength in aerospace, defense, and energy means the deepest and most mature projections are in MRO, asset management, and field service management. If your integration targets these domains, IFS provides richer API surfaces than competing general-purpose ERPs. [src6, src7]
- Custom projections created via IFS Developer Studio are deployment-specific. They must be included in customization packages for migration between environments (dev/test/prod). Test custom projections thoroughly after each IFS Cloud upgrade. [src8]

## Related Units

- [IFS Connect service bus for event-driven and outbound integrations](/business/erp-integration/ifs-connect-integration/2026)
- [SAP S/4HANA OData API for aerospace and defense ERP integration](/business/erp-integration/sap-s4hana-rest-api/2026)
- [IFS to SAP migration playbook for aerospace organizations](/business/erp-integration/ifs-sap-migration/2026)
