IFS Aurena Extensibility: Custom Pages, Projections, and Integration Guide
How does IFS Aurena extensibility work for customization and integration?
TL;DR
- Bottom line: IFS Aurena extensibility is built on a layered architecture -- the
.clientfile defines the UI, the.projectionfile defines the data/API layer, and customizations live in a separate Cust layer using@Override(merge changes) or@Overtake(replace entirely) annotations. Projections double as OData v4 REST endpoints for external integration. - Key limit: Commands in
.clientfiles are atomic -- they cannot be partially overridden with@Overrideand must be fully rewritten with@Overtake. Lobby element creation still requires Enterprise Explorer, not Aurena. - Watch out for: Mixing up
@Overrideand@Overtake--@Overridemerges your changes with the base layer, while@Overtakecompletely replaces the original definition. Using@Overtakewhen@Overridewould suffice makes upgrades harder. [src2] - Best for: Extending IFS Cloud with custom pages, custom projections (that also serve as REST/OData APIs), lobby dashboards, and non-intrusive customizations that survive upgrades. [src1, src3]
- Authentication: OAuth 2.0 / OpenID Connect via IFS IAM for
/main/Aurena projections; Basic Auth available only for Integration-category projections on the/int/path. [src5, src6]
System Profile
IFS Cloud is a cloud-native ERP platform built on a component-based architecture. The Aurena client is the modern web-based UI (replacing the legacy Enterprise Explorer / Java-based client), built using a declarative domain-specific language called Marble. Aurena uses a clear separation between the client layer (UI definition in .client files) and the projection layer (data/API definition in .projection files). The underlying architecture generates two deployable packages from these models: the _CPI package (client page definition) and the _SVC package (projection/service logic). The projection services are exposed as OData v4 endpoints, making every Aurena projection inherently a REST API. [src1, src3]
| Property | Value |
|---|---|
| Vendor | IFS |
| System | IFS Cloud 24R2 (Aurena client) |
| API Surface | OData v4 (Projections as REST endpoints) |
| Current API Version | 24R2 (November 2024 release) |
| Editions Covered | All IFS Cloud editions |
| Deployment | Cloud (SaaS) / Managed Cloud |
| API Docs | IFS Technical Documentation - Extensibility |
| Status | GA |
API Surfaces & Capabilities
IFS Aurena extensibility spans both UI customization and API integration. Every projection defined in Marble is automatically exposed as an OData v4 service endpoint, which means UI extensibility and API extensibility are the same thing. [src1, src4]
| API Surface | Protocol | Best For | Max Records/Request | Rate Limit | Real-time? | Bulk? |
|---|---|---|---|---|---|---|
| OData v4 Projections (Main) | HTTPS/JSON OData | Aurena pages + external OAuth integrations | Configurable via $top | Server-managed | Yes | Paged |
| OData v4 Projections (Integration) | HTTPS/JSON OData | Middleware / iPaaS integrations (Basic Auth) | Configurable via $top | Server-managed | Yes | Paged |
| Custom Projections | HTTPS/JSON OData | New business entities, custom logic | Same as standard | Shared pool | Yes | Paged |
| Projection Actions | HTTPS/JSON POST | Business operations (approve, release) | N/A (action-based) | Shared | Yes | N/A |
| Push Notifications / Business Events | HTTP callbacks | Real-time outbound event detection | N/A | N/A | Yes | N/A |
| IFS REST Task (Workflows) | HTTPS/JSON | Calling external REST APIs from IFS workflows | N/A | Per-workflow | Yes | N/A |
Rate Limits & Quotas
IFS Cloud does not publish hard numeric API rate limits. Rate management is handled at the infrastructure level through server-side throttling, connection pooling, and tenant isolation.
Per-Request Limits
| Limit Type | Value | Applies To | Notes |
|---|---|---|---|
| Max records per query page | Configurable via $top | All OData projections | Default page size varies by projection; use $top and $skip for pagination [src4] |
| Max $expand depth | Limited (implementation-dependent) | OData queries | Deep nesting may hit server limits or timeout |
| Max request body size | Server-configured (typically 10-50 MB) | POST/PUT operations | Depends on IFS Cloud deployment configuration |
| Concurrent OData connections | Deployment-dependent | Per tenant | Managed by IFS Cloud infrastructure |
Rolling / Daily Limits
| Limit Type | Value | Window | Edition Differences |
|---|---|---|---|
| API request throughput | Server-managed (no published hard limit) | Continuous | Infrastructure-level throttling [src5] |
| Concurrent user sessions | License-dependent | Per deployment | Check IFS licensing terms |
| Workflow REST Task calls | Per-workflow frequency limits | Per execution | Configurable in workflow designer; new in 24R1 [src8] |
| Integration projection sessions | Deployment-dependent | Per tenant | Separate connection pooling on /int/ path |
Authentication
IFS Cloud uses IFS IAM (Identity and Access Manager) as its OAuth 2.0 authorization server. The authentication method depends on whether you access projections through the Main application path or the Integration path. [src5, src6]
| Flow | Use When | Token Lifetime | Refresh? | Notes |
|---|---|---|---|---|
| OAuth 2.0 / OpenID Connect | All Aurena /main/ projections | Configurable in IFS IAM | Yes | Required for standard Aurena projections [src5] |
| Basic Auth (Integration category) | Middleware / iPaaS via /int/ path | Session-based | No | Only for Integration-category projections [src5] |
| Client Credentials (OAuth 2.0) | Server-to-server automation | Configurable | Yes | Register application in IFS IAM [src6] |
| Authorization Code (OAuth 2.0) | User-context interactive apps | Configurable | Yes | Redirect-based flow [src6] |
Authentication Gotchas
- Main vs Integration path: Projections on
/main/require OAuth 2.0. If your middleware only supports Basic Auth, change the projection category to "Integration" in API Explorer (moves it to/int/path). [src5] - IFS IAM token scopes: Tokens carry scopes tied to the user's IFS permission sets. A valid token with insufficient permissions returns 403, not 401. [src6]
- Integration category exposes Basic Auth attack surface: Only set to Integration when consuming system cannot support OAuth, and restrict network access. [src5]
Constraints
- Cust layer is mandatory for customizations: All customizations must use files with
-Custsuffix. Modifying base layer files directly is unsupported -- IFS upgrades overwrite them. [src2, src7] - Commands cannot use @Override: Commands in
.clientfiles are atomic -- you must@Overtakethe entire definition. [src2] - Lobby creation requires Enterprise Explorer: Lobby elements display in Aurena but must be designed/created in Enterprise Explorer. [src1]
- Projection extensions are component-scoped: Custom projections belong to a specific IFS component and require packaging for cross-environment deployment. [src2, src3]
- Code generation merges layers at deploy time: Conflicts between overlapping @Overtake annotations can cause deployment failures. [src3]
- PL/SQL backing code required for custom actions: Custom actions defined in Marble require a corresponding
.plsvcfile for business logic. [src1]
Integration Pattern Decision Tree
START -- User needs to extend or integrate with IFS Cloud (Aurena)
|-- What type of extensibility?
| |-- UI Customization (change existing pages)
| | |-- Add fields? --> @Override in .client-Cust + .projection-Cust [src2]
| | |-- Change behavior (commands)? --> @Overtake in .client-Cust [src2]
| | |-- New page? --> New .client + .projection + .plsvc in Cust layer [src2]
| |-- API / Data Integration (external systems)
| | |-- Read data? --> Expose projection via API Explorer as OData [src4]
| | |-- Write data? --> POST/PUT to projection OData endpoint [src4]
| | |-- Business action? --> POST to projection action endpoint [src4]
| | |-- Auth: OAuth capable? --> /main/ path [src5]
| | |-- Auth: Basic Auth only? --> Set to Integration, /int/ path [src5]
| |-- Dashboard / Lobby
| | |-- Design in Enterprise Explorer [src1]
| | |-- Auto-appears in Aurena after configuration
| |-- Workflow Integration (24R1+)
| |-- Call external API? --> IFS REST Task [src8]
| |-- Event-driven outbound? --> Business Events
|-- Customization layer?
| |-- Cust layer (-Cust suffix) --> Customer changes [src2, src7]
| |-- Ext layer (-Ext suffix) --> ISV/partner extensions [src3]
| |-- Base layer --> Never modify [src7]
|-- Deploy as IFS Cloud component, test in sandbox first [src3]
Quick Reference
| Operation | Method | Endpoint Pattern | Payload | Notes |
|---|---|---|---|---|
| Query records | GET | /main/ifsapplications/projection/v1/{Projection}.svc/{EntitySet} | N/A | OData v4: $filter, $select, $expand, $top, $skip [src4] |
| Get single record | GET | /main/.../v1/{Projection}.svc/{EntitySet}(keys) | N/A | Key fields in parentheses |
| Create record | POST | /main/.../v1/{Projection}.svc/{EntitySet} | JSON | Standard OData POST |
| Update record | PATCH | /main/.../v1/{Projection}.svc/{EntitySet}(keys) | JSON | Partial update via PATCH |
| Delete record | DELETE | /main/.../v1/{Projection}.svc/{EntitySet}(keys) | N/A | Not all entities support delete |
| Execute action | POST | /main/.../v1/{Projection}.svc/{ActionName} | JSON params | Actions defined in projection |
| Integration path | GET/POST | /int/ifsapplications/projection/v1/{Projection}.svc/{EntitySet} | JSON/N/A | Integration-category only [src5] |
| API Explorer | Browser | Solution Manager > Integration > API Explorer | N/A | Browse projections, enable for integration |
| Page registration | N/A | Solution Manager > Navigator | N/A | Register custom .client pages |
Step-by-Step Integration Guide
1. Explore available projections in API Explorer
Navigate to Solution Manager > Integration > API Explorer. Browse or search for projections, view entity sets, actions, and functions. Enable for Integration to allow Basic Auth access. [src4]
Verify: Projection appears in API Explorer with entity sets listed.
2. Authenticate and obtain OAuth access token
Register your application in IFS IAM. For server-to-server, use client credentials flow. [src5, src6]
# Discover OAuth endpoints
curl -s "https://yourinstance.ifs.cloud/.well-known/openid-configuration" | python3 -m json.tool
# Obtain token using client credentials flow
curl -X POST "https://yourinstance.ifs.cloud/auth/realms/ifs/protocol/openid-connect/token" \
-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: Response contains an access_token field.
3. Query data via OData projection endpoint
Use standard OData v4 query syntax against the projection endpoint. [src4]
# Query with OAuth
curl -X GET "https://yourinstance.ifs.cloud/main/ifsapplications/projection/v1/CustomerOrderHandling.svc/CustomerOrderSet?\$filter=State eq 'Planned'&\$top=50" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json"
# Query with Basic Auth (Integration path)
curl -X GET "https://yourinstance.ifs.cloud/int/ifsapplications/projection/v1/CustomerOrderHandling.svc/CustomerOrderSet?\$top=10" \
-u "username:password" \
-H "Accept: application/json"
Verify: Response contains @odata.context and a value array.
4. Create a custom projection in Cust layer
When existing projections do not expose the data shape you need, create a custom projection using IFS Developer Studio in the Cust layer. [src1, src2]
-- File: YourComponent-Cust.projection (Marble DSL)
projection MyCustomIntegrationHandling;
component YourComponent;
layer Cust;
description "Custom projection for external integration";
entityset MyCustomEntitySet for MyCustomEntity;
@Override
entity MyCustomEntity {
attribute OrderNo Text;
attribute CustomerNo Text;
attribute TotalAmount Number;
attribute Status Enumeration(CustomerOrderState);
}
action ApproveOrder {
initialcheck none;
parameter OrderNo Text;
}
Verify: After deploying, the projection appears in API Explorer.
5. Extend an existing Aurena page with custom fields
Use @Override in a Cust-layer .client file. [src2]
-- File: CustomerOrderHandling-Cust.client (Marble DSL)
client CustomerOrderHandlingCust;
component ORDER;
layer Cust;
@Override
page CustomerOrderForm using CustomerOrderSet {
group CustomFieldsGroup after GeneralGroup {
label = "Custom Fields";
field MyCustomField {
label = "Custom Reference";
size = Medium;
}
}
}
Verify: The custom field group appears on the Customer Order page in Aurena.
6. Implement error handling for OData integration
Parse OData error responses and implement retry logic. [src4, src5]
import requests, time
def ifs_odata_request(instance_url, token, projection, entity_set,
params=None, max_retries=3):
url = (f"{instance_url}/main/ifsapplications/projection/v1/"
f"{projection}.svc/{entity_set}")
headers = {"Authorization": f"Bearer {token}",
"Accept": "application/json"}
for attempt in range(max_retries):
resp = requests.get(url, headers=headers, params=params, timeout=30)
if resp.status_code == 200:
return resp.json().get("value", [])
if resp.status_code == 401:
raise Exception("Token expired or invalid")
if resp.status_code == 403:
raise Exception("Valid token but insufficient projection access")
if resp.status_code in (500, 502, 503):
time.sleep(min(2 ** attempt * 2, 30))
continue
raise Exception(f"OData error {resp.status_code}: {resp.text[:500]}")
raise Exception("Max retries exceeded")
Verify: Test with an invalid projection name to confirm error parsing.
Code Examples
Python: Query and paginate IFS Cloud OData projection
# Input: IFS Cloud instance URL, OAuth token
# Output: All customer orders matching filter across all pages
import requests
def get_all_orders(instance_url, token, state="Planned", page_size=100):
headers = {"Authorization": f"Bearer {token}", "Accept": "application/json"}
all_orders, skip = [], 0
while True:
url = (f"{instance_url}/main/ifsapplications/projection/v1/"
f"CustomerOrderHandling.svc/CustomerOrderSet"
f"?$filter=State eq '{state}'&$top={page_size}&$skip={skip}")
resp = requests.get(url, headers=headers, timeout=30)
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
JavaScript/Node.js: Create a record via OData POST
// Input: IFS Cloud instance URL, OAuth token, order data
// Output: Created record or error
// npm install [email protected]
const axios = require("axios");
async function createOrder(instanceUrl, token, orderData) {
const url = `${instanceUrl}/main/ifsapplications/projection/v1/CustomerOrderHandling.svc/CustomerOrderSet`;
try {
const resp = await axios.post(url, orderData, {
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
});
console.log("Order created:", resp.data.OrderNo);
return resp.data;
} catch (err) {
if (err.response?.status === 403) console.error("Check IFS permission sets");
throw err;
}
}
cURL: Quick OData connectivity test
# Test OAuth (Main path)
curl -s "https://yourinstance.ifs.cloud/main/ifsapplications/projection/v1/CustomerHandling.svc/CustomerSet?\$top=5" \
-H "Authorization: Bearer $TOKEN" -H "Accept: application/json" | python3 -m json.tool
# Test Basic Auth (Integration path)
curl -s "https://yourinstance.ifs.cloud/int/ifsapplications/projection/v1/CustomerHandling.svc/CustomerSet?\$top=5" \
-u "user:pass" -H "Accept: application/json" | python3 -m json.tool
# OData metadata
curl -s "https://yourinstance.ifs.cloud/main/ifsapplications/projection/v1/CustomerHandling.svc/\$metadata" \
-H "Authorization: Bearer $TOKEN" -H "Accept: application/xml"
Data Mapping
Field Mapping Reference
| IFS Aurena Field | OData Representation | Type | Transform | Gotcha |
|---|---|---|---|---|
| Standard attribute | Direct JSON property | String/Number/Date | None | Field names case-sensitive, match Marble attribute names [src4] |
| Enumeration fields | String value | String | Display value in OData | Filter by display value, not internal enum code [src4] |
| Reference fields (LOV) | String (key value) | String | Key only, not description | Use $expand for descriptions |
| Date fields | ISO 8601 string | DateTimeOffset | YYYY-MM-DDTHH:MM:SSZ | Time zone depends on instance config |
| Computed/virtual fields | Read-only JSON property | Varies | Defined by fetch attribute | Cannot be updated via API [src1] |
| Custom fields (Cust layer) | Same as standard | Varies | Auto-exposed if in projection | Must be in .projection-Cust to appear in OData [src2] |
Data Type Gotchas
- Enumeration filter values: OData queries must use the display value (e.g.,
State eq 'Planned'), not the internal database code. [src4] - Date/time handling: Dates follow the instance time zone. OData responses may not include timezone offset. [src4]
- Custom field naming: Custom fields follow IFS naming conventions. The OData property name matches the Marble attribute name, not the database column name. [src2]
Error Handling & Failure Points
Common Error Codes
| Code | Meaning | Cause | Resolution |
|---|---|---|---|
| 400 | Validation error | Invalid field value, missing required field, or malformed OData query | Parse OData error body for field-level details [src4] |
| 401 | Authentication failure | Expired OAuth token, invalid credentials | Re-authenticate; for /main/ use OAuth, for /int/ use Basic Auth [src5] |
| 403 | Insufficient permissions | Valid token, user lacks projection access | Check IFS permission sets [src5, src6] |
| 404 | Not found | Wrong projection name, entity set name, or record key | Verify names in API Explorer; case-sensitive |
| 500 | Server-side failure | PL/SQL error in projection logic or DB constraint | Check IFS Cloud application server logs |
| 502/503 | Service unavailable | Deployment in progress or overload | Retry with exponential backoff |
Failure Points in Production
- OAuth token expiry during batch operations: Long-running batch jobs fail mid-batch when token expires. Fix:
Implement token refresh before each request. Use refresh tokens.[src5, src6] - Cust layer conflicts after IFS upgrade: @Overtake customizations may conflict with new base layer. Fix:
Use @Override where possible. Run Configuration Analyzer before upgrades.[src2, src7] - Missing permissions on new custom projections: New projections accessible to admin but 403 for regular users. Fix:
Create and assign IFS permission set for the projection.[src5] - Integration projection left with Basic Auth in production: Security risk from bypassing OAuth/SSO. Fix:
Audit Integration-category projections; restrict via firewall rules.[src5]
Anti-Patterns
Wrong: Modifying base layer files directly
-- BAD -- base layer modification will be overwritten on upgrade
-- File: CustomerOrderHandling.client (base layer)
client CustomerOrderHandling;
component ORDER;
layer Core;
page CustomerOrderForm using CustomerOrderSet {
field MyCustomField; -- Lost on next IFS upgrade
}
Correct: Use Cust layer with @Override
-- GOOD -- Cust layer survives upgrades
-- File: CustomerOrderHandling-Cust.client
client CustomerOrderHandlingCust;
component ORDER;
layer Cust;
@Override
page CustomerOrderForm using CustomerOrderSet {
field MyCustomField after ExistingField {
label = "Custom Reference";
}
}
Wrong: Using @Override on commands
-- BAD -- commands are atomic, @Override fails
@Override
command ApproveOrderCommand {
label = "Custom Approve"; -- Deployment error
}
Correct: Use @Overtake to replace commands entirely
-- GOOD -- @Overtake replaces entire command
@Overtake
command ApproveOrderCommand {
label = "Custom Approve";
enabled = [Status = "Planned"];
execute {
call ApproveOrder(OrderNo);
refresh;
success("Order approved successfully");
}
}
Wrong: Using Basic Auth on /main/ path
# BAD -- Basic Auth rejected on /main/ path
url = "https://instance.ifs.cloud/main/.../CustomerHandling.svc/CustomerSet"
response = requests.get(url, auth=("user", "pass")) # 401
Correct: Use /int/ path for Basic Auth
# GOOD -- /int/ path accepts Basic Auth for Integration-category projections
url = "https://instance.ifs.cloud/int/.../CustomerHandling.svc/CustomerSet"
response = requests.get(url, auth=("integration_user", "password"))
Common Pitfalls
- Using @Overtake when @Override suffices: @Overtake replaces the entire original, losing base changes in future upgrades. Fix:
Only use @Overtake for commands (required) and fundamental behavior changes. Use @Override for additive changes.[src2] - Forgetting .projection-Cust when adding client fields: Client references non-existent attribute, causing deployment error. Fix:
Always modify both .client-Cust and .projection-Cust together.[src2] - Not running Configuration Analyzer before upgrades: Conflicts cause deployment failures. Fix:
Run Configuration Analyzer, Lobby Analyzer, and Update Analyzer before accepting upgrades.[src7] - Exposing all projections for Integration without review: Basic Auth bypasses SSO. Fix:
Maintain register of Integration-category projections; prefer OAuth.[src5] - Missing .plsvc for custom actions: Runtime errors when action is invoked. Fix:
Create PL/SQL implementation for every custom action in the .plsvc file.[src1] - Assuming full OData v4 compliance: IFS may not support $count, $search, or complex lambda expressions. Fix:
Test each OData feature in API Explorer before building integration.[src4]
Diagnostic Commands
# Test OAuth token
curl -s "https://yourinstance.ifs.cloud/main/ifsapplications/projection/v1/" \
-H "Authorization: Bearer $TOKEN" -H "Accept: application/json"
# Get OData metadata for a projection
curl -s "https://yourinstance.ifs.cloud/main/ifsapplications/projection/v1/CustomerHandling.svc/\$metadata" \
-H "Authorization: Bearer $TOKEN" -H "Accept: application/xml" | head -50
# Test Basic Auth on Integration path
curl -s "https://yourinstance.ifs.cloud/int/ifsapplications/projection/v1/CustomerHandling.svc/CustomerSet?\$top=1" \
-u "integration_user:password" -H "Accept: application/json"
# Discover OpenID Connect configuration
curl -s "https://yourinstance.ifs.cloud/.well-known/openid-configuration" | python3 -m json.tool
# Verify projection entity schema
curl -s "https://yourinstance.ifs.cloud/main/ifsapplications/projection/v1/CustomerOrderHandling.svc/\$metadata" \
-H "Authorization: Bearer $TOKEN"
Version History & Compatibility
| IFS Cloud Version | Release Date | Status | Key Extensibility Changes | Migration Notes |
|---|---|---|---|---|
| 24R2 | 2024-11 | Current | Enhanced OAuth in IFS REST Task; externalized URL configuration | Audit workflow REST tasks for new OAuth options [src8] |
| 24R1 | 2024-05 | Supported | External REST API calls from workflows (IFS REST Task) | New capability, no breaking changes [src8] |
| 23R2 | 2023-11 | Supported | Solution Manager enhancements; improved API Explorer | N/A |
| 23R1 | 2023-05 | Supported | Custom Projection assistant in Solution Manager | Low-code projection creation |
| 22R2 | 2022-11 | Legacy | Projection-level security enhancements | Consider upgrading |
| 22R1 | 2022-05 | EOL | Baseline for current extensibility model | Minimum version for full support |
When to Use / When Not to Use
| Use When | Don't Use When | Use Instead |
|---|---|---|
| Extending IFS Aurena pages with custom fields, groups, or commands | Building separate web apps that read IFS data | Direct OData API integration |
| Creating custom projections for OData APIs | Needing hard numeric rate limits and SLA-guaranteed throughput | IFS Connect or middleware with rate management |
| Configuring lobby dashboards with KPIs | Needing real-time streaming / CDC | IFS Business Events + external event processing |
| Non-intrusive customizations surviving upgrades | Modifying core IFS PL/SQL base packages | IFS Developer Studio extension layer with partnership |
| Middleware integration via Basic Auth on /int/ path | Complex multi-step orchestration across systems | iPaaS (MuleSoft, Boomi) with IFS OData connector |
Important Caveats
- IFS Cloud does not publish hard numeric API rate limits. Throughput depends on deployment configuration and tenant sizing. Engage IFS support for capacity planning. [src5]
- The Aurena extensibility model (Cust layer, @Override, @Overtake) is specific to IFS Cloud. IFS Applications 10 uses a different framework -- do not confuse the two. [src1, src3]
- Lobby element design still requires Enterprise Explorer, even though lobbies display in Aurena. [src1]
- Integration-category projections with Basic Auth bypass OAuth/SSO security. Restrict with network-level controls. [src5]
- The Marble DSL is proprietary to IFS -- development requires IFS Developer Studio, available only to licensed customers and partners. [src1, src7]
- Custom projections and pages are deployment artifacts that must be packaged as IFS Cloud components -- not exportable through UI screens. [src2, src3]