Concepts

Pagination

Read long lists a page at a time with offsets or cursors.

Actions that return lists return one page at a time. They use one of two styles, and each action's reference page shows which fields it takes.

Offset pages

Most lists take limit and offset. Ask for the next page by adding the number of records you already have to offset, and stop when a page comes back shorter than limit. callOatmilk is the helper from Retrying safely.

curl -G https://app.getoatmilk.com/api/v1/accounting/entries.list \
  -H "Authorization: Bearer $OATMILK_API_KEY" \
  --data-urlencode 'limit=100' \
  --data-urlencode 'offset=0'
all-entries.js
const entries = [];
for (let offset = 0; ; offset += 100) {
  const page = await callOatmilk("entries.list", { limit: 100, offset, from: "2026-09-01", to: "2026-09-30" });
  entries.push(...page);
  if (page.length < 100) break;
}

Cursor pages

Lists that change quickly, such as attention.mine and inbox.list, return items with a nextCursor. Pass it back as cursor to get the next page. When nextCursor is null, you have everything.

curl -G https://app.getoatmilk.com/api/v1/accounting/attention.mine \
  -H "Authorization: Bearer $OATMILK_API_KEY" \
  --data-urlencode 'limit=25'
attention.mine response
{
  "data": {
    "total": 1,
    "cards": [
      "4242"
    ],
    "items": [
      {
        "id": "7f0f6c1e-1c1f-4b5e-9c8d-2f5e8e3c1a10",
        "merchant": "Synthetic Office Supply",
        "date": "2026-09-18",
        "currency": "CAD",
        "amountMinor": "4520",
        "lastFour": "4242"
      }
    ],
    "nextCursor": null
  }
}

Cursors don't skip or repeat records when new ones arrive between pages, which offsets can.

Keep pages small

Ask for what you need. A page of 100 is quick to read and keeps you well inside the rate limit. Filter on the server with fields like from, to, status and search instead of downloading everything and filtering yourself.