Skip to content

Rate limits

Rate limits keep the platform fast and fair for everyone. There are two surfaces with two signalling contracts — make sure you read the section for the host you call.

HostLimited by429 body
api.unitedpetclub.com — the Partner APIyour application’s tier, per application and per application-accountapplication/problem+json with platformResponseCode 0010010000429
the platform app endpoints (/api/… on the United Pet Club apps)a signed-in user: 1,200 a minute per user (account-security writes 15 a minute per user); anyone else: per IP, 15 a minute on sign-in and verification writes{ "resultCode": "Platform_RateLimit_HD_RateLimitExceeded_RJ" }

Every authorized request is counted against two buckets at once:

BucketCountsHeader pair
Appevery request your application makes, across all accounts it is connected toX-RateLimit-Limit-App / X-RateLimit-Remaining-App
Installrequests your application makes for one connected account — on the Partner API, for one connected businessX-RateLimit-Limit-Install / X-RateLimit-Remaining-Install

Both are per-minute token buckets that refill continuously — a burst that drains a bucket recovers at one-sixtieth of the limit every second, not all at once at the top of the minute.

With a token from a business’s authorization (the Partner API), each connected business has its own install bucket: a busy salon cannot use up the budget of your app’s other businesses, while the app bucket still caps your app as a whole.

Your application’s tier sets both limits. It is assigned when the application is approved; ask Support about moving tiers.

TierApp requests / minInstall requests / min
Starter (default)60060
Growth3,000300
Enterprise30,0003,000

The headers are on every authorized response, success or failure, so you can watch your remaining budget without waiting for a 429:

HTTP/1.1 200 OK
X-RateLimit-Limit-App: 600
X-RateLimit-Remaining-App: 412
X-RateLimit-Limit-Install: 60
X-RateLimit-Remaining-Install: 7
X-RateLimit-Reset: 1787270460

X-RateLimit-Reset is a Unix timestamp (seconds) roughly one minute ahead — the point by which a fully drained bucket is full again. In the example above the install bucket is nearly empty while the app bucket has plenty of room: slow down calls for that account.

HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit-Install: 60
X-RateLimit-Remaining-Install: 0
Content-Type: application/problem+json
{
"type": "https://api.unitedpetclub.com/errors/rate-limit-exceeded",
"title": "Rate limit exceeded",
"status": 429,
"detail": "Per-account rate limit exceeded. Retry after 12 seconds.",
"instance": "/api/animal/v1/animals",
"correlationId": "…",
"platformResponseCode": "0010010000429",
"scope": "install",
"limit": 60,
"retryAfterSeconds": 12
}
  • scope tells you which bucket ran dry: app (slow everything down) or install (slow down calls for this account only).
  • retryAfterSeconds and the Retry-After header carry the same number — the time until one token is available again.
  • The request was not processed. Retry it after waiting.

The token endpoint (/connect/token) is outside these buckets, but requesting a token per call is still the most common cause of avoidable load — cache it for its full lifetime.

The endpoints used by the United Pet Club apps apply a simpler per-caller limit and signal throttling with a resultCode body:

HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json
{ "resultCode": "Platform_RateLimit_HD_RateLimitExceeded_RJ" }

resultCode is the same code you will see across those endpoints for throttling, so branch on it directly rather than parsing prose. It is retryable. Sign-in, token and verification routes are throttled more tightly than data routes, and only for non-GET requests.

Per-plan limits (a per-minute request rate or a monthly call quota tied to the account’s plan) are not enforced yet: the default rates above apply to every caller, whatever the account’s plan. The 429 signalling contract above is in effect; build against it.

  • Respect Retry-After. Wait at least that many seconds before retrying the same request.
  • Back off exponentially on repeated 429s, and add jitter so retries from many workers don’t line up.
  • Watch the headers, not just the status. On the Partner API, X-RateLimit-Remaining-* lets you throttle yourself before the API does.
  • Don’t hammer authentication. Cache and reuse access tokens rather than re-authenticating per request.
  • Batch where you can. One request for 100 records costs the same as one request for 20 — see Pagination.
  • Key off the stable code — platformResponseCode 0010010000429 or resultCode Platform_RateLimit_HD_RateLimitExceeded_RJ — as your retry trigger.