Skip to content
MultigateAPI
Support Staff

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.data
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:

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.

Deep pages are refused on the customer list

List customers refuses a request that would skip more than 100,000 customers (for example pageOffset=202 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.