Infor M3 EXPORTMI Select Query Generator (REST URL, curl and paging loop)
This generator builds an EXPORTMI Select call for M3 Business Engine 13.x on-prem: the decoded query, the REST request, a curl command and a Python loop that pages by key range. Use it when no standard Lst transaction returns the columns you need from a single table.
Fill in
Example only: use the HTTPS port your M3 BE grid exposes for m3api-rest.
MITMAS uses index 00. MITMAS80 would use index 80.
Decoded QERY (first page)
MMITNO,MMITDS,MMSTAT from MITMAS where MMSTAT = '20'
HTTP request (URL-encode SEPC and QERY before sending)
GET https://m3be.acme.local:21108/m3api-rest/execute/EXPORTMI/Select;cono=100;maxrecs=10000?SEPC=<encoded ;>&HDRS=1&QERY=<url-encoded query above> Authorization: Basic <base64 of M3SRVINT:password> Accept: application/json
curl (encodes the parameters for you)
curl -s -G -u "M3SRVINT" -H "Accept: application/json" \ "https://m3be.acme.local:21108/m3api-rest/execute/EXPORTMI/Select;cono=100;maxrecs=10000" \ --data-urlencode "SEPC=;" \ --data-urlencode "HDRS=1" \ --data-urlencode "QERY=MMITNO,MMITDS,MMSTAT from MITMAS where MMSTAT = '20'"
Next page by key range (decoded QERY)
MMITNO,MMITDS,MMSTAT from MITMAS where MMSTAT = '20' and MMITNO > 'A-10450'
Python: page through the whole table by key range
import os
import requests
BASE = 'https://m3be.acme.local:21108/m3api-rest/execute/EXPORTMI/Select;cono=100;maxrecs=10000'
COLUMNS = 'MMITNO,MMITDS,MMSTAT'
KEY = 'MMITNO'
SEP = ';'
PAGE = 10000
cols = [c.strip() for c in COLUMNS.split(',')]
key_idx = cols.index(KEY)
s = requests.Session()
s.auth = ('M3SRVINT', os.environ['M3_PASSWORD'])
s.headers['Accept'] = 'application/json'
rows = []
last = ''
while True:
q = COLUMNS + ' from MITMAS where MMSTAT = '20''
if last:
q += ' and ' + KEY + " > '" + last + "'"
r = s.get(BASE, params={'SEPC': SEP, 'HDRS': '0', 'QERY': q}, timeout=300)
r.raise_for_status()
data = r.json()
if 'Message' in data and 'MIRecord' not in data:
raise SystemExit('M3 error: ' + data['Message'])
recs = data.get('MIRecord', [])
if not recs:
break
for rec in recs:
rows.append(rec['NameValue'][0]['Value'])
last = rows[-1].split(SEP)[key_idx].strip()
print('fetched', len(rows), 'rows, last key', last)
if len(recs) < PAGE:
break
with open('MITMAS_export.csv', 'w', encoding='utf-8') as f:
f.write(SEP.join(cols) + '\n')
for line in rows:
f.write(line + '\n')Verify on your 13.x server before relying on it: the base path and port of m3api-rest on your grid, that matrix parameters cono and maxrecs are accepted (they are on the classic m3api-rest execute endpoint), and the JSON shape (MIRecord list with NameValue pairs). EXPORTMI reads one table only, needs a table that contains the company field, and does not allow a company filter: set the company on the session instead. Keywords from, where, and, or must be lowercase with one space on each side, and so must operators.
Get your extract query reviewed
Send the table, filter and volume and we will check the index choice and paging approach against your M3 13.x setup.
Optional. The tool and every export work without this. No spam.
How to use it
Enter the host and port of m3api-rest, the table and the columns you want, always with the table prefix (MMITNO, not ITNO). Write the filter without the company field: EXPORTMI does not support company selection and always uses the company of the API session, which the generator sets with the cono matrix parameter. Pick a separator for SEPC and whether the first record should carry column names (HDRS = 1). The curl block URL-encodes the parameters for you, which avoids the most common failure: an unencoded quote, semicolon or space in QERY.
- List columns explicitly; select * is allowed but slower
- Keep the output to roughly 10 fields or fewer for speed
- Use the index suffix (for example MITMAS80) when your filter matches that index
- Lowercase from, where, and, or, each with single spaces around them
The 10,000 record cap and key-range paging
Infor documents that EXPORTMI returns at most 10,000 records per call, except when you name an index with filter values that match it. The safe pattern for a large table is to page by the leading key of the index. MITMAS read through index 00 comes back in item number order, so after each page you take the last MMITNO and ask for MMITNO greater than that value. The Python block does exactly this with HDRS = 0 on every call, stops when a page returns fewer rows than the page size, and writes one CSV. Include the key field in your column list, or the loop cannot read the last value.
Worked example
For company 100, active items (status 20) with number, description and status: QERY is MMITNO,MMITDS,MMSTAT from MITMAS where MMSTAT = '20'. With SEPC ; and HDRS 1 the first record holds the column names, then each record is one delimited row in a single output field. If the call returns exactly 10,000 rows, run the next-page query with the last item number, for example MMITNO > 'A-10450'. Check the first and last rows of each page on the MMS001 panel to confirm the filter did what you expected.
Performance and when to use something else
An unindexed filter makes EXPORTMI scan the table, which is slow on MITTRA, FGLEDG or similar large files and competes with interactive users. If you read the same table repeatedly with the same keys, add an MDBREADMI transaction on an existing index through MRS001, MRS002 and MRS003 instead: it is the API Infor recommends when no standard API exists. For full-table extracts every night, a replicated reporting database or Data Lake is cheaper than any API loop. Joins are not possible in EXPORTMI; use a CMS100MI custom list for those.
Frequently Asked Questions
How do I page through more than 10,000 records with the Infor M3 API?
EXPORTMI and CMS100MI return at most 10,000 records per call. Page by key range: sort by an index, take the last key value from the page and request key greater than that value until a page comes back short. Using an index that matches your filter is both faster and the documented exception to the cap.
What do SEPC, HDRS and QERY mean in EXPORTMI Select?
SEPC is the separator between field values: blank gives fixed-width output with trailing spaces, any character gives trimmed delimited values. HDRS = 1 makes the first record contain the field names. QERY is the SQL-like query without the word select, for example MMITNO,MMITDS from MITMAS where MMSTAT = '20'.
Why does my EXPORTMI query return nothing or an error?
Typical causes are field names without the table prefix, uppercase AND or WHERE, missing spaces around operators, a company field in the filter, or a query that was not URL-encoded so a semicolon or quote broke the request. Also check the user's company: EXPORTMI only reads the session company.
Can EXPORTMI join two M3 tables?
No. EXPORTMI reads one table and the table must contain the company field. For a join, define a CMS100MI custom list, or read each table separately and join in your integration layer. For repeated single-table reads on a known index, an MDBREADMI transaction is faster.
If your team pulls M3 tables by hand like this, we can put a private assistant on your own servers that answers those questions from M3 data with the query shown.
Related Tools
Infor M3 MDBREADMI and Custom List API Design Worksheet
Plan each custom M3 read API row by row: which API type, which table and index, which output fields, who calls it and how often, with a warning above 10 output fields.
Developer ToolsInfor M3 ION API Gateway OAuth 2.0 Python Client Generator
Generate a Python script that loads your .ionapi credentials file, gets and reuses an OAuth 2.0 token, and calls an M3 MI transaction through the on-prem ION API Gateway.
Developer ToolsInfor M3 CSV to MI API Bulk Loader Script Generator
Generate a Python loader that reads a CSV, maps columns to MI fields, calls one M3 transaction per row and writes a result file with the M3 message for every failed row.
Infor M3 & CloudSuiteInfor M3 Core Database Tables Reference
Look up the main M3 tables, their two-letter column prefix and the key fields you join on. Searchable and exportable.
Infor M3 & CloudSuiteInfor M3 MI API Transaction Call Generator
Fill in program, transaction and parameters to get a ready M3 REST call as URL, curl and a JavaScript fetch snippet.
More Developer Tools tools
See all- Infor M3 H5 Script TypeScript Template Generator
- Infor M3 EXPORTMI Extraction Call Volume 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
- SAP QM Inspection Lot ABAP SELECT Generator
- SAP Quality Notification Pareto SQL Query Generator
- SAP QM Usage Decision BAPI Skeleton
Keep exploring
Free tools
- Infor M3 EXPORTMI Extraction Call Volume CalculatorPlan paged extracts from M3 through EXPORTMI or Lst transactions: calls per run, elapsed minutes and daily call volume under a record cap.
- Infor M3 Private AI Layer Blueprint GeneratorFill in your Infor M3 environment and get a ready-to-share architecture plan for a private, on-prem AI assistant.
- Infor M3 MI API Transaction Call GeneratorFill in program, transaction and parameters to get a ready M3 REST call as URL, curl and a JavaScript fetch snippet.