Product that suits modern B2B Tech companies

Book Demo
B
Book demo call-to-action illustration
BACK
B

BambooHR API Rate Limits: 429 vs 503 and Retry-After

Platform APIs
September 30, 2026
Summarise the blog with AI
Open in ChatGPT
Ask questions about this page
Open in Claude
Ask questions about this page

Key takeaways

  • BambooHR publishes no numeric rate limit; its Technical Overview says only that requests can be throttled if they're too frequent.
  • Since September 16, 2026, a throttled request returns 429 with a Retry-After header instead of 503. The limits themselves didn't change.
  • A 503 now means the API is temporarily unavailable, so keep a 503 branch but stop treating it as the throttle signal.
  • BambooHR's Technical Overview, last modified 2025-10-16, still describes 429 as an employee-limit error. Treat Planned Changes to the API as current.
  • Retry-After arrives as seconds or an HTTP-date, so parse both forms before you wait.
  • Send credentials on every request, and log X-BambooHR-Error-Message without branching on it.

Code written before September 16, 2026 expects a 503 when BambooHR throttles it, and may treat a 429 as something to give up on. Code written today expects the opposite, and may retry a genuine outage as though it were just a busy queue.

Since September 16, 2026, a throttled request returns 429 (Too Many Requests) instead of 503: the rate limits themselves did not change, only the code that reports them, per BambooHR's Planned Changes to the API notice. BambooHR still publishes no numeric limit to design against; its Technical Overview says only that requests can be throttled if BambooHR deems them "too frequent."

This is the throttling and error-handling half of Bindbee's BambooHR API integration guide: why BambooHR's own documentation still disagrees with itself, the retry logic that holds up either way, a verdict for every documented status code, and how to stop spending your limit on requests that were always going to fail.

Last verified against BambooHR's documentation: 2026-09-30.

Why BambooHR's own docs disagree about 429

Open BambooHR's Technical Overview page to check any of this, and you'll find a different story. It still lists 429 as your account reaching its employee limit, and calls 503 the common signal for rate limiting, with a note that a Retry-After header "may be available." That page was last modified 2025-10-16, months before the September change, and it hasn't been updated since.

Here's how the two pages compare:

Page Last updated What it says about 429 What it says about 503
Technical Overview 2025-10-16 (predates the change) Account has reached its employee limit Commonly due to rate limiting; Retry-After "may be available"
Planned Changes to the API 2026-09-10 Returned when a request is throttled; Retry-After included Returned only when the API is temporarily unavailable

Planned Changes to the API documents the change with a specific effective date; Technical Overview simply hasn't caught up. Until BambooHR corrects it, expect a search engine or an LLM to keep surfacing both answers side by side, because both pages are still live.

None of this means you should drop 503 handling. After September 16, a 503 means the API is temporarily unavailable rather than throttled, and genuine outages still happen, so keep the branch and stop treating it as your throttle signal. On either code, Retry-After is what tells you how long to wait.

How to handle a 429 or 503

Integrations should read Retry-After rather than infer meaning from the code alone. BambooHR promises the header on every rate-limited response, in one of two forms defined by RFC 9110: a plain delay in seconds, or an HTTP-date. Build your branch around that header, not around whether the status happens to be 429 or 503.

Python
import logging, random, time
from datetime import datetime, timezone
from email.utils import parsedate_to_datetime

import requests

API_KEY = "your-api-key"
MAX_ATTEMPTS = 5

session = requests.Session()
session.auth = (API_KEY, "x")  # send credentials on every request

def parse_retry_after(value):
    value = value.strip()
    if value.isdigit():
        return int(value)  # delay-seconds
    target = parsedate_to_datetime(value)  # HTTP-date
    return max(0.0, (target - datetime.now(timezone.utc)).total_seconds())

def bamboohr_request(method, url, **kwargs):
    for attempt in range(MAX_ATTEMPTS):
        response = session.request(method, url, **kwargs)
        if response.status_code not in (429, 503):
            return response
        retry_after = response.headers.get("Retry-After")
        if retry_after:
            time.sleep(parse_retry_after(retry_after))
        elif response.status_code == 503:
            time.sleep(min(60, 2 ** attempt) + random.uniform(0, 1))  # backoff with jitter
        else:
            logging.warning("429 without Retry-After: %s", response.headers)
            return response  # don't assume it's the throttle
    return response

That covers every code worth waiting out. Everything else on BambooHR's list means something is wrong with the request itself, not the pace of them.

Every BambooHR status code, and what to do with it

Here's a verdict for every code BambooHR documents, current as of September 2026:

Code What BambooHR says it means Retry? What to do
200 Success N/A Proceed
201 Resource created N/A Proceed
400 Bad Request: malformed request No Fix the request; resubmitting unchanged will likely fail again
401 Unauthorized: missing or invalid credentials No Fix credentials; repeated attempts with a bad key trigger a temporary lockout
403 Forbidden: insufficient privileges No Fix the requesting user's permissions. Also returned to every request while API access is disabled after repeated unknown-key attempts
404 Not Found: invalid URL or object ID No Fix the endpoint or object ID
406 Not Acceptable: invalid field reference No Fix the field reference in the request
409 Conflict: duplicate resource No Fix the request; deduplicate before resending
422 Unprocessable Entity (datasets endpoint): filter operators combined incorrectly No Fix the filter syntax
429 Too Many Requests: throttled (as of Sept 16, 2026, replaces 503 for this case); Retry-After included Yes Wait the stated Retry-After, then retry, up to a cap
500 Internal Error Maybe BambooHR says retrying "may be appropriate"
502 Bad Gateway Maybe Treat as transient; back off and retry
503 Temporarily unavailable (as of Sept 16, 2026, no longer indicates rate limiting) Yes Back off (Retry-After if present, otherwise exponential with jitter), then retry

A verdict is only useful once you know why the error happened in the first place.

Diagnosing errors and saving your rate-limit budget

Once every code has a verdict, the next problem is why an error happened at all, and how to stop causing avoidable ones. Two habits catch most of what's left:

  • Log X-BambooHR-Error-Message, and branch on the status code. Most 4xx and some 5xx responses carry the header, and it's the fastest way to see why a request failed. BambooHR says its text can change at any time, so keep it in your logs and out of your control flow.
  • Send credentials on every request. Waiting for the Basic-auth challenge before sending them turns every call into two, and the extra request spends rate-limit budget you can't see. The same goes for a key that's already failing: repeated requests with an unknown key get API access disabled for a period, so replace the key instead of retrying it.

If credential handling isn't built yet, BambooHR API authentication walks through the OAuth and API-key paths in full.

Get all of this right and the client survives both today's behavior and BambooHR's next change. It's also a client someone has to keep maintaining.

If you'd rather not maintain this client

BambooHR changed its throttle signal on September 16, 2026, and two weeks later its own docs still disagree about it. That's the maintenance cost of a direct integration: staying correct every time the vendor moves something, long after the first build ships.

Bindbee is one way to hand off that clock. Bindbee's BambooHR connector is an API connector: Bindbee calls BambooHR's API with the credentials your customer authorizes, with no screen scraping involved. Data syncs on a 24-hour default schedule, adjustable on request, and Bindbee's webhooks notify you when a sync starts, finishes, or fails, or finds created or updated records. The notifications follow the sync, so they don't make the data real time, and that distinction is worth knowing before you build a workflow that assumes otherwise.

For anything outside Bindbee's unified BambooHR models, Passthrough sends the request straight to BambooHR's own API. None of this describes how Bindbee's connector itself reacts to a 429; if you call BambooHR directly through Passthrough, the retry logic in this guide is still the logic you're writing.

To see the BambooHR connection flow, book a demo.

Frequently asked questions

What is the BambooHR API rate limit?

BambooHR doesn't publish one. Its Technical Overview says only that requests can be throttled if they're too frequent, so design around the Retry-After header rather than a requests-per-minute figure.

Why does BambooHR now return 429 instead of 503?

Since September 16, 2026, a throttled request returns 429 (Too Many Requests) instead of 503. BambooHR says the limits themselves didn't change, only the status code that reports them. A 503 now means the API is temporarily unavailable.

How long should I wait after a BambooHR 429?

As long as Retry-After says. BambooHR sends the header on rate-limited responses, either as a number of seconds or as an HTTP-date, so your client needs to parse both forms.

Should I still handle 503 from BambooHR?

Yes. Genuine outages still happen, so keep a 503 branch: honor Retry-After if it's present, otherwise back off with jitter. Just stop treating 503 as your throttle signal.

Why does BambooHR's Technical Overview describe 429 differently?

That page still lists 429 as an account reaching its employee limit and was last modified 2025-10-16, before the September 2026 change. Treat Planned Changes to the API as current on this point until BambooHR updates the Technical Overview.

Kunal Tyagi
CTO
Bindbee
VIEW AUTHOR
BLOG_

Related blogs