fepli
REST API

Pagination

Lists are returned one page at a time: 30 records by default, up to 200 if you ask for more.

Query parameters

Every paginated list accepts two parameters:

  • Name
    page
    Type
    integer
    Description

    The page to return, starting at 1. Defaults to 1.

  • Name
    itemsPerPage
    Type
    integer
    Description

    How many records a page holds. Defaults to 30; values above 200 are capped at 200.

They work alongside the filters of each endpoint:

The response body is a JSON array holding the records of the requested page, and nothing else. A page past the end is an empty array.

There is no total count and no Link header. To read a whole list, request page after page until a page holds fewer records than itemsPerPage.

Request

curl "https://ferienpass-musterstadt.de/api/offers?edition=herbstferien-2026&page=2&itemsPerPage=50"

Response

[
  {
    "uuid": "0192a4f1-6e3b-7c85-b1d2-8f4e6a9c3b03",
    "name": "Fahrradtour durch den Stadtpark",
    "…": "…"
  },
  {
    "uuid": "0192a4f3-9d2c-7a1e-8b4f-5c6d7e8f9a11",
    "name": "Töpfern für Anfänger",
    "…": "…"
  }
]

Reading a whole list

Fetch every page

async function fetchAll(path, params = {}) {
  const itemsPerPage = 200
  const records = []

  for (let page = 1; ; page++) {
    const query = new URLSearchParams({ ...params, page, itemsPerPage })
    const response = await fetch(
      `https://ferienpass-musterstadt.de/api${path}?${query}`,
      { headers: { Authorization: `Bearer ${process.env.FEPLI_TOKEN}` } },
    )
    if (!response.ok) throw new Error(`${response.status} ${await response.text()}`)

    const batch = await response.json()
    records.push(...batch)
    if (batch.length < itemsPerPage) return records
  }
}

const applications = await fetchAll('/attendances', { edition: 'herbstferien-2026' })

Order

Each list has a fixed order, documented with its endpoint. Offers can be sorted with sort and order; the other lists are ordered the way the admin shows them, for example applications by newest first or accounts by last name.

For lists that change while you read them, use the modifiedSince (or createdSince) filter where the endpoint offers one, and fetch only what changed since your last run.

Lists without pages

A few lists are always returned in full, and ignore page and itemsPerPage:

GET /search returns at most limit hits per kind of record instead.

Was this page helpful?