API Status Get API Key

Rate Limits

Buffer applies API rate limits per client. The number of API keys and app clients you can create, along with how many requests each client can make over a rolling 15-minute, 24-hour, and 30-day window, depend on your Buffer plan.

Feature Free Essentials Team
API Keys 1 3 5
App Clients 1 3 5
15-min limit 100 100 100
24-hr limit 250 250 500
30-day limit 3,000 7,500 15,000

Does your integration require higher limits? Reach out to developersupport@buffer.com.

Response Headers

Every response includes rate-limit information as structured RateLimit headers. Each of the three windows - 15-minute, 24-hour, and 30-day - contributes one policy, so you'll see three of each header:

RateLimit:        "200-in-15min";r=198;t=897
RateLimit:        "1000-in-1day";r=998;t=86397
RateLimit:        "30000-in-30days";r=29969;t=696980
RateLimit-Policy: "200-in-15min";q=200;w=900;pk=:ZjJjZjVmNzM5M2Zm:
RateLimit-Policy: "1000-in-1day";q=1000;w=86400;pk=:ZjJjZjVmNzM5M2Zm:
RateLimit-Policy: "30000-in-30days";q=30000;w=2592000;pk=:ZjJjZjVmNzM5M2Zm:
  • RateLimit-Policy describes each limit: q is the quota, w is the window length in seconds, and pk is the partition key identifying your rate-limit bucket.
  • RateLimit reports the live status of each policy: r is the requests remaining and t is the seconds until that window resets.
  • Policy names like 200-in-15min are generated from your quota and window, so they change with your plan. Match a policy by its window length (w) - 900 (15 minutes), 86400 (24 hours), or 2592000 (30 days) - rather than by name.

The numbers above are from one example response. The quotas you see depend on your plan.

The headers come back on every GraphQL response, so you can read them off requests you already make. For example, in JavaScript:

// POST your GraphQL query to the API as usual
const response = await fetch('https://api.buffer.com', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ query: '{ account { id } }' }),
})

// then read the rate-limit headers off the same response.
// fetch joins the repeated RateLimit headers with ", ", one entry per window:
const policies = response.headers.get('ratelimit').split(/,\s*(?=")/)
// ['"200-in-15min";r=198;t=897', '"1000-in-1day";r=998;t=86397', ...]

How repeated headers are exposed varies by HTTP client - some give you an array or separate lines rather than one joined string - so adjust to match your language. If you use a GraphQL client library instead of fetch, read the response headers through whatever mechanism it provides.

Error Response

When you exceed a rate limit, the API returns an HTTP 429 Too Many Requests with a GraphQL-shaped error body:

{
  "errors": [
    {
      "message": "Too many requests from this client. Please try again later.",
      "extensions": {
        "code": "RATE_LIMIT_EXCEEDED",
        "window": "15m"
      }
    }
  ]
}

extensions.window tells you which window was exhausted: 15m, 24h, or 30d. To know how long to wait, read the Retry-After response header (in seconds) - the retry hint is in the header, not the body.

Monitoring Your Usage

You don't have to track headers by hand to see where you stand:

  • Developer Dashboard - your API settings page shows live usage per window for each of your clients.
  • Buffer CLI - the CLI reads these headers on every command. Run any command with --verbose to print a rate-limit summary for each window, and it warns you when you're running low even without it (silence it with --quiet). On a 429 it reports the exhausted window and how long to wait, then exits with code 3:
Error: Rate limit exceeded (`15m` window). Retry after `9m 51s`. (api · code 3)

Query Limits

In addition to rate limits, we enforce query-level limits to protect against overly complex or expensive GraphQL queries.

Query Complexity

Each query is assigned a cost based on the fields it requests:

  • Scalar fields (e.g., id, name): 1 point each
  • Object fields (e.g., organization, channel): 2 points each
  • Nesting multiplier: Nested fields are multiplied by a factor of 1.5x per level of depth

The maximum allowed query cost is 175,000 points. If your query exceeds this, you will receive an error asking you to simplify it.

Query Depth

Queries are limited to a maximum depth of 25 levels. Deeply nested queries can cause exponential resource consumption, so keep your queries as flat as possible.

Aliases

A maximum of 30 aliases are allowed per query. Aliases let you rename fields in a response, but excessive use can be used to amplify query cost.

Directives

Queries are limited to a maximum of 50 directives.

Tokens

Queries are limited to a maximum of 15,000 tokens. This is a parser-level limit on the overall size of the query document.

Query Limit Error Responses

When a query limit is exceeded, you will receive a GraphQL error response:

{
  "errors": [
    {
      "message": "Query exceeds maximum allowed complexity. Please simplify your query."
    }
  ]
}

The error message will indicate which limit was exceeded (complexity, depth, aliases, directives, or tokens).

These limits may change as we evolve the API, so keep an eye on your usage.