Deze referentie is alleen in het Engels. Naar het Nederlandse REST API-overzicht

Diese Referenz gibt es nur auf Englisch. Zur deutschen REST-API-Übersicht

Cette référence existe uniquement en anglais. Aller à la présentation de l'API REST en français

Esta referencia solo está en inglés. Ir a la introducción de la API REST en español

Rate limits

Rate limits

What each request costs, the ceilings per token and per organisation, and the headers that tell you how much budget is left.

View as Markdown

Every request to /api/v2 spends units from rate buckets. You can work out what a request costs before you send it, and every response tells you how much budget is left.

Ceilings

Every bucket counts over a window of 60 seconds.

BucketRead unitsWrite units
Per token600120
Per organisation, shared by all its tokens and users3000600
  • Each token has its own budget, but every token in your organisation also spends from the organisation's bucket. Another token can therefore lower what you have left.
  • For an app that signs in with OAuth, the per-token budget belongs to the app and the user who signed in. It carries over when the access token is refreshed.

Before the token is checked, a per-IP limit applies as well: 600 requests per minute per IP address and host, and 1200 requests per minute per IP address. It counts requests, not units, and it never shows in the RateLimit headers.

These ceilings are the current budget. Read RateLimit-Policy at runtime instead of hard-coding them.

Read and write buckets

  • A GET spends its cost from the read buckets.
  • A POST, PATCH or DELETE spends its cost from the write buckets, plus 1 unit from the read buckets. A write therefore needs room in both, and an empty read bucket blocks writes too.

Each operation page in the reference shows the bucket it spends from.

What a request costs

cost = base                  1, or 3 for view=detail on a collection
     + each include path     +1, or +3 when the path is a list
     + q                     +2 when a search term is sent
     + with_total=1          +2
PartUnitsWhen it applies
Base1Every request.
Base with view=detail3 instead of 1Only on a collection read. On a single record and on a write, view=detail costs nothing extra.
Include path, to-one+1 per pathThe path inlines one related record, such as assignee.
Include path, to-many+3 per pathThe path inlines a list of records, such as labels: up to 25, or 50 for tags.
q+2A search term is sent.
with_total=1+2A collection read asks for the total.

A DELETE always costs 1.

Name each include path once. A path you repeat, such as include=labels,labels, is loaded once but charged every time it appears.

Worked example

GET /work-items takes the to-many include paths comments, drive_items, labels and subtasks, and to-one paths such as assignee and sprint.

RequestCost
GET /work-items1
?view=detail3
?include=assignee1 + 1 = 2
?include=labels1 + 3 = 4
?include=assignee,sprint,labels1 + 1 + 1 + 3 = 6
?q=invoice&with_total=11 + 2 + 2 = 5
?view=detail&q=invoice&with_total=1&include=comments,drive_items,labels,subtasks,assignee3 + 2 + 2 + 4 × 3 + 1 = 20

With each path named once, the last request is as expensive as GET /work-items gets: it names as many include paths as one request may, and every to-many path is among them. Limits at a glance has the maximum.

What costs exactly one unit, and what costs nothing

The extra units are charged only on a successful 2xx response that was not replayed. So these cost exactly 1 unit, whatever the request asked for:

  • a 304 Not Modified
  • a replayed POST that returns the stored response for its Idempotency-Key
  • an error response, such as a 400 or a 422

These cost no units at all:

  • a 429
  • a path or method that does not exist
  • a request refused before or at the token check: an address that serves no API, a switched-off REST API, or a missing or invalid token. It still counts towards the per-IP limit.

The headers

Every response carries the current state of your budget, errors and 429 included:

HTTP
RateLimit: limit=600, remaining=598, reset=42
RateLimit-Policy: 600;w=60
HeaderMeans
RateLimitlimit is the ceiling of the tightest bucket this request spent from: the one with the fewest units left. remaining is what is left in it, after this request's own cost. reset is the number of seconds until it refills.
RateLimit-PolicyThe same bucket's ceiling and window in seconds, as <limit>;w=<seconds>.

These headers use the syntax of an earlier draft of the IETF RateLimit header fields. Later drafts changed the syntax, so parse the form shown here.

Three older headers are still sent, but they are deprecated and stop on 2027-09-01:

  • X-RateLimit-Limit
  • X-RateLimit-Remaining
  • X-RateLimit-Reset

Move to RateLimit now. Note that X-RateLimit-Reset is a Unix timestamp, while the reset in RateLimit counts seconds from now.

When you run out

You get 429 rate-limit-exceeded:

JSON
{
  "type": "https://developers.plnnrly.com/api/v2/problems/rate-limit-exceeded",
  "title": "Rate limit exceeded",
  "status": 429,
  "detail": "The rate limit for this caller has been exhausted. Retry after the interval in the Retry-After header.",
  "instance": "/api/v2/work-items",
  "request_id": "01K4B7Q9YV3PZ2N8T1E6M0XR4S",
  "rate_limit": {
    "limit": 600,
    "retry_after": 42
  }
}

rate_limit.limit is the ceiling that ran out. rate_limit.retry_after and the Retry-After header give the seconds until it refills. Wait that long: a retry that arrives earlier is refused again.

A 429 is always safe to retry, because the request did not run. On a POST, retry with the same Idempotency-Key anyway.

MCP and OAuth

  • MCP. Calls through the MCP server do not spend these units. The MCP server allows 60 requests per minute per user, and every MCP request counts, not only tool calls. See Tools.
  • OAuth. Registering an app and getting or refreshing its tokens have limits of their own. See Sign in with OAuth.

Spending less

  • Ask for full pages. Send per_page=100: a page costs the same whether it holds 1 row or 100. With a to-many include, the maximum is 25 rows per page.
  • Do not ask for a total you will not read. with_total=1 adds 2 units, and links.next already tells you whether there is another page.
  • Prefer an include over follow-up reads. A to-one path adds 1 unit for a whole page of rows. A to-many path adds 3 and limits the page to 25 rows, so compare it with reading that list separately.
  • Stay on the summary view while paging. view=detail triples the cost of a collection read.
  • Honour the cache lifetime. A few configuration reads, such as labels and work types, declare Cache-Control: private, max-age=60, and discovery declares private, max-age=300. The operation page says so. Re-reading them sooner spends units for nothing.
  • Revalidate instead of reading again. Send If-None-Match: a 304 costs 1 unit, even for a request that would otherwise cost more. See Concurrency and ETags.