Concepts
Pagination
List endpoints return results one page at a time. You choose the page and its size with query parameters, and the response tells you how many pages exist. The parameter names and the response shape differ between endpoints, so check the table below before you write a loop.
Request
Every list takes a page number and pageSize. The page number's name depends on the endpoint: pageNumber or pageOffset. Both mean the page to return, starting at 1 (pageOffset is not a row offset). A parameter an endpoint doesn't read is ignored, so with the wrong name you always get page 1.
| Endpoint | Page parameter | Default pageSize |
Maximum pageSize |
Order | Items in |
|---|---|---|---|---|---|
| Find transfers | pageNumber |
10 | 100 | Newest first | data |
| List banks | pageNumber |
10 | 100 | Oldest first | data |
| List customers | pageOffset |
10 | 500 | Newest first (sortField, sortDirection) |
data |
| List accounts | pageOffset |
10 | none | Newest first | data |
| List beneficiaries | pageOffset |
10 | none | Oldest first (sortField, sortDirection) |
data |
| List receivables | pageOffset |
10 | 100 | Newest first | data |
| List conversions | pageOffset |
10 | 100 | Newest first (sortField, sortDirection) |
items |
| Get account transactions | pageOffset |
10 | 1000 (above it, an empty list) | Newest first | data |
| Get an account statement | pageOffset or pageNumber |
100 | none | Newest first | statement. |
| List banks you can link | pageNumber |
20 | 50 | Newest first | banks |
| Search linking requests | pageNumber |
10 | none | Newest first | accounts |
| List letters of credit | pageNumber |
10 | 100 | Depends on the filters (sortField, sortDirection) |
data |
| List export letters of credit | pageNumber |
10 | 100 | Newest first | data.data (page fields inside data too) |
| List import letters of credit | pageNumber |
10 | 100 | Newest first | data |
| List guarantees | pageNumber |
10 | 100 | Last updated first (sortField, sortDirection) |
data |
| List inward guarantees | pageNumber |
10 | 100 | sortField, sortDirection |
data |
| List outward guarantees | pageNumber |
10 | 100 | Newest first | data |
| List lifecycle alerts | pageNumber |
10 | 100 | Newest first | data |
A pageSize above the maximum isn't rejected: you get the maximum. The exception is Get account transactions, which returns an empty list for a pageSize above 1000. Where there is no maximum, keep pageSize at 100 or less so responses stay fast.
curl "$MG_BASE_URL/client-service/api/v1/beneficiaries?pageOffset=2&pageSize=50" \
-H "mp-api-key: $MG_API_KEY"
Response
Most lists put the items in data and the paging details beside it:
{
"data": [
{ "entityId": "c0a8012e-…", "accountName": "Ada Okafor" }
],
"totalItems": 137,
"pageSize": 50,
"currentPage": 2,
"totalPages": 3
}
| Field | Meaning |
|---|---|
data |
The items on this page. |
totalItems |
Total items matching your filters, across all pages. |
pageSize |
Page size used. It can be lower than you asked for if you went above the maximum. |
currentPage |
The page returned. |
totalPages |
Pages available at this page size. 0 when nothing matches. |
The exceptions:
- List conversions returns
count(total items) anditems, with no page fields. - List receivables returns
data,count(items on this page) andtotalCount(all matching items), with no page fields. - List banks you can link returns the items in
banks, and Search linking requests inaccounts, beside the usual page fields. - Get an account statement nests the items and the page fields in
statement:statement.,data statement.,page statement..total Pages - List accounts and List beneficiaries answer
404("account not found", "beneficiary not found") instead of an empty page when nothing matches, including when you ask for a page past the last one.
Reading every page
This function reads every page of any list in the table, whatever its shape. It uses callMultigate from the error handler.
import { callMultigate, Outcome } from './multigate.js'; // the handler from the Errors page
const PAGE_SIZE = 100;
// path: for example '/client-service/api/v1/beneficiaries'
// pageParam: 'pageNumber' or 'pageOffset', from the table above
export async function listAll(path, pageParam, filters = {}) {
const items = [];
for (let page = 1; ; page += 1) {
const url = new URL(`${process.env.MG_BASE_URL}${path}`);
for (const [name, value] of Object.entries(filters)) url.searchParams.set(name, value);
url.searchParams.set(pageParam, String(page));
url.searchParams.set('pageSize', String(PAGE_SIZE));
const result = await callMultigate(url.toString()); // sends MG_API_KEY
if (result.status === 404 && isEmptyListError(result)) return items; // accounts and beneficiaries
if (result.outcome !== Outcome.SUCCESS) {
throw new Error(`Page ${page} failed with HTTP ${result.status}: ${result.errors[0]?.message}`);
}
const { pageItems, isLastPage } = readPage(result.body, page, items.length);
items.push(...pageItems);
if (isLastPage || pageItems.length === 0) return items;
}
}
function readPage(body, page, itemsSoFar) {
if (Array.isArray(body.items)) {
// List conversions: { count, items }
return { pageItems: body.items, isLastPage: itemsSoFar + body.items.length >= body.count };
}
if (typeof body.totalCount === 'number') {
// List receivables: { count, totalCount, data }
return { pageItems: body.data, isLastPage: itemsSoFar + body.data.length >= body.totalCount };
}
const container = body.statement ?? body; // Get an account statement nests everything in `statement`
const pageItems = container.data ?? container.banks ?? container.accounts ?? [];
return { pageItems, isLastPage: page >= container.totalPages };
}
function isEmptyListError(result) {
return result.errors.some((e) => e.message === 'account not found' || e.message === 'beneficiary not found');
}
A 404 with "Resource not found" is not an empty list: it means your API user lacks the permission for that list.
List customers refuses a request that would skip more than 100,000 customers (for example page with pageSize=500) with HTTP 422. Narrow the results with filters instead of paging that far.
Ordering and changing data
The Order column above gives each list's default order. If new items are created while you page through a list, an item can move to the next page and appear twice, or (on oldest-first lists) new items appear on the last page. To get a stable snapshot, filter by a date range that ends in the past, and de-duplicate by ID.