This card compares the API surfaces across the three major Infor CloudSuite ERP product lines: M3 (manufacturing/distribution), LN (industrial enterprise), and CloudSuite Industrial/CSI (formerly SyteLine). All three are deployed on Infor OS in the cloud and share the ION API Gateway as the external-facing API proxy, but each product has a distinct native API architecture. This card does NOT cover Infor CloudSuite Financials (Lawson), Infor EAM, or Infor WMS as standalone API surfaces. [src1, src2]
| System | Role | API Surface | Direction |
|---|---|---|---|
| Infor M3 | Manufacturing/Distribution ERP | MIProgram REST (6,000+ transactions) via ION API Gateway | Bidirectional |
| Infor LN | Industrial Enterprise ERP | OData REST APIs (modeled via ttadv2570m700) via ION API Gateway | Bidirectional |
| Infor CSI (SyteLine) | Industrial Manufacturing ERP | IDO REST/SOAP web services via ION API Gateway | Bidirectional |
| ION API Gateway | Unified API proxy (Infor OS) | OAuth 2.0 + throttling + routing | Orchestrator |
| Infor Data Lake | Bulk data retrieval | Compass SQL API / Data Fabric | Outbound (read) |
| ION (Middleware) | Event-driven messaging | BOD XML documents | Bidirectional |
Each CloudSuite product exposes different native API surfaces, all accessible through the ION API Gateway. The gateway adds OAuth 2.0 security, throttling, and routing but does not normalize the underlying API patterns. [src1, src2]
| API Surface | Product | Protocol | Best For | Max Records/Request | Rate Limit | Real-time? | Bulk? |
|---|---|---|---|---|---|---|---|
| MIProgram REST | M3 | HTTPS/JSON or XML | Individual record CRUD, business logic | ~1,000 (maxrecs) | ION Gateway throttling | Yes | No |
| M3 BOD (via ION) | M3 | XML/BOD | Event-driven, async replication | Per-BOD | ION message throughput | Async | Yes |
| OData REST API | LN | HTTPS/JSON (OData v4) | CRUD, filtered queries, pagination | OData page size | ION Gateway throttling | Yes | Limited |
| LN BOD (via ION) | LN | XML/BOD | Event-driven, cross-app integration | Per-BOD | ION message throughput | Async | Yes |
| LN SOAP | LN | HTTPS/XML | Legacy integrations, complex transactions | Per-operation | ION Gateway throttling | Yes | No |
| IDO REST | CSI | HTTPS/JSON | IDO object CRUD, queries | IDO-dependent | ION Gateway throttling | Yes | No |
| IDO SOAP | CSI | HTTPS/XML | Legacy .NET integrations | IDO-dependent | ION Gateway throttling | Yes | No |
| CSI BOD (via ION) | CSI | XML/BOD | Async event-driven messaging | Per-BOD | ION message throughput | Async | Yes |
| Data Lake / Compass | All | SQL API / HTTPS | Bulk data extraction, analytics | Unlimited (query) | Query concurrency | Near-RT (~10 min) | Yes |
| Limit Type | Value | Applies To | Notes |
|---|---|---|---|
| M3 MIProgram max records | ~1,000 default | MIProgram REST execute | Use maxrecs matrix parameter to adjust |
| LN OData page size | Server-configured | LN OData REST API | Use $top and $skip or @odata.nextLink |
| CSI IDO result set | IDO-configured | CSI IDO REST/SOAP | Depends on IDO definition |
| BOD message size | ~10 MB typical | ION BOD messaging | Large payloads should be chunked |
| Limit Type | Value | Window | Product Differences |
|---|---|---|---|
| ION API Gateway throttling | Configurable per-endpoint | Per time period (e.g., 60s) | Spike arrest + rate smoothing configurable |
| ION BOD throughput | Tenant-dependent | Per-minute/hour | Shared across all apps on tenant |
| Data Lake query concurrency | Tenant-dependent | Concurrent | Limited concurrent Compass queries |
| OAuth token requests | Not publicly documented | Per-tenant | Token endpoint has rate limiting |
The gateway supports configurable throttling policies per endpoint: timePeriodInMilliseconds (e.g., 60,000ms), spikeArrest.maxRequestsPerPeriod (e.g., 1,000), rateSmoothing.delayAfterCount (e.g., 1,000), rateSmoothing.delayFactorInMilliseconds (e.g., 1,000ms). [src2]
All three CloudSuite products authenticate external API consumers through the ION API Gateway using OAuth 2.0. [src5, src8]
| Flow | Use When | Token Lifetime | Refresh? | Notes |
|---|---|---|---|---|
| Authorization Code | Native mobile/desktop/web apps | Access: ~2h | Yes (30-day grant default) | Requires user interaction for consent |
| Resource Owner Password | Server-to-server backend services | Access: ~2h | Yes | Requires Service Account AccessKey + SecretKey + ClientID + ClientSecret |
| Client Credentials | Machine-to-machine | Access: ~2h | No | Simpler but limited to app-level permissions |
| SAML Bearer | Infor Ming.le embedded apps | Access: ~2h | Yes | Ming.le context only |
| Implicit | Single-page apps (deprecated) | Access: ~2h | No | Deprecated in OAuth 2.1; avoid for new dev |
START -- Integrate with Infor CloudSuite (M3, LN, or CSI)
|-- Which CloudSuite product?
| |-- M3 (CloudSuite Distribution/Fashion/Equipment)
| | |-- Individual record CRUD (< 1,000 records)
| | | --> MIProgram REST: /M3/m3api-rest/execute/{Program}/{Transaction}
| | |-- Bulk data extraction (> 10,000 records)
| | | --> Data Lake + Compass SQL API
| | |-- Event-driven (react to M3 changes)
| | --> ION BOD document flows
| |-- LN (CloudSuite Industrial Enterprise)
| | |-- Standard CRUD (procurement, logistics, finance)
| | | --> OData REST API: /lnapi/odata/tdapi.{resource}
| | |-- Custom entity CRUD --> Model in ttadv2570m700, then OData
| | |-- Complex transactions --> SOAP web services via ION
| | |-- Bulk data --> Data Lake + Compass
| |-- CSI / SyteLine
| |-- IDO object CRUD --> IDO REST web service via ION
| |-- Legacy .NET --> IDO SOAP or .NET extension class
| |-- Event-driven --> ION BOD or IDO Request XML
| |-- Bulk data --> Data Lake + Compass
|-- Data direction?
| |-- Inbound (write) --> REST APIs
| |-- Outbound (read) --> REST (real-time) or Data Lake (bulk)
| |-- Bidirectional --> REST for writes + BOD/Data Lake for changes
|-- Error tolerance?
|-- Zero-loss --> ION BOD with connection point monitoring
|-- Best-effort --> REST API with application-level retry
| Capability | M3 | LN | CSI (SyteLine) |
|---|---|---|---|
| Primary REST Surface | MIProgram REST (/m3api-rest/execute/) | OData v4 (/lnapi/odata/) | IDO REST web services |
| API Transaction Count | 6,000+ pre-built | Must be modeled (ttadv2570m700) | IDO-registered objects only |
| Request Method | GET only | GET, POST, PATCH, DELETE | GET, POST, PUT, DELETE |
| Response Format | JSON or XML | JSON (OData) | JSON or XML |
| URL Pattern | /M3/m3api-rest/execute/{Prog}/{Txn} | /lnapi/odata/tdapi.{Resource} | /IDORequestService/ |
| Pagination | maxrecs matrix param | OData $top, $skip, nextLink | IDO-specific paging |
| Filtering | Query string params | OData $filter, $select, $expand | IDO property filters |
| Event-Driven | ION BOD | ION BOD | ION BOD or IDO Request XML |
| Bulk Data | Data Lake / Compass | Data Lake / Compass | Data Lake / Compass |
| Auth (Cloud) | OAuth 2.0 (ION Gateway) | OAuth 2.0 (ION Gateway) | OAuth 2.0 (ION Gateway) |
| SOAP Support | Limited / legacy | Full SOAP | Full IDO SOAP |
| Standards Compliance | Proprietary REST | OData v4 | Proprietary REST/SOAP |
Navigate to Infor OS > ION API > Authorized Apps. Register your external application and download the .ionapi credentials file. [src5]
{
"ti": "TenantID",
"cn": "ClientName",
"ci": "ClientID_GUID",
"cs": "ClientSecret",
"iu": "https://{tenant}.ionapi.{region}.inforcloudsuite.com",
"pu": "https://{tenant}.ionapi.{region}.inforcloudsuite.com/{tenant}/as/token.oauth2",
"saak": "ServiceAccountAccessKey",
"sask": "ServiceAccountSecretKey"
}
Verify: .ionapi file downloads with all required fields (ci, cs, pu, saak, sask).
Use Resource Owner Password grant for server-to-server. [src5, src8]
curl -s -X POST "{token_endpoint}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "{ClientID}:{ClientSecret}" \
-d "grant_type=password&username={AccessKey}&password={SecretKey}"
Verify: Response contains access_token with expires_in: ~7200.
All M3 API calls use GET through the execute endpoint. [src3]
curl -s "{base}/M3/m3api-rest/execute/CRS610MI/LstByNumber;maxrecs=20?CONO=1" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Verify: Response contains MIRecord array with NameValue pairs. HTTP 200.
LN supports standard OData query operators. [src4]
curl -s "{base}/lnapi/odata/tdapi.PurchaseOrders?$top=10&$select=OrderNumber,Supplier" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Verify: Response contains @odata.context and value array.
# Input: .ionapi credentials file path
# Output: List of M3 customer records
import json
import requests
with open("credentials.ionapi", "r") as f:
creds = json.load(f)
# Acquire token (Resource Owner grant)
token_resp = requests.post(
creds["pu"],
auth=(creds["ci"], creds["cs"]),
data={
"grant_type": "password",
"username": creds["saak"],
"password": creds["sask"],
},
)
access_token = token_resp.json()["access_token"]
# Call M3 MIProgram
headers = {"Authorization": f"Bearer {access_token}", "Accept": "application/json"}
resp = requests.get(
f"{creds['iu']}/M3/m3api-rest/execute/CRS610MI/LstByNumber;maxrecs=100?CONO=1",
headers=headers,
)
for record in resp.json().get("MIRecord", []):
fields = {nv["Name"]: nv["Value"] for nv in record["NameValue"]}
print(f"Customer: {fields['CUNO']} - {fields['CUNM']}")
// Input: .ionapi credentials, LN OData resource
// Output: LN purchase orders
const fetch = require("node-fetch"); // npm install node-fetch@2
const fs = require("fs");
const creds = JSON.parse(fs.readFileSync("credentials.ionapi", "utf8"));
async function getLnData() {
const tokenResp = await fetch(creds.pu, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: `Basic ${Buffer.from(`${creds.ci}:${creds.cs}`).toString("base64")}`,
},
body: `grant_type=password&username=${creds.saak}&password=${creds.sask}`,
});
const { access_token } = await tokenResp.json();
const resp = await fetch(`${creds.iu}/lnapi/odata/tdapi.PurchaseOrders?$top=10`, {
headers: { Authorization: `Bearer ${access_token}`, Accept: "application/json" },
});
console.log("Orders:", (await resp.json()).value);
}
getLnData().catch(console.error);
# IMPORTANT: Store the NEW refresh_token from this response
curl -s -X POST "{token_endpoint}" \
-u "{ClientID}:{ClientSecret}" \
-d "grant_type=refresh_token&refresh_token={your_refresh_token}"
| Aspect | M3 MIProgram | LN OData | CSI IDO |
|---|---|---|---|
| Record structure | MIRecord[].NameValue[] (name/value pairs) | Standard OData entities (key/value JSON) | IDO property collections |
| Field naming | 4-char codes (CUNO, CUNM, ITNO) | Full names (CustomerNumber, ItemDescription) | .NET property names (CustomerNum) |
| Date format | YYYYMMDD as string ("20260302") | ISO 8601 ("2026-03-02T00:00:00Z") | .NET DateTime |
| Null handling | Empty string "" | JSON null | JSON null or absent |
| Boolean | "1"/"0" as string | true/false | true/false |
co_num may be CoNum or CompanyNumber in the IDO layer. Always reference IDO docs, not DB schema. [src6]| Code | Meaning | Cause | Resolution |
|---|---|---|---|
| 401 | Unauthorized | Token expired (>2h) or revoked | Acquire new token; check refresh token validity |
| 403 | Forbidden | Insufficient permissions | Check ION API app permissions and ERP user roles |
| 404 | Not Found | Wrong MIProgram, unpublished LN OData, or unregistered IDO | Verify program/resource exists in API catalog |
| 429 | Too Many Requests | ION Gateway spike arrest triggered | Exponential backoff; respect Retry-After header |
| 500 | Internal Server Error | Backend ERP application error | Check response body for ERP error message |
| NOK (M3) | Transaction rejected | M3 business validation failed | Parse MIRecord error message; check field values |
Always persist the latest refresh_token from every token refresh call. [src8]Always parse response body for @type: ErrorMessage or nrOfFailedTransactions field. [src3]Document all custom API definitions; include re-publication in upgrade runbook. [src4]Monitor ION Desk connection point health with alert notifications. [src7]Validate schema compatibility before upgrading; pin queries to specific versions. [src1]# BAD -- M3 does not use POST/PUT/DELETE methods
requests.post(f"{base}/M3/m3api-rest/execute/CRS610MI/AddAddress",
json={"CUNO": "Y30000", "ADRT": "1"})
# Returns 405 Method Not Allowed
# GOOD -- M3 uses GET for everything; mutation is in the transaction name
requests.get(
f"{base}/M3/m3api-rest/execute/CRS610MI/AddAddress"
"?CONO=1&CUNO=Y30000&ADRT=1&CUA1=123+Main+St",
headers={"Authorization": f"Bearer {token}"}
)
# BAD -- calling an LN endpoint that hasn't been modeled
resp = requests.get(f"{base}/lnapi/odata/tdapi.CustomEntity")
# Returns 404 because the API was never published in ttadv2570m700
# GOOD -- check LN OData API catalog (session ttadv2570m700) before design
# Only use endpoints that appear in the published API list
resp = requests.get(
f"{base}/lnapi/odata/tdapi.PurchaseOrders?$top=1",
headers={"Authorization": f"Bearer {token}"}
)
# BAD -- looping through 100K records via M3 MIProgram
while True: # Takes hours, may hit throttle limits
resp = requests.get(f"{base}/M3/m3api-rest/execute/MMS200MI/LstByNumber;maxrecs=1000")
...
# GOOD -- Data Lake handles millions of records efficiently
resp = requests.get(
f"{base}/DATAFABRIC/compass/v2/schemas/M3/tables/OCUSMA",
headers={"Authorization": f"Bearer {token}"},
params={"$filter": "OKCONO eq 1", "$top": 100000}
)
Use Gateway for sync REST; ION Desk for async BOD flows. [src1, src7]Build a transformer that converts MIRecord[].NameValue[] to flat key-value objects. [src3]Always read base URL from the .ionapi file "iu" field. [src5]Always include CONO in M3 MIProgram calls. [src3]Load-test against sandbox with production-equivalent data volumes. [src1]Implement periodic reconciliation jobs independent of BOD flow. [src7]# Test ION API Gateway authentication
curl -s -X POST "{token_endpoint}" \
-u "{ClientID}:{ClientSecret}" \
-d "grant_type=password&username={AccessKey}&password={SecretKey}" | jq .
# Test M3 API connectivity (list first 5 customers)
curl -s "{base}/M3/m3api-rest/execute/CRS610MI/LstByNumber;maxrecs=5?CONO=1" \
-H "Authorization: Bearer {TOKEN}" -H "Accept: application/json" | jq .
# Test LN OData API connectivity
curl -s "{base}/lnapi/odata/tdapi.PurchaseOrders?$top=1" \
-H "Authorization: Bearer {TOKEN}" -H "Accept: application/json" | jq .
# Check M3 API availability (WADL discovery)
curl -s "{base}/M3/m3api-rest/application.wadl" \
-H "Authorization: Bearer {TOKEN}" | head -50
# Revoke token (cleanup)
curl -s -X POST "{base}/{tenant}/as/revoke_token.oauth2" \
-u "{ClientID}:{ClientSecret}" \
-d "token={TOKEN}&token_type_hint=access_token"
| Change | Date | Impact | Migration Notes |
|---|---|---|---|
| ION API Gateway mandatory for M3 CloudSuite | 2024 | Breaking (on-prem to cloud) | Reroute all direct M3 API calls through ION Gateway with OAuth 2.0 |
| LN REST API Modeler (ttadv2570m700) | 2023 | New feature | Enables custom OData REST API creation for LN |
| Data Lake / Compass SQL API | 2022-2024 | New feature | Preferred method for bulk data extraction |
| Unified ION API Gateway (Infor OS) | 2021-2022 | Architecture change | Single gateway layer; unified OAuth 2.0 |
| M3 BOD Processor replaces Media Management | 2023 | Migration required | Outbound messages via Event Analytics + BOD Processor |
| Use When | Don't Use When | Use Instead |
|---|---|---|
| Comparing API surfaces across M3, LN, and CSI for architecture decisions | Need deep-dive on single product's API | Product-specific API capability card |
| Designing a multi-product Infor integration | Need authentication setup instructions | business/erp-integration/infor-ion-api-authentication/2026 |
| Evaluating which CloudSuite product to integrate with | Need iPaaS/middleware comparison | business/erp-integration/ipaas-infor-integration/2026 |
| Understanding Infor's API landscape before cloud migration | Need on-premise integration patterns | On-prem patterns differ; ION Gateway is cloud-only |
| Capability | M3 | LN | CSI (SyteLine) | Notes |
|---|---|---|---|---|
| API Style | MIProgram REST (GET-only) | OData v4 REST | IDO REST/SOAP | LN most standards-compliant |
| Pre-built Coverage | 6,000+ transactions | Must model (ttadv2570m700) | IDO-registered only | M3 broadest out-of-the-box |
| HTTP Methods | GET only | GET, POST, PATCH, DELETE | GET, POST, PUT, DELETE | M3 encodes mutations in txn names |
| Response Format | NameValue pair arrays | Standard OData JSON | IDO property collections | M3 requires custom parsing |
| Query Filtering | Query string params | OData $filter, $select, $expand | IDO property filters | LN richest query language |
| Pagination | maxrecs matrix param | OData $top/$skip/nextLink | IDO-specific | LN follows OData standard |
| Event-Driven | ION BOD (Event Analytics) | ION BOD (direct) | ION BOD or IDO Request XML | All share ION infrastructure |
| Bulk Data | Data Lake + Compass | Data Lake + Compass | Data Lake + Compass | Shared Infor OS capability |
| Authentication | OAuth 2.0 (ION Gateway) | OAuth 2.0 (ION Gateway) | OAuth 2.0 (ION Gateway) | Identical auth layer |
| Developer Tooling | M3 API Repository | REST API Modeler | Mongoose / IDO dev | M3 most mature tooling |
| SOAP Support | Limited / legacy | Full | Full (IDO SOAP) | M3 is REST-first |