# Paging M3 API MI List Transactions Past the Default Record Limit

> Source: https://netray.co/erp-help/m3-api-mi-list-transaction-pagination-maxreturnedrecords
> Publisher: Netray (netray.co), AI and integration engineering for ERP and manufacturing systems.
> Section: ERP Help

## Short answer

M3 List transactions (the read/browse transaction most MI programs expose, such as CRS610MI.LstByNumber or OIS100MI.LstOrderHead) cap the rows returned per call using the MaxReturnedRecords input field, and by default many clients leave it low or unset, which looks like the API silently truncating results. Set MaxReturnedRecords explicitly, then loop the call using the last key values from the previous page as the starting position until fewer rows than the limit come back.

## Kind

advanced

## System

infor-m3

## Erp

Infor M3 (M3 Business Engine)

## Module

M3 API / MI Programs

## Query

M3 MI List transaction only returns 100 records - how do I page through more

## Alternate Queries

- M3 API MaxReturnedRecords parameter
- M3 API MoreDataExist flag pagination
- how to get more than 100 records from M3 MI List
- M3 API NextStartAt continuation key

## Applies To

Infor M3 Business Engine 10.x-14.x, all List-type MI transactions over MvxAPI, m3api-rest and ION API

## Steps

### Page through a full M3 List result set

**Items:**

Identify the List transaction for the program you need (naming is usually LstByNumber, Lst, or Select - check the program's transaction list, not just the program name).

Set MaxReturnedRecords explicitly on every call; do not rely on the adapter default, since m3api-rest, MvxAPI and different ION flow nodes do not all default to the same value.

Send the first call with the starting key fields left at their lowest meaningful value (often blank or zero) to start from the beginning of the range.

Read the returned rows and note the key field values of the last row returned - these become the starting key values for the next call.

Re-issue the List call with those key values as the new starting position; most M3 List transactions are exclusive of the starting key, so the next page begins immediately after it.

Stop looping when the number of rows returned is less than MaxReturnedRecords - that is the standard signal you have reached the end, since M3 List transactions do not return an explicit hasMore flag on most programs.

For high-volume extracts, keep MaxReturnedRecords in the low hundreds rather than maxing it out in one call; very large single responses increase timeout risk on the API Gateway and on ION flows.

If you are calling through ION API, watch the flow's own step timeout separately from the M3 API Gateway timeout - a large List call can exceed the flow timeout even when M3 itself would have returned in time.

## Sections

### Why results look capped at 100

**Body:**

A lot of first M3 integrations hit this because whatever sample code or low-code connector they started from either omits MaxReturnedRecords entirely or hardcodes a small value like 100 as a safe default. The API is not silently dropping data - it is honoring the limit you gave it, explicitly or by omission. Anyone who reports 'M3 API only returns 100 rows no matter what I query' has almost always left this field unset or capped low somewhere in the call chain.

Different adapters behave slightly differently when the field is omitted: some pass through to the underlying MI program's own internal default, others substitute their own connector-level default. If you cannot find where the 100 is coming from, log the exact outbound request XML/JSON so you can see whether your code, your middleware, or the adapter default is responsible.

### Key-based paging, not offset paging

**Body:**

M3 List transactions page by key value, not by row offset - there is no SKIP/TAKE style parameter on most programs. This means paging correctness depends on the sort order of the key fields matching a stable, unique sequence; if the underlying data changes between calls (a row is inserted between page 3 and page 4), you can see a duplicate or a gap. For extracts that must be exactly consistent, take a snapshot approach: capture a timestamp or sequence field at the start of the run and filter on it, rather than relying purely on natural key ordering across a long-running paged extract.

**Code:**

Call 1: OIS100MI.LstOrderHead
  MaxReturnedRecords=200, ORNO="" (start)
Response: 200 rows, last ORNO="0000005210"

Call 2: OIS100MI.LstOrderHead
  MaxReturnedRecords=200, ORNO="0000005210" (continue after)
Response: 87 rows -> fewer than 200 -> end of set

### Where this breaks in low-code tools

**Body:**

Low-code integration platforms (Boomi, Workato, Power Automate connectors, and similar) that wrap M3 API often hide the MaxReturnedRecords field behind a generic 'batch size' setting, or worse, do not expose it at all and silently apply their own default. When an extract in one of these tools looks truncated, check the connector's advanced or raw-parameter view before assuming the M3 side is at fault - most of these tools do let you pass MaxReturnedRecords through if you dig into the raw call configuration.

## Pitfalls

- Assuming there is an offset or page-number parameter - M3 List transactions page by last key value, not by row number.
- Leaving MaxReturnedRecords unset and blaming the API for a silent 100-row cap that actually came from a connector default.
- Using a non-unique or non-sequential field as the paging key, which can produce duplicate or skipped rows across pages.
- Setting MaxReturnedRecords too high in one call to 'avoid paging', which increases timeout risk on the API Gateway or the calling middleware.
- Not accounting for data changing between page calls in a long-running extract, causing inconsistent snapshots.
- Treating a page returning zero rows as an error rather than the normal end-of-data condition.

## Ai Angle

When a report or agent built on ERPray needs a full M3 dataset rather than a single lookup, it handles the List-transaction paging loop itself - setting MaxReturnedRecords, tracking the continuation key, and stopping at the natural end of the set - so the person asking the question just gets the complete answer instead of having to notice the result was silently truncated at 100 rows.

## Faq

### What is a safe MaxReturnedRecords value for interactive queries?

**Answer:** For an interactive lookup feeding a screen or a chat answer, 20-50 rows is usually enough and keeps response time low. For batch extracts, 200-500 balances fewer round trips against per-call timeout risk; test against your specific ION or API Gateway timeout settings.

### Is there a total record count field I can check before paging?

**Answer:** Most List MI transactions do not return a total count up front, since M3 evaluates and returns rows without a separate counting pass. If you need an approximate count first, a targeted MI Get or a small List call against a narrower filter is more reliable than assuming a count field exists.

### Does this pagination pattern apply to ION API the same way as direct MI calls?

**Answer:** Yes - ION API and m3api-rest both pass MaxReturnedRecords and the key-based continuation through to the same underlying MI List transaction, so the paging logic in your calling code does not need to change based on which adapter you use.

### Why did paging return a duplicate row on the boundary between two pages?

**Answer:** This usually means the starting key on the second call was set to the last row returned rather than the value immediately after it, or the sort key is not unique enough to guarantee an unambiguous cut point. Confirm the List transaction's exclusive-versus-inclusive behavior for the specific starting-key field you are using.

## Search terms

M3 API pagination, M3 MI List MaxReturnedRecords, M3 API only returns 100 records, M3 API continuation key, m3api-rest pagination, M3 List transaction paging, MvxAPI batch extract, M3 API Gateway timeout, ION API M3 List transaction, OIS100MI LstOrderHead paging

---
Talk to an engineer: https://netray.co/contact?intent=erp_ai | Machine catalog: https://netray.co/agent/catalog.json
