Skip to content

Pulling documents

Orders, invoices, payments and returns are all pulled the same way: by version, never by page number. Every change to a record gives it a higher version, and versions are handed out in commit order, so a cursor can’t skip a record that was being written while you read.

GET /orders?filter[version_after]=0&per_page=100
→ {"data": [ …oldest change first… ],
"meta": {"per_page": 100, "has_more": true, "next_version_after": 18342, "high_water": 18990}}
GET /orders?filter[version_after]=18342&per_page=100
→ … until "has_more": false
  1. Read your watermark: the highest version you have staged, or 0 the first time.
  2. GET /{orders|invoices|payments|returns}?filter[version_after]=<watermark>&per_page=100.
  3. Stage every row under a unique key (id, version) — and line_number for line tables. A record that changes while you read comes back later with a higher version; the unique key makes the second copy harmless.
  4. Repeat with meta.next_version_after until meta.has_more is false.
  5. Book from staging, then ack what you booked.

Every collection takes these:

Parameter Meaning
filter[version_after] The cursor.
filter[updated_after]=2026-10-01T00:00:00Z First load only: start at the first change from that time. Not with a cursor.
filter[ack]=pending Only records not acked at their current version. Also accepted, rejected, any (default).
filter[id]=a,b,c Only these ids — at most 100 (more answers 400 INVALID_REQUEST).
filter[external_ref]=SO-0012345 Only the record you acked under that key.
per_page 1–500, default 100. page= and offset= are refused.
filter[status]=ERP_PENDING,ERP_FAILED Orders only.
filter[seq_after] Invoices, payments and returns only — see the invoice counter.

Brackets may be sent raw (filter[ack]) or encoded (filter%5Back%5D). An unknown filter[…] is refused, not ignored, so a typo can’t silently widen a query.

If your staging table is purged or the ERP database restored, the watermark is gone. Don’t start from 0 and re-book: pull filter[ack]=pending instead. It returns exactly the records you haven’t acked at their current version — including ones that changed after you acked them.

  • Order: header; customer, branch and rep with both keys; lines (product, unit, quantity, price, discount, free-goods flag, promotion) with VAT per line worked out as the invoice will; totals; status; idempotency_key; and your last ack.
  • Invoice: as issued — lines, VAT, totals — its order with that order’s lines, and its state with the tax authority (tax_submission).
  • Payment: method (CASH, CHEQUE, TRANSFER, INSTAPAY, WALLET), amount, allocations to invoices, the receipt, the cheque and its state, and a reversal when undone.
  • Return: lines against the original invoice’s lines, the reason, the approval, and the credit note number.

The loop in curl and jq, printing each order’s id, version and number. -g stops curl reading the brackets as a pattern:

Terminal window
v=0
while :; do
page=$(curl -sg "$SLFLO_BASE/orders?filter[version_after]=$v&per_page=100" -H "Authorization: Bearer $SLFLO_TOKEN")
echo "$page" | jq -r '.data[] | "\(.id) \(.version) \(.number)"'
[ "$(echo "$page" | jq .meta.has_more)" = true ] || break
v=$(echo "$page" | jq .meta.next_version_after)
done
echo "watermark: $v"

The same in Python, with staging and booking, is the pull connector.