Skip to main content
To ensure reliable service for all practices, the TeamCare Vendor API limits how many locations a vendor integration can be pulling data for at the same moment. Requests that exceed a limit are rejected with HTTP 429 Too Many Requests and are not queued. Your integration must implement the client-side handling described below. The limit applies to concurrent locations, not request rate. There is no cap on how many requests you may send to a single location, how quickly you may page through it, or how many locations you may sync in total.

Limits

Limits apply to every endpoint under /api/v1/vendors/locations/{location_id}/. The locations list, the organizations endpoint, and the token endpoint are not limited.
  • The unit is the location, not the request. A location occupies one slot while it has any request executing. Any number of concurrent requests for the same location share that slot.
  • Slots free immediately. A location’s slot is released the instant its last in-flight request finishes — success or error. There are no fixed windows and no idle timers.
  • The two pools are independent. Incremental polling never blocks initial syncs, and the same location may hold one slot in each pool at the same time.
  • Budgets are per credential. Limits are counted per API credential across all your processes and servers combined. Other vendors’ traffic never affects yours.
  • Rejected requests cost you nothing. A 429 request is not executed, occupies no slot, and is not recorded against you. Nothing was read and no partial response was produced, so retrying is always safe.
  • Sequential clients are never limited. If you sync one location at a time, you cannot reach these limits.

Throttled Response Contract

When a limit is exceeded, the API responds as follows:

Required Client Behavior

  • MUST limit concurrent locations to 5 per sync mode. Initial and incremental are counted separately, so you may run up to 5 of each.
  • MUST treat HTTP 429 as a retryable condition and wait at least retry_after_seconds (or the Retry-After header) before retrying.
  • MUST NOT retry in a tight loop without a delay.
  • MUST cache the access token and reuse it. Tokens are valid for 6 hours; request a new one only when the current token expires.
  • SHOULD detect this limit by checking the response body for max_concurrent_locations rather than assuming every 429 is a concurrency rejection.
  • SHOULD read the limit from max_concurrent_locations rather than hardcoding 5, so a future change on our side requires no change on yours.
  • SHOULD parallelize freely within a location. Fetching one location’s patients, appointments, and treatments simultaneously consumes a single slot and is the most efficient way to sync.
  • SHOULD set items explicitly when paging. Cursor pagination defaults to 10 records per page and accepts up to 5000; leaving it at the default makes large pulls far slower than necessary.
  • SHOULD add random jitter to retry delays if you run many workers, so they do not retry in lockstep.
  • SHOULD use q[fetch_modified_since] for routine polling. It returns only records with updated_at >= your timestamp and routes the request to the incremental pool, so polling never competes with initial syncs.
If you are seeing this 429 regularly, your effective location fan-out is above 5. Correct the fan-out rather than relying on retries.

Reference Implementation

Minimal retry handling (Python; the same pattern applies in any language):
A worker pool is the natural structure for the limit: give each worker one location at a time, and run at most 5 workers per sync mode. The number of locations you sync overall is unlimited — 50 or 500 locations flow through the 5-wide pipe without any additional coordination on your side.

Verifying Your Integration

The limit triggers as documented. Start pulls for 6 distinct locations simultaneously in the same pool. Requests for the first 5 locations succeed; requests for the 6th return 429 with max_concurrent_locations in the body. Once one of the active locations finishes, the 6th is admitted on retry. Same-location parallelism is unrestricted. Fire several endpoints for one location at once. None are rejected — they share a single slot. The pools are independent. With 5 locations already active in the initial pool, a request carrying q[fetch_modified_since] for a 6th location still succeeds, because it draws on the incremental pool. Normal operation is clean. Run your usual sync with fan-out capped at 5 per mode and confirm you see no 429 responses at all. A correctly capped client should never trigger this limit in steady state.