Skip to main content

Optimize Your API Calls: Best Practices

The Boond API is governed by call limits. This article gathers best practices to optimize your consumption: call only what you need, avoid unnecessary requests, and build an efficient integration over time.

Written by Charlie Troccaz

🤖 This article was translated by AI.

Who is this article for?

For users and integrators who consume the Boond API from a script, connector, or third-party automation tool, and who want to optimize their number of calls—to stay comfortable with the limits and to build a cleaner integration.

1. Rate limiting and quota

Your consumption is governed by two independent mechanisms, which are cumulative:

  • Rate limiting smooths your throughput in the short term, per minute and per 10-second interval. If you go too fast, the API temporarily responds with 429 Too Many Requests. The thresholds depend on the endpoint called. This mechanism is being rolled out and will apply from the end of September 2026: size your integration now.

  • The quota caps your total number of calls per month; this monthly cap depends on your subscription.

Details of the thresholds are described in the dedicated article: Understanding API Call Limits.

Some clarifications on what is counted:

  • Only API calls are counted: your employees' navigation in the Boond interface does not count toward the quota.

  • A failed call is counted like any other—the counter increments at authentication, even before your request is processed. An integration that loops rejected calls consumes its quota for nothing.

  • Calls from Apps developed by third parties (partners, for example) do not consume your quota as long as the connection mode uses OAuth2 or JWTApp. If you share login/password information or your administration client key, their calls will be counted.

If you exceed the quota and the volume is not covered by your current quota, you can subscribe to additional API packs.

2. Reduce unnecessary calls

The first source of savings is simply the calls you don’t make. And it’s more profitable than it seems: each call replays the entire authentication sequence—token validation, instance resolution, account and rights loading, quota counting. Nothing is shared from one call to the next. So it’s the number of calls, even more than their content, that matters.

Cache what changes infrequently. Some data is not expected to change often: reference data, configuration, structure of your instance. Retrieve it once, store it on your side, and refresh it at a reasonable frequency rather than at every execution.

⚠️ Note: The API does not expose a revalidation mechanism—no ETag, no "nothing has changed" response. Do not rely on the Last-Modified header: it is returned with the time of the response, not the date the data was modified—relying on it would make you conclude everything has changed with every call. The last modification date is read in the response itself, on the record. Your cache should therefore rely on a fixed lifetime or on webhooks (see §3).

One useful exception: the response for your instance parameters carries a version number, which changes as soon as the configuration is modified. This is the only reliable signal to detect that a reference has changed without comparing everything.

Save static data. Historical data that no longer evolves—old Activity Reports, closed invoices, completed projects—do not need to be re-extracted in a loop. Save them once in your system, then only recall recent or potentially changing periods.

Do not authenticate at every step. A common and costly reflex is to call a verification endpoint like current-user before each request. Authentication does not change during a process: a single check at the start of the session is enough.

Use a dedicated account for your integration if it is backend-integrated. Running a flow on a collaborator’s personal account poses two problems:

  1. The flow inherits their perimeter: all records they are not authorized to see produce rejected calls, counted and replayed each cycle.

  2. The day this collaborator changes roles or leaves the company, the integration does not stop—it continues seeing less data, without a visible error.

A service account, with an explicitly defined perimeter, avoids both. If you use an integrated App or rely on the connected user’s rights, the service account makes no sense and would bypass Boond’s rights configuration.

Do not request what was denied. An access denial is not a temporary incident: the record will remain inaccessible until rights change. Memorize the denial and stop requesting it each time. This is a frequent and costly reason: tens of thousands of calls per month, all counted, for a known answer.

Bring back more data per call—but ask yourself the right question first. The number of results per page is adjustable, and leaving it at its default value mechanically multiplies your calls. Two caveats, however:

  • A value outside the limit is not brought up to the maximum: it silently falls back to the default value. Check the actual number of results returned rather than assuming your parameter was accepted.

  • Increasing the page size reduces the number of calls, not the cost of the request. On heavy collections, a very large page may be slower than several medium pages, even exceeding your timeout—and an interrupted call is still executed to the end and counted.

Especially, if you bring back a large volume only to extract a list of IDs and then recall the records one by one, it’s the mechanism itself that needs review: you pay twice. Question what your process really needs before adjusting page size.

Group rather than one call per record. Sub-resources of a record are efficient for consulting one; used to browse all your records, they become the worst reason—one call per entity, replayed each cycle. This is by far what inflates consumption the most. Whenever a search lets you retrieve several known entities in a single call, by listing their references, always prefer it—and apply this reflex everywhere, not just where you first implemented it.

Avoid "just in case" calls. Each call should answer a real need. If you don’t know if data has changed, target the change (see §3) rather than re-downloading everything as a precaution.

3. Synchronize on changes

For data that changes, the rule is simple: only retrieve what has changed since your last check. Several levers, from simplest to most refined.

Limit your extractions to the useful window. An unbounded extraction—"everything, every time"—unnecessarily inflates your consumption. Always restrict to the window you really need, filtering by date, period, or perimeter. A window that’s too wide costs not only in volume: it overflows pages, and you end up paying in pagination for data you don’t use. A significant part of calls in a poorly bounded integration exist only for this reason.

💡 Tip: To build any filtered call (extraction or Activity log), apply the desired filter directly in the Boond interface, then open your browser’s Network tab: you’ll see the exact endpoint and its parameters, ready to reproduce in your integration.

Switch to incremental. Concretely: memorize the date of your last run and only process the delta—what was created or modified since. This is often a strong reduction in call volume.

Question the frequency. This is the most effective lever, and most often overlooked: before optimizing your calls, ask yourself how many times a day you really need to make them. Running a full cycle every hour on Activity Reports, absences, or projects—which don’t change fourteen times a day—multiplies consumption without benefit. Align the cadence with the freshness your use requires, not what your scheduler allows.

⚠️ Attention: Not all data synchronizes in delta. Times, absences, and Activity Reports do not offer a filter by modification date: for these collections, there is no "give me what has changed." The best practice is to strongly restrict the requested window—the current and previous week rather than the whole year—and supplement with the Activity log to spot older changes.

Target precisely via the Activity log. It records creations, modifications, and deletions. Queried with filters, it tells you which records have changed, and often which fields, over a given period—you only need to re-fetch those, instead of browsing everything.

Or switch to event-driven with webhooks. Subscribe to creation, update, and deletion events for the entities you care about: Boond notifies you in real time, instead of you polling in a loop.

⚠️ Attention: Webhook delivery is "best-effort"—short delay, no retry. If your data freshness relies solely on them, a missed event can create a lasting, silent gap. Plan a daily safety net: a catch-up pass on the Activity log, or a delta resynchronization on a rolling 24- to 48-hour window. This is also the only way to see deletions: a deleted record disappears from results without any signal, and a modification-date sync will never tell you.

4. Control your throughput

Space out heavy extractions. Extraction, reporting, and export endpoints are among the most costly, with the strictest limits. Reserve them for scheduled and spaced-out processes—off-peak hours, segmentation—rather than for close series.

Request compression. API responses are compressed, but only if your client announces it, via the Accept-Encoding: gzip, deflate header. Without it, everything transits uncompressed, several times larger. It’s a line of configuration in your HTTP client, and one of the most immediate gains—check that your library doesn’t remove it.

Reporting cache is decided with your client. Reporting endpoints recalculate all their Key indicators by default at each call: these are the most costly in the API. They can serve a cached result, but it’s not a simple request parameter: the option is part of instance configuration, disabled by default, and its retention period—several days—is set by the client. Agree with them on activation and duration: the gain is significant, provided you accept the corresponding freshness.

React properly to a 429. It’s not a blocking error, but a temporary signal:

  • Respect the Retry-After header: it tells you how many seconds to wait before retrying. Never retry immediately.

  • Apply progressive back-off in the absence of other signals—1 s, 2 s, 4 s, with some randomness—to avoid all your calls restarting at once.

  • Smooth your throughput client-side, with a queue and a ceiling below the limit, rather than sending bursts.

By applying these principles, your integration calls less, updates faster, and helps preserve platform stability.

Did this answer your question?