Care4Fresh API ← API documentation

Integration health guide

Care4Fresh watches how each integration uses the API and, now and then, points out a habit that could be smoother, cheaper, or safer. These are suggestions, not errors, and nothing is blocked or throttled because of a suggestion itself. Our network security does separately block IP addresses that behave like scanners or brute-force attempts (for example, abnormally high request volumes from one address, or repeatedly ignoring rate limits), so the fastest way to stay clear of that is to follow the advice here.

When you get an advisory email or see a note in the portal, it will link to one of the sections below. Each one explains what the pattern is, why it is worth changing, and the concrete steps to fix it.

On this page

The recommended sync flow

Most integrations keep a local copy of your Care4Fresh data (products, relations, sales, purchases, stock) and refresh it on a schedule. The reliable, low-cost way to do that is a one-time full sync followed by incremental deltas. The same shape works for every collection, so the examples below use /sales but apply to /products, /relations, /purchases, and /stock too.

1. Initial full sync (once)

On the very first run, read the entire collection and page through to the end. Omit modifiedSince so you get everything, and sort by last-modified ascending so paging stays stable while data changes underneath you.

2. Incremental sync (every run after that)

On each later run, ask only for what changed since your checkpoint. This is a handful of requests instead of the whole data set.

3. Pick up deletions

A record that is removed simply stops appearing in the list, so incremental reads alone never tell you it is gone. Each collection has a matching deletions feed for this.

4. Reconcile occasionally

On a slower schedule (for example weekly), run a full sync again with modifiedSince omitted to catch any drift and confirm your copy still matches. Between reconciliations, the incremental poll plus the deletions feed keeps you current.

Two habits keep this healthy: honor the Retry-After header if you ever get a 429 (see below), and after a write such as creating a sales order, confirm the 2xx response and record the order so you do not resubmit it. The sections below explain what Care4Fresh flags when these slip.

Rate-limit responses are being ignored

What it means

When you send requests faster than your plan allows, the API answers with status 429 Too Many Requests and a Retry-After header telling you how many seconds to wait. This pattern shows up when an integration receives those 429s and keeps sending new requests straight away instead of pausing.

Why it matters

A 429 means the request was rejected, not served. If the workflow does not go back and retry it later, whatever it asked for is quietly missing from your copy of the data. Hammering through the limit also makes every response slower, so ignoring 429s tends to lose data and cost time at once.

How to fix it

Polling without incremental sync

What it means

An incremental sync asks the API for only the records that changed since your last run. This pattern shows up when an integration makes many list requests but never uses the modifiedSince parameter and never reads a deletions feed, so it re-pulls the full data set every time.

Why it matters

Re-pulling everything is far more requests than you need, which is what pushes an integration into the rate limit. It is also easy to miss deletions this way, because a record that was removed simply stops appearing and nothing tells you it is gone.

How to fix it

Sync checkpoint is not moving forward

What it means

This pattern shows up when an integration does send modifiedSince on every request, but always sends the same value. The parameter is there; the checkpointing behind it is not. Every run then asks for everything that changed since that one fixed moment, rather than since the previous run.

Why it matters

The period being re-read grows by a day every day. Each run returns more data than the last, takes longer, and nearly all of it is data you already have. It gets worse on its own, and it is easy to miss because nothing fails: the responses are correct, just far larger and slower than they need to be.

How to fix it

Change window is never drained to the end

What it means

This pattern shows up when an integration stops at the same page of a change feed on every run, while the point it syncs from never moves forward. It is the two problems above happening together, and the combination is worse than either alone.

Why it matters

A window that starts from a fixed point only grows, so the pages you do read are always the same oldest changes. Everything newer sits in the pages you never ask for. Results come back with a 200 and nothing looks wrong, which is why this is usually noticed weeks later as "our data stopped updating" rather than as an error. Because the feed is sorted oldest-first by default, the records lost are the most recent ones.

How to fix it

Paging a change feed the slow way

What it means

The price-changes feeds can be paged two ways: by page number, or with a cursor. This pattern shows up when an integration drains one of them with page= even though the cursor is available.

Why it matters

It is the slowest way to read the feed, and your own sync is what waits. Page numbers make the server re-run the whole comparison for every page, and they get slower the deeper the page number goes, so a run that drains several pages can spend seconds on each one. The cursor walks forward through a window prepared once instead. Page-number requests also cannot use the prepared-window cache that serves cursor readers, so every page pays full price on every run, however the administration is configured. Integrations that have switched typically see the same data arrive several times faster.

How to fix it

Re-fetching record detail that has not changed

What it means

This pattern shows up when an integration reads the detail of the same records over and over, far more often than those records actually change. It is refreshing everything it tracks on every run rather than only the records that moved.

Why it matters

Most of those detail reads return data you already have, unchanged. They spend your request budget without adding anything, and they crowd out the requests that do carry new information.

How to fix it

Requests to an address that does not exist

What it means

The URL your integration calls is not one the API serves, so every request comes back as not found. Nothing is read and nothing is saved.

Why it matters

This is not a request being refused, it is a request arriving nowhere, so there is nothing in the body to correct. Because each call fails quietly on its own rather than breaking anything visible, it can run for a long time before anyone notices that the data it was meant to move has never moved at all.

How to fix it

The same request keeps failing

What it means

This pattern shows up when an integration sends a request that fails with the same client error (for example 400, 404, 409, or 422) on every run. It is usually a bad parameter or a reference to something that no longer exists, and often no one has noticed.

Why it matters

A request that always fails never returns data, so whatever it was meant to fetch or write is missing. Because it fails quietly in the background, it can go unnoticed for a long time while it wastes part of your request budget every run.

How to fix it

Write requests are being rejected

What it means

This pattern shows up when an integration sends create or update requests (for example creating a sales order) and the API rejects a large share of them with a client error such as 400, 409, or 422.

Why it matters

A rejected write is a change that was not saved. If the workflow does not correct the request and resend it, that data never lands in Care4Fresh, and it is easy to miss because each failure comes back one at a time in the background.

How to fix it

Want to stop receiving these suggestions? You can turn the advisory emails off from the API portal.