Infor Data Lake Compass SQL API Request Generator (Python and curl)
This generator writes Python and curl code for the Infor Data Lake Compass v2 query API: submit a SQL job, poll its status, then download the result in pages with offset and limit. It targets Infor OS tenants that call Compass through the Data Fabric suite of the ION API Gateway.
Fill in
Use the data object name as shown in Data Lake Atlas or the Data Catalog.
Python: submit, poll and page a Compass v2 query
# Requires: pip install requests
# Token: create an ION API backend service client and get a bearer token
# from the token endpoint in the .ionapi file (pu + ot), then export it as ION_TOKEN.
import os
import time
import requests
BASE = "https://mingle-ionapi.inforcloudsuite.com/ACME_PRD/DATAFABRIC/compass/v2"
TOKEN = os.environ["ION_TOKEN"]
PAGE_LIMIT = int("10000")
POLL_SECONDS = float("5")
ACCEPT = "application/x-ndjson"
SQL = """SELECT * FROM YourDataObject LIMIT 100"""
session = requests.Session()
session.headers.update({"Authorization": "Bearer " + TOKEN})
def call(method, url, **kwargs):
"""One HTTP call with backoff on 429 and a clear message on 404."""
for attempt in range(6):
resp = session.request(method, url, timeout=300, **kwargs)
if resp.status_code == 429:
# Per-tenant per-minute quota hit: back off and retry
time.sleep(min(60, 2 ** attempt))
continue
if resp.status_code == 404:
raise RuntimeError(
"404 Query not found. Check the queryId, the tenant in the URL, that the "
"same principal (client) submitted the job, that results have not expired, "
"and the Accept header. Body: " + resp.text[:500]
)
resp.raise_for_status()
return resp
raise RuntimeError("Still rate limited (429) after retries: " + url)
# 1) Submit the SQL as a job (body is plain text)
submit = call(
"POST",
BASE + "/jobs/",
data=SQL.encode("utf-8"),
headers={"Content-Type": "text/plain"},
)
query_id = submit.json()["queryId"]
print("queryId:", query_id)
# 2) Poll status until the job ends
while True:
st = call("GET", BASE + "/jobs/" + query_id + "/status/").json()
status = st.get("status")
if status == "FINISHED":
row_count = st.get("rowCount")
print("FINISHED, rowCount:", row_count)
break
if status in ("FAILED", "CANCELLED"):
# For FAILED jobs the result call returns the error details
detail = call("GET", BASE + "/jobs/" + query_id + "/result/", headers={"Accept": ACCEPT})
raise RuntimeError(status + ": " + detail.text[:2000])
time.sleep(POLL_SECONDS)
# 3) Fetch result pages with offset and limit
extension = ".csv" if ACCEPT == "text/csv" else ".ndjson"
out_path = "compass_" + query_id + extension
offset = 0
header = None
written = 0
with open(out_path, "w", encoding="utf-8", newline="") as out:
while True:
page = call(
"GET",
BASE + "/jobs/" + query_id + "/result/",
params={"offset": offset, "limit": PAGE_LIMIT},
headers={"Accept": ACCEPT},
)
lines = [ln for ln in page.text.splitlines() if ln.strip()]
if ACCEPT == "text/csv" and lines:
if header is None:
header = lines[0]
out.write(header + "\n")
if lines[0] == header:
lines = lines[1:]
for ln in lines:
out.write(ln + "\n")
written += len(lines)
offset += PAGE_LIMIT
if len(lines) < PAGE_LIMIT:
break
if row_count is not None and offset >= int(row_count):
break
print("Wrote", written, "rows to", out_path)curl equivalent (bash, needs jq)
BASE="https://mingle-ionapi.inforcloudsuite.com/ACME_PRD/DATAFABRIC/compass/v2"
TOKEN=$(printenv ION_TOKEN)
cat > query.sql <<'EOF'
SELECT * FROM YourDataObject LIMIT 100
EOF
# 1) Submit
QUERY_ID=$(curl -s -X POST "$BASE/jobs/" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: text/plain" \
--data-binary @query.sql | jq -r '.queryId')
echo "queryId: $QUERY_ID"
# 2) Poll status
while true; do
STATUS=$(curl -s "$BASE/jobs/$QUERY_ID/status/" -H "Authorization: Bearer $TOKEN" | jq -r '.status')
echo "status: $STATUS"
case "$STATUS" in
FINISHED) break ;;
FAILED|CANCELLED) curl -s "$BASE/jobs/$QUERY_ID/result/" -H "Authorization: Bearer $TOKEN"; exit 1 ;;
esac
sleep 5
done
# 3) First result page (repeat with offset=10000, 2x10000 ... until a short page)
curl -s "$BASE/jobs/$QUERY_ID/result/?offset=0&limit=10000" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/x-ndjson" \
-o page_0.outLimits to design around
| Item | Documented behaviour |
|---|---|
| Result page size | limit up to 100,000 rows per call, with a 10 MB cap per page |
| Result retention | Roughly 20 hours after the job reaches FINISHED |
| Who can read results | Only the tenant and principal that submitted the job |
| Rate limits | Per-tenant per-minute quotas apply to the jobs, status and result endpoints; a 429 means back off. Check the current values in the Data Fabric API documentation |
| Status values handled here | RUNNING, FINISHED, FAILED, CANCELLED (any other value is treated as still in progress) |
Verify on your tenant before production use: open the Infor Data Fabric suite in API Gateway and compare the Compass v2 paths, verbs and parameters with this code (newer tenants expose Compass under the Data Fabric suite; older material may show it under the ION API suite). Page limits, quotas and retention come from the Infor OS Data Fabric documentation and can change between releases.
Get your Compass extract reviewed
Send us your SQL, data object and volume and we will suggest partition filters, page size and a schedule that stays inside your tenant quotas.
Optional. The tool and every export work without this. No spam.
How to use it
Open your downloaded .ionapi file and copy the iu value (the ION API base URL) and ti value (the tenant). Get a bearer token for a backend service client from the token endpoint in the same file, export it into the environment variable you named, and paste your SQL. The SQL runs against Data Lake data objects, so use object names as they appear in Atlas or the Data Catalog. Pick NDJSON when you want one JSON object per row for loading into Python or a warehouse, or CSV for spreadsheets. Keep the page size well below 100,000 if rows are wide, because the 10 MB page cap applies first.
- Run a COUNT(*) version of the query first to see how many pages you will pull.
- Store the queryId: you can re-read pages for about 20 hours without re-running the SQL.
- Run the script under the same API client that submitted the job.
How the Compass v2 flow works
Compass is asynchronous. The jobs call accepts the SQL as a text/plain body and returns a queryId straight away. The status call reports RUNNING until the engine ends with FINISHED, FAILED or CANCELLED; a FINISHED status includes the total rowCount. Only then do you call result. Version 2 differs from version 1 in that the result is returned in row sets: offset is a 0-based row position and limit is the page size, and both apply only to the result call. The script loops offset by the page size and stops on a short page or when it reaches rowCount. For a FAILED job, the result call returns the error text, which is usually a SQL or data object name problem.
- POST .../jobs/ submits, GET .../jobs/{queryId}/status/ polls, GET .../jobs/{queryId}/result/ pages.
- Content-Type text/plain is required on submit; a different type is rejected.
- Accept selects text/csv or application/x-ndjson for the result.
Errors you will actually see
A 404 Query not found on status or result nearly always means one of four things: the queryId was mistyped or truncated, the tenant in the URL differs from the one that submitted, a different API client (principal) is asking, or the result expired after about 20 hours. A 429 means a per-tenant per-minute quota was hit, so batch work into fewer, larger queries rather than one query per record. A 401 means the token expired; tokens are short-lived, so long downloads should refresh the token between pages.
- Poll status every few seconds, not in a tight loop, to stay inside the status quota.
- Add WHERE clauses on partition or date fields to keep jobs short.
When Compass is the wrong tool
Compass is built for analytical pulls and extracts from the Data Lake, not for transactional lookups. If you need one record in real time, call the source application API through ION API instead. If you need a recurring feed into another system, an ION data flow or Data Lake flow is usually easier to monitor than a scheduled script. For BI tools there is also a Compass JDBC driver, which handles paging for you. Use this generated script for one-off extracts, data science notebooks and lightweight scheduled jobs where you control the code.
Frequently Asked Questions
What is Infor Data Lake?
Infor Data Lake is the storage layer of Infor OS Data Fabric. ION and other publishers load data objects from Infor applications such as M3, LN and CloudSuite Industrial into it, and you query them with Compass SQL through the Compass UI, the JDBC driver or the Compass REST API shown here.
What is the difference between Compass v1 and v2?
Version 1 returns the whole result set in one result call. Version 2 returns it in pages, with offset and limit parameters on the result call, so large extracts do not need one huge response. In both versions the SQL is the body of the jobs call.
How do I get a token for the ION API Gateway?
In Infor OS, register an authorized app as a backend service in ION API, download its .ionapi credentials file, then request a token from the token endpoint built from the pu and ot values using the client and service account credentials in that file. Pass it as a Bearer token.
Why do I get 404 Query not found right after submitting?
Check that the status call uses exactly the returned queryId and the same tenant, and that the same API client makes both calls, because results are visible only to the submitting principal. If it worked earlier and fails now, the roughly 20 hour retention window may have passed.
If you want people to ask questions of your Infor Data Lake in plain English on infrastructure you control, we can build that layer on top of these same Compass calls.
Related Tools
Infor EAM Work Order Backlog and PM Schedule SQL Generator
Read-only SQL for Infor EAM and HxGN EAM: backlog by department, oldest open work orders, estimated vs booked hours, PM schedule for the year and PM on-time results.
Maintenance & ReliabilityInfor EAM / HxGN EAM Work Management Table Reference (R5 Tables)
The R5 tables behind work orders, equipment, PM schedules, labor, stores and cases in Infor EAM 11.x and HxGN EAM 12, with key columns and common joins.
Infor M3 & CloudSuiteInfor Factory Track Installation and Go-Live Checklist (CSI)
A 37-item checklist for installing or enabling Infor Factory Track with CloudSuite Industrial, from version compatibility to labels, devices, pilot and hypercare.
More Developer Tools tools
See all- Infor ION API Gateway OAuth Token Request Generator (.ionapi)
- Infor ION BOD XML Shell Generator
- Infor ION Connection Point Types Reference (On-Premises and Cloud)
- Infor ION On-Premises Grid and Connector Health Checklist
- Infor OS ION API and API Flow Payload and Timeout Calculator
- SAP Sales Order ABAP SELECT Generator (VBAK, VBAP, VBFA)
- SAP Sales Order Create BAPI ABAP Generator (BAPI_SALESORDER_CREATEFROMDAT2)
- SAP ABAP Open Items SELECT Generator
- SAP ACDOCA SQL Query Generator
Keep exploring
Free tools
- SyteLine ION API IDO Request GeneratorTurn a .ionapi backend service file into working PowerShell and curl calls that load SyteLine IDO data through ION API, including bookmark paging.
- NetSuite REST API SuiteQL Request GeneratorTurn a SuiteQL statement into a ready POST to the REST query/v1/suiteql endpoint, plus curl and a Python script that pages through every result.
- Infor ION API Gateway OAuth Token Request Generator (.ionapi)Turn the values in a downloaded .ionapi file into code that requests a token from the Infor authorization server, calls the ION API Gateway and revokes the token.
ERP fixes and how-tos
- How to query Infor Data Lake with Compass SQLHow to run a SQL query against Infor Data Lake with Compass: finding the right schema, filtering large BOD tables, and exporting the results safely.
- Infor Data Lake Compass API: Submit a Query, Poll and Fetch ResultsHow the Compass API works in Infor Data Lake: submit SQL as a job, poll status, page results, and handle timeouts, with a Python outline and common errors.
- Connect a Birst Space to Infor Data Lake and build a reportHow to connect a Birst Space to Infor Data Lake with a Live Access source, build the logical model, and publish a secured dashboard to Infor OS.
Guides
- Infor Data Lake Setup and Analytics ConfigurationConfigure Infor Data Lake for CloudSuite Industrial with data replication, schema mapping, Birst analytics integration, and custom reporting for enterprise insights.
- Infor Data Lake: Analytics Setup and Optimization GuideSet up and optimize Infor Data Lake for manufacturing analytics. Data ingestion, Birst integration, custom reports, and performance tuning guide.
- Managing the SyteLine Integration Server InfrastructureManage SyteLine integration server components including ION Connect, BODs, data lake connectors, and middleware. Admin guide for Infor CloudSuite Industrial integrations.
Integrations
- How to connect Power BI to Infor M3How to connect Power BI to Infor M3: Data Lake and Compass, direct database, or API options, on-prem gateway, key manufacturing dashboards, and natural-language Q&A.
- How to connect Power BI to Infor LNHow to connect Power BI to Infor LN: direct database, ION and Data Lake options, on-prem data gateway, key manufacturing dashboards and adding natural-language Q&A.