Skip to main content
Paginated mutable-resource collections use limit/offset pagination unless you filter them with updated_since (see Incremental synchronization). limit defaults to 10 and accepts 1–100; offset is the zero-based position. Both are validated, not coerced: a non-integer value (ASCII digits only), limit outside that range, or a negative offset returns 400 validation_error with errors[].code = "invalid_parameter" on the parameter — a limit above 100 is no longer silently capped. Follow the returned next URL instead of rebuilding it, and stop when next is null. Sort order uses one query parameter, ordering, on every list that can be sorted: the order and mandate collections (name, created, amount, status), the statement collections (for example ordering=-booking_date), the Partner company list, and the Mahnservice invoice (created, due_date, amount, invoice_number) and debtor (created, customer_number) lists. Terms are comma-separated, and a - prefix sorts descending. Without ordering, the order, mandate, statement, and Mahnservice lists are newest first; on the order, mandate, and Mahnservice lists ties are broken by id. Every other list is ordered as its reference documents. An undeclared parameter — including the retired sort and direction — is 400 with unknown_parameter, so read the operation reference before adding one. An empty ordering= value is treated as omitted and keeps the default. Otherwise ordering is strict: an unknown field or an empty comma-separated term (for example created,,name) is 400 validation_error with invalid_parameter on ordering. Not every collection is paginated. In particular, the immutable Case and Partner legal-form catalogs return an unpaginated JSON array and may be cached privately for one day.

Incremental synchronization

Mutable collections of the Case Management and Partner APIs accept a timezone-aware RFC 3339 updated_since; a naive timestamp or another format is 400 validation_error with invalid_parameter. The filter is inclusive. The Mahnservice API offers offset pagination only — its updated field on invoices and documents is a change marker to compare, not a filter. With updated_since, a list switches from offset to keyset paging:
  • Results are ordered by updated_at, then id. A requested ordering is ignored, because the cursor needs that order.
  • next carries an opaque cursor instead of offset. Follow it exactly; do not decode, build, or edit a cursor. previous is always null, and count is the size of the whole window, not of the remainder.
  • offset together with updated_since is 400 validation_error with invalid_parameter on offset. cursor without updated_since is invalid_parameter as well, and an altered cursor is invalid_cursor.
  • Rows changed less than 60 seconds ago are held back until they are settled. A row whose change was still being committed therefore never lands behind your checkpoint.
  • A row that changes while you page is returned again later in the same scan with its newer updated_at, instead of pushing another row out of the result. One complete scan sees every row changed since updated_since.
Keep one checkpoint per company and collection:
  1. For the initial import, record the time you start (allow a few minutes for clock skew), omit updated_since, and follow every next URL. Use the recorded time as the first checkpoint.
  2. On each later run, request updated_since=<checkpoint> and follow every returned next URL. Upsert each row by id, keeping the representation with the newest updated_at; the inclusive boundary returns rows at the checkpoint again, so accept duplicates.
  3. After all pages are durably applied, move the checkpoint to the greatest updated_at you received. No overlap window is needed.
  4. If a run is interrupted, keep the previous checkpoint. Either resume with the last unapplied next URL or start the run again from the checkpoint.
Use webhooks for prompt change signals and the checkpointed scan for convergence.

Synchronize claims by stable UUID

The claim collection accepts order_id, effective status, and updated_since together. For example:
Treat filters as a view of current relationships, not a permanent partition. If paywise review moves a claim, its order_id changes and its updated_at advances. A change to the current order’s debtor projection likewise advances the claim cursor because debtor_id or additional_debtor_ids changed in the claim read. Follow the exact next URL returned by the server, including every filter. A page can, for example, return https://api.paywise.de/v2/claims/?cursor=MjAyNi0wOC0yN1QwOToxNTowMCswMDowMHwzMDAwMDAwMC0wMDAwLTQwMDAtODAwMC0wMDAwMDAwMDAxMDA&limit=100&order_id=20000000-0000-4000-8000-000000000001&status=submitted&updated_since=2026-08-27T09%3A00%3A00Z. Do not rebuild that URL or assume later pages still contain the same rows. Deduplicate claim versions by (id, updated_at) and retain the newest complete representation. A stored claim UUID can always be confirmed directly at /v2/claims/{id}/, without scanning orders.

Runnable reconciliation example

This Python example synchronizes the Case Management API’s debtor collection. Use the same approach for other mutable collections that support updated_since, with a separate checkpoint for each company and collection. The key needs read access to the collection being synchronized. The example starts from a previously saved checkpoint and runs two consecutive incremental syncs, each starting from the checkpoint the previous run committed. It keeps its results in memory. In your application, load that checkpoint and the existing local records, then persist each applied page before advancing the checkpoint. For the initial import, omit updated_since and follow all pages.
Python workflow
The example keeps the newest version of each resource across both runs. It limits each run to five pages and rejects pagination cycles and URLs outside the configured API origin. Choose a finite page budget suitable for your dataset. An interrupted run must retain its previous checkpoint. Mandate history supports the same incremental reads through GET /v2/mandates/{id}/history/. Its updated_at includes changes to represented attachments and linked resources, so update existing entries by status id when they reappear. See Follow a case for main-case and subcase selection and the complete history representation.

Recover interrupted syncs

After a timeout or transient 5xx, retry the same next URL. If its result may already have been applied, upsert by id so replay is harmless. After 429, wait for Retry-After, then resume from the last uncommitted page. If a stored URL is no longer usable or answers invalid_cursor, restart from the last committed checkpoint rather than guessing a cursor or offset. See the current orders collection, mandates collection, and Partner companies collection for supported filters and response shapes. The Case legal-form catalog shows the unpaginated exception.