Skip to content

Rate Limits

Two limits apply, and a request can run into either one:

LimitApplies toAllowance
Route limitEvery API request, including /auth and /me60 requests per minute per client IP
Resource limitEvery endpoint except /auth and /me30 requests per minute

In practice the resource limit is the one you’ll meet: a job that only calls resource endpoints runs out at 30 a minute. /auth and /me don’t count against it, which makes them cheap health checks.

The route limit is per client IP, so integrations and workers that share an IP address share those 60 requests.

Resource endpoints report the 30-per-minute window on successful responses, and on 429s from that limit:

X-RateLimit-Limit: 30
X-RateLimit-Remaining: 24
X-RateLimit-Reset: 47
HeaderMeaning
X-RateLimit-LimitMaximum requests allowed in the window
X-RateLimit-RemainingRequests left in the window
X-RateLimit-ResetSeconds until another request is available

/auth and /me report the route limit instead: X-RateLimit-Limit: 60 and the requests left in that bucket. When the route limit rejects a request, on any endpoint, the headers describe that limit: X-RateLimit-Limit is 60, and X-RateLimit-Reset is a Unix timestamp, not a number of seconds.

So don’t carry a count from one endpoint to another. X-RateLimit-Remaining from /me describes the 60-request bucket, not the 30 your resource calls draw on.

Stop sending, and wait:

  1. If Retry-After is present, honor it. It’s a number of seconds whichever limit fired.
  2. Otherwise wait for X-RateLimit-Reset. Both windows are one minute long, so a value above 60 is a Unix timestamp rather than a number of seconds.

The body depends on which limit fired. The resource limit returns:

{
"message": "Too many requests. Please try again later.",
"errors": {
"rate_limit": "Too many requests. Please try again later."
}
}

The route limit returns only a message:

{
"message": "Too Many Attempts."
}

Neither has a status field. See Errors for how these fit with the other error shapes.

  • Queue your work rather than firing many requests concurrently.
  • Cache stable IDs. Brand and collection IDs don’t change during a job. Resolve them once.
  • Page efficiently. per_page goes up to 100, so one page often beats four.
  • Use the narrowest list. Post lists filter on the server: ?view=SCHEDULED on one brand-wide call beats paging through every collection.
  • Add jitter when several workers share one key or one IP, or they’ll all retry in lockstep and re-trigger the limit.
  • Retry reads after the server’s reset time.
  • Don’t blindly retry writes after a timeout or a 5xx. Without a documented idempotency key, the request may have already succeeded. See Errors.

MCP tool calls and CLI commands go through the same public API, so the same limits apply to them. This matters more than it sounds: one conversational request like “show me everything in my account” can chain a brand list, then a collection, channel, media, and post list per brand, and spend a dozen requests before it answers.