# Limits and defaults

> The limits and defaults on session replay, events, lists, AI judging, Ask, reading your data, sign-in and API access, and what happens at each one.

> **In short**
>
> - Most limits count per project. Some count per person, per network address or per server. The row says so.
> - By default, you can play a replay for 30 days after its first part arrives at Sequential.
> - Background judging has a daily allowance of 5,000,000 input tokens per project. **Ask** in the app has its own, 2,000,000. **Ask** from an agent has another, 2,000,000.
> - Some lists stop at 10,000 rows and do not say so. Narrow the dates or add a condition.
> - Some values look like limits, but Sequential does not apply them. See [Values that are not enforced](#values-that-are-not-enforced).

## How to read this page

Values can carry a label:

- **Project default**: a new project starts with this value. Owners and admins can change it under Settings → Projects → your project → **Session replay**.
- **Server default**: one value for every project on your Sequential service. You cannot set it per project or see it in the app.
- No label: the limit is built in and is the same everywhere.

### When a server value is not valid

If the server value for a judging allowance or a request limit is 0, empty or not valid, Sequential uses the default. So nobody can turn off these limits by mistake.

## Session replay

### Uploads

| Limit | Value | Result |
|---|---|---|
| One upload from a website | 5 MB before compression. Server default | Sequential refuses it. The recorder stops for that page. |
| One upload from a mobile app | 5 MB compressed, 20 MB decompressed. One event in it: 5 MB after Sequential compresses it. Server default | Sequential refuses it. |
| Upload volume | 50 MB a minute per project. 50 MB a minute per network address. Server default | Sequential refuses uploads until the minute ends. Long overloads leave gaps. |
| Storing an upload for replay | 2 seconds. Server default | Refused with 503: "The replay upload could not be stored right now. Retry the same block shortly." `Retry-After` is 30 seconds. A retried block is stored once. |
| When a new recording can be played | Sequential collects uploads in 5-minute periods. It prepares each period 30 seconds after the period ends. Server default | You can play a recording only when all its uploads are ready. Until then, **Sessions** shows "Processing · ready by 14:05", with a time, in place of **▶ Replay**, and the player shows "This recording is still being processed — ready by 14:05." The time is at most about 6.5 minutes after the last upload. |

### Per session

| Limit | Value | Result |
|---|---|---|
| **Max MB** | 25 MB per session, counted before compression. Allowed: 1–500. Project default | Sequential refuses more uploads for the session. Websites: the recorder stops. |
| **Max minutes** | 60. Allowed: 1–1,440. Project default | Websites: the recorder stops. Counts from each page load. Not sent to mobile apps. |
| **Skip sessions under (ms)** | 2,000. Allowed: 0–60,000. Project default | Sequential does not record shorter sessions. |
| How long you can play a replay | The organisation's replay period: 30 days by default, counted from when the first part of the recording arrived. One of 7, 30, 90, 180 or 365 days. A server-wide limit can make it shorter: see [A server-wide limit](/docs/retention-and-deletion#a-server-wide-limit). Only Sequential support can change it, for all the projects of the organisation | You cannot play the replay. The player shows "This recording has expired." The storage deletes the recording files about 2 days later. |

### DevTools and the player

| Limit | Value | Result |
|---|---|---|
| Per page (websites) | 1 MB of DevTools data. 1,000 network requests | That capture stops for the page. |
| Bursts (websites) | Console messages: 50 at once, then 5 a second. Uncaught errors: 20 at once, then 1 a second | Sequential does not record the rest. |
| Events in the replay player | The first 2,000 of a session | "Showing the first 2000 events — more were captured for this session." |

At a DevTools limit, the replay's **Console** tab shows a recorder notice. The badge in the **Problems** column on **Sessions** → **Latest** gets a **+**: "12+ JS errors" means at least 12.
- Sequential does not record a DevTools entry larger than 64 KB.
- Websites: **Skip sessions under (ms)** counts from each page load. If a visitor leaves a page sooner, Sequential records nothing for that page.

> **A missing chip does not mean a clean session**
>
> The chip shows only JS errors and failed requests. A session with neither shows no chip, even when it reached a DevTools limit. See [DevTools in replays](/docs/devtools).

### Replay limits in detail

**Uploads**

- One upload from a website: recording starts again on the next page load. The likeliest cause is a very large page snapshot, which the recorder sends in one upload.
- One upload from a mobile app: PostHog's mobile SDK decides what the app does next.
- Upload volume per project: all the project's visitors share it. The web recorder keeps up to 5 refused uploads and sends them again after 30 seconds. After 5, it drops the oldest, so a long overload leaves gaps in the replay.
- Upload volume per network address: everyone behind that address shares it, whichever project they visit. The web recorder sends refused uploads again, as for the per-project limit. Visitors behind one office network count together.

**Per session**

- **Max MB**: Sequential refuses more uploads for the session, from websites and mobile apps. On websites, the recorder stops. If Sequential's counter is unavailable, it does not apply the limit. The count starts again when a session sends nothing for 2 hours.
- **Max minutes**: because it counts from each page load, it limits each page, not the whole session.
- **Skip sessions under (ms)**: on websites it counts from each page load. If a visitor leaves a page sooner, the recorder sends nothing for that page.
- How long you can play a replay: the **Session replay** tab's summary line shows it as "30 d", and a line under it says "Replays kept · Set by Sequential: 30 days". The organisation sets it for all its projects. Only Sequential support can change it. A shorter period deletes nothing: stored recordings keep their old period. Through the settings API, a change of `replay_retention_days` gets 409 `retention_set_by_organisation` and saves nothing. See [Retention and deletion](/docs/retention-and-deletion).

**DevTools**

- Per page: at 1 MB, DevTools capture stops for the rest of the page. At 1,000 network requests, network capture stops for the rest of the page.
- One DevTools entry: 64 KB. Sequential does not record a larger entry.
- Sequential counts bursts of uncaught errors separately from console messages.

### See a replay limit in the browser

1. Open your browser's developer tools.
2. Open **Network**.
3. Look at requests to `/rec/`.

- A 413 means an upload was too large or the session reached **Max MB**. In the second case the response says `session_cap`.
- A 429 means the page reached an upload budget.

See [Check your install](/docs/verify).

### Heatmap data

Heatmap data is on by default for each project that records websites. Owners and admins turn it on or off under **Session replay** → **Heatmaps**. See [Heatmap data](/docs/privacy-overview#heatmap-data).

| Limit | Value | Result |
|---|---|---|
| Sessions in the sample | `"auto"`: about 2,000 recorded sessions a day, from the average of the last 7 full UTC days. A project that records fewer keeps all its sessions. Never less than 1 in 1,000. Or a fixed share from 0.001 to 1. In Settings, **Sample** is **Auto** or **Fixed**, from 0.1 to 100 % of recorded sessions. Project default: `"auto"` | A session outside the sample gives no heatmap data. |
| Page views | 25,000 a UTC day per project. Server default | Sequential stores no more heatmap data for the project that day. Recordings are not affected. |
| Facts: page views, scroll steps, clicks and counts | 500,000 a UTC day per project. Server default | The same. |
| Different pages | 2,000 a UTC day per project. Server default | The same. |
| Different clicked elements | 100,000 a UTC day per project. Server default | The same. |
| Clicks per page view | 300. Per session: 2,000 | The recorder counts the rest as clicks that it could not place. |

### Heatmap limits in detail

- Sequential picks the sample from the session id, so a session is in or out on every page.
- The recorder gets the share rounded up to 1, 1/2, 1/4 and so on, so that its settings do not reveal your traffic. So the recorder can collect for up to about twice as many sessions as Sequential keeps. Sequential drops the rest when they arrive.
- A session outside the rounded-up share installs no listeners.
- A new project with no recorded days keeps every session.
- Until Sequential has worked out a project's share, for example just after a server starts, it collects no heatmap data for that project.
- If Sequential cannot check the daily limits, it stores no heatmap data until it can. Recordings are not affected.
- With heatmap data on, the recorder that each page loads is about 7.6 KB larger, compressed: about 22 % more, measured with DevTools off. This is on every page load, in the sample or not.
- A heatmap page picture over 4 MB, compressed, is not kept. Sequential answers `too_large` for that page. Sequential also answers `too_large` when the builder refuses a part of the recording: it would use too much memory, it is too dense to read safely, or two earlier attempts on it did not finish. Sequential keeps a `too_large` answer for one hour, and starts no new build for that picture during the hour. Only the builder service builds pictures. A finished picture is kept for at most 15 minutes. See [The page picture](/docs/privacy-overview#the-page-picture).

## Events

| Limit | Value | Result |
|---|---|---|
| One request of events | JSON: 1 MB. Compressed batch from a PostHog SDK: 1 MB compressed, 16 MB decompressed. Form-encoded (events in a `data=` field): 56 KB | Sequential refuses it with 413. |
| Sending from your own servers | Not supported | If the User-Agent names a server-side SDK or HTTP client, Sequential refuses the request as bot traffic (403). Other server-side sending is not supported either. |
| Headless browsers | Not accepted | Sequential refuses them as bot traffic (403). Test in a normal browser. |
| A Sequential SDK session | 30 minutes without an event, or 24 hours after it started | The next event starts a new session. |
| A retried request | Can be stored once, only if every event in it carries the SDK's own event id | Otherwise, Sequential stores the events again. See **Event limits in detail**. |
| Events a project sends | 20,000 events a minute, for all SDKs and keys of the project together. Server default | Sequential refuses the batch that goes over the limit with 429 and stores none of its events. The Sequential SDK waits, then sends the batch again. See **Event limits in detail**. |
| A server that is overloaded | Not a limit of your project | Sequential refuses some event and recording uploads with 503 `overloaded`, and stores none of them. The Sequential SDK and the recorder wait, then send again. See **When Sequential is overloaded**. |

### Event limits in detail

- The 1 MB JSON limit includes the last batch a page sends as it closes. If Sequential refuses a JSON request, it stores none of that request's events.
- Sending from your own servers: examples of clients refused as bot traffic are curl, axios, node-fetch and python-requests.
- Headless browsers: automated tests in a headless browser do not appear.
- A retried request: an SDK sends a request again when it gets a server error or no answer. Sequential drops the retry as a duplicate only if every event in the request carries the SDK's own event id: `uuid` from PostHog and the Sequential SDK, `$insert_id` from Mixpanel, `insert_id` from Amplitude. If one event has no id, Sequential stores all the events in the retry again.
- Sequential does not drop duplicates from the Smartlook shim or Pendo. It also does not drop duplicate runtime issues: the problems that it takes from replay uploads to build findings.
- Sequential compares a retry with the whole earlier request. If an SDK sends the earlier events together with new events, Sequential stores the earlier events again.
- A retry that arrives in a new week is stored again. Weeks start on Monday at 00:00 UTC.
- Sequential remembers about the last 100,000 requests that carry event ids, across all projects on the server. A retry that arrives after that is stored again.
- A self-hosted server whose database was created before this feature drops duplicates only after it applies `migrations/2026-09-28-async-dedup-window.sql`. Until then, it stores every retry again.
- The event rate limit counts per project, not per key. A new key does not reset it. It counts the events from sequential.js, PostHog, Mixpanel, Amplitude, Pendo and Smartlook. Session replay has its own limit: see **Session replay**.
- Each minute starts at 00 seconds on the clock. At the start of a minute, the project can send its full 20,000 events again.
- If a batch goes over the limit, Sequential refuses the full batch. It does not store a part of it. The refused events still count for that minute.
- The answer is 429 with the body `{ "error": "rate_limited", "retry_after_sec": N }` and a `Retry-After` header. N is the number of seconds to the end of the minute. Pendo gets its image with the 429.
- These requests do not count: a batch with no events, and a request that Sequential refused because the website is not in the project's allowed origins.
- The Sequential SDK on a 429: it waits `retry_after_sec`. If there is none, it waits the `Retry-After` value. If there is none, it waits 60 seconds. The wait is 1 second at minimum and 300 seconds at maximum. During the wait, it keeps the refused batch and the events that it records. It keeps at most 100 events and about 128 KB, and drops the oldest first. After the wait, it sends them. It sends a refused batch again only once. If the page closes during the wait, the SDK sends what it keeps as the page closes.
- Other SDKs follow their own rules for a 429.
- A refused batch shows in the project's refused data as `event_rate_limited`. See [Troubleshooting](/docs/troubleshooting).
- If the store that counts the limit is unavailable, Sequential accepts the events.
- See [Sessions](/docs/sessions).

### When Sequential is overloaded

When a Sequential server has too much work, it refuses some uploads at once, before it reads them. Then it can answer the other uploads quickly, and fewer requests time out. This protects the server. It is not a limit of your project: Sequential does not read the project or the key before it refuses.

- The answer is 503 with the body `{ "error": "overloaded", "retry_after_sec": N }` and a `Retry-After` header. N is a random number of seconds from 3 to 8, so that clients do not all send again at the same time. Sequential stores nothing from that request.
- Only uploads are refused: events from the Sequential SDK, PostHog, Mixpanel, Amplitude, Pendo and Smartlook, and recording uploads. The app, the API, sign-in, agents and the loading of the SDK and the recorder are never refused.
- Sequential refuses a part of the uploads. The part becomes larger while requests wait too long in the server, or while the server is too busy, at most 95%. It becomes smaller when the server is calm again: quickly when the server is less than 70% busy, and slowly from 70% to 80%, so that the part does not go up and down. When the server already handles 128 uploads, it refuses each new one until one of them is done.
- From 13 October 2026, how busy the server is counts only when it stays more than 90% busy for 1 second, and only while the server gets about 200 uploads a second or more. So other work on the server, for example a background job, does not make Sequential refuse uploads. At 97% busy or more, the part becomes larger more quickly.
- Measured on a test box, not a promise: one server with half a CPU core, at 3,200 events a second. Sequential refused about 46% of the uploads, answered the other uploads in 160 ms or less (p95), and no request timed out. With no refusals, the same load had a p95 of 23.5 seconds, and about 20% of the requests timed out. A sudden start at 1,600 events a second refused about 2% to 4% of the uploads, nearly all in the first few seconds.
- The Sequential SDK on a 503 `overloaded`: it waits as on a 429. It waits `retry_after_sec`, else the `Retry-After` value, else 60 seconds, from 1 to 300 seconds. It keeps the batch and the new events, at most 100, and sends a refused batch again once. On another 503, it tries again quickly, 3 times in total.
- The recorder keeps the upload and sends it again after about 30 seconds. See **Replay limits in detail**.
- Other SDKs follow their own rules. If a server stored a batch after the SDK stopped waiting, and the SDK then sends the batch again, Sequential stores it once when every event carries the SDK's own event id. See **A retried request** in **Event limits in detail**.
- These refusals do not show in the project's refused data, because Sequential does not know the project at that time.
- On a self-hosted server: GET `/` shows `ingest.shed`, `ingest.shed_fraction`, `ingest.event_loop_lag_p99_ms`, `ingest.sojourn_p95_ms`, `ingest.in_flight` and `ingest.utilization`. `ingest.shed_raised_by` and `ingest.shed_raised_far` count which signal made the part larger (`utilization`, `sojourn` or `lag`), and `ingest.shed_by_cap` counts the uploads refused at 128. `INGEST_SHED=off` turns it off.
- How busy the server is (`ingest.utilization`): the larger of the event loop's busy time and the process CPU divided by the CPU quota. `INGEST_CPU_QUOTA_CORES` sets the quota in cores. Without it, Sequential reads the quota from the cgroup files, else it uses 1 core. The limits are `INGEST_SHED_UTIL_HIGH` (0.90), `INGEST_SHED_UTIL_FAR` (0.97), `INGEST_SHED_UTIL_LOW` (0.80), `INGEST_SHED_UTIL_FAST_LOW` (0.70), `INGEST_SHED_UTIL_TICKS` (4 checks of 250 ms) and `INGEST_SHED_UTIL_MIN_ARRIVALS` (50 uploads in a check).

## Lists and reports

| Limit | Value | Result |
|---|---|---|
| **Individual user actions** on **Events** | The 100 most recent matching events. No paging | "Showing 100 of N recent actions." |
| **Sessions** → **Latest** | 100 rows a page, most recent activity first. The next page loads on scroll or with **Load more**, with no limit on the pages | The count next to the tabs is the number of sessions in the range. If the count takes more than 2 seconds, it reads 10,000+. |
| **Users** list | From 10 October 2026, 100 rows a page, most recent activity first. The next page loads on scroll or with **Load more**, with no limit on the pages | The count next to the title is the number of people in the range. If the count takes more than 2 seconds, it reads 10,000+. Then **Users** shows no tiles. |
| **Accounts** list | 50 rows a page, the accounts with problems first. **Previous** and **Next** move between pages | Up to 10,000 accounts, the most recently active. With more, the count reads 10,000+. |
| **Sessions** on **User detail** | From 10 October 2026, 100 sessions a page, most recent activity first. **Load more** shows the next page | "N of M" counts the person's sessions in the range. If the count takes more than 2 seconds, M reads 10,000+. |
| Replay state on **Sessions** → **Latest** and **Watch**, and in the session list of a user | On **Latest**, the rows of each page, with the page. On the other lists, up to 200 rows with the list, and the other rows when they come into view, up to 200 in one request | Until a row has its state, a dim "…" shows, from the moment the list appears. If Sequential cannot read the state, it tries one more time, about 30 seconds later. Meanwhile, a row with an index of a recording shows ▶, and the other rows keep "…". If the second try also fails, those other rows read "Couldn't check recording", not "No recording". |
| Groups (the group table on **Events**) | 2 levels, top 1,000 rows by count | Later rows are not shown. With two levels, a first-level row can miss some of its second-level rows. Its total is still exact. |

At a list limit, narrow the dates or add a condition.

### List limits in detail

- **Individual user actions**: older events in the range are not listed.
- **Sessions** → **Latest**: each page holds 100 sessions. **With JS errors** and **With failed requests** apply before Sequential splits the list into pages, so they search the whole range.
- **Users** and **Accounts**: see [Users and accounts](/docs/users-and-accounts).
- **Past filters**: the last 10 different filters that you applied on that page, in that project. Sequential removes older entries.
- Breakdowns: with two levels the limit counts pairs. That is why a first-level total can be too low.
- Blank ids: **Events**, **Users**, **Accounts** and **Sessions** never count a blank id as a user, an account or a session. **Funnels**, **Flows** and **Retention** never count an event without a user id as a user.

## AI judging

Background judging is on by default for each project. It runs only while the project's switch is on and your Sequential server allows it, with `JUDGING_AUTOMATIC=on`. If it is off, **Sessions** → **Watch** says why. See [Watch](/docs/watch).

### Background judging

| Limit | Value | Result |
|---|---|---|
| Sessions that can be judged | A session id and at least 3 events that are not System events | Sequential never judges the session. |
| When a session is judged | 30 minutes after its last event. Checked every 5 minutes | Usually 30–35 minutes after the last event. |
| How far back | Last event in the past 7 days | Older sessions are never judged automatically, even when judging is turned on again. |
| A session's background judgment | Made once. No automatic retry after a failure | The session stays "not judged" on **Watch**. |
| Saved background judgment | 400 days after the session ended | The session counts as not judged and is not judged again. |
| Events the judge reads | 255 per session | Sequential drops lower-priority events first. |
| **Watch** ranking | Every judged session in the date range. 100 rows a page | The next rows load when you scroll near the end of the list, or with **Load more**. |

### Background judging in detail

- The **Insights** tab in the replay player judges one session on demand.
- A session with fewer than 3 events that are not System events: **Watch** counts it as not judged. The **Insights** tab says "Not enough activity to judge — fewer than 3 meaningful events".
- Sessions taken per check: 500 per project. The rest wait for the next check.
- Events the judge reads: lower-priority events are, for example, custom events and plain clicks. A judgment made from fewer events ranks like a full one.

### Daily allowances

Values are input tokens per project per UTC day. All reset at midnight UTC.

| Allowance | Value | Result |
|---|---|---|
| Background judging | 5,000,000. Server default | Background judging tries again hourly. **Ask** is not affected. |
| **Ask** in the app | 2,000,000. Server default | "Today's judgment budget is used up · resets …". Background judging is not affected. |
| **Try it**, the rubric preview | 750,000. Server default | "Today's judgment budget is used up · resets …". Background judging and **Ask** are not affected. |
| The **Insights** tab | 500,000. Server default | "On-demand judging has used this project's daily allowance." Saved judgments still open. |
| **Ask** from an agent (`ask_sessions`) | 2,000,000. Server default | 402 `budget_exhausted`. Background judging and **Ask** in the app are not affected. See [Ask from an agent](#ask-from-an-agent). |
| Screening visitor text for agents | 300,000. Server default | New visitor text in an agent's answer reads `{"withheld": "not screened"}`. This includes a token's GET `/api/findings/:n/verification` and the verdict reasons in a token's findings list or one finding. See [Privacy at a glance](/docs/privacy-overview). |

From 15 October 2026, for an organisation in its first 30 days on the free tier, unless Sequential support set its limits, background judging is 500,000 and **Ask** in the app 200,000 input tokens per project per UTC day. If Sequential cannot read the organisation's age, it uses these smaller values.

From 15 October 2026, a Sequential server also has one daily ceiling for all its projects together: 20,000,000 input tokens per UTC day by default. When the server reaches it, every allowance above reads as used up until midnight UTC. The same happens when the operator turns all AI spend off, or when Sequential cannot read the ceiling's count.

The app does not show the allowances or how much of them is used.

### Daily allowances in detail

- Background judging starts again after midnight UTC.
- **Ask** in the app: if Sequential cannot read the allowance, it refuses the search. The server answers 503 `budget_unavailable`, "Ask is unavailable right now. Try again shortly.", with `Retry-After: 30`. It spends nothing. This is not the same as 503 `ask_unavailable`, which means that judging is not set up. A saved answer still returns.
- Operators change the **Ask** allowance with `ASK_DAILY_TOKENS` and the background judging allowance with `BELIEFS_DAILY_TOKENS`.
- **Try it**: find it under Settings → Projects → your project → **Insights**.
- The **Insights** tab: Sequential refuses new judgments until midnight UTC. The tab also says when the allowance resets.
- The **Insights** tab and **Try it**: if Sequential cannot read the allowance, they do not judge. The server answers 503 `budget_unavailable` with `Retry-After: 30`. Sequential spends nothing and does not call the judge. The **Insights** tab shows "Insights failed (Insights can't run right now. Try again shortly.)". **Try it** shows "Preview failed" and "Can't test the rubric right now. Try again shortly.". Both show **Retry**.
- The allowance of the **Insights** tab also pays for the screening of fix briefs and for the key actions that the judge picks for **Dashboard**.
- If Sequential cannot read the allowance, the screening of fix briefs and the key actions for **Dashboard** continue, with a cap. Each server process allows, per project, 10 brief screenings a minute and 5 key-action judgments a minute. With more than one server process, each process has its own cap.
- Past the screening cap, Sequential does not screen the brief. It withholds every quoted passage, and the brief says "screen paused". Sequential does not keep this result, so a later request screens as usual. See [Privacy at a glance](/docs/privacy-overview).
- Past the key-action cap, a new dashboard starts with **Most frequent events** instead of **Key actions**, and without **Failed or abandoned**. The dashboard keeps these tiles. An add of **Key actions** says "Key actions can't be worked out right now. Try again later." An add of **Failed or abandoned** says "Failed and abandoned events can't be worked out right now. Try again later."

### The Insights tab and Try it

| Limit | Value | Result |
|---|---|---|
| Events the **Insights** tab judges | From the first 2,000 events the player loads | Later events are not judged there. |
| **Re-run** | Once every 10 minutes per session | Another **Re-run** returns the saved judgment. |
| Saved **Insights** judgment | 7 days | Opening the tab judges the session again. |
| **Insights** browser wait | 45 seconds | "Timed out after 45 s — try again." |
| **Try it** previews | 10 per person per minute | "Too many previews — try again in N s" |

### The Insights tab in detail

- Events the **Insights** tab judges: clicks and page changes read from the recording still come from the whole session.
- **Re-run**: within 10 minutes of a **Re-run**, the tab says "Already judged — same events, same questions, so the verdict below is unchanged."
- Waiting in the browser: **Retry** can return a judgment that the server finished in the meantime.

**Why re-judging is limited**

Sequential limits re-judging on purpose. Every new judgment is a new call to the judge. So Sequential reuses saved judgments.

### Rubric size

If a rubric breaks a limit, Sequential refuses the save and marks the field that broke it. See [Session insights](/docs/session-insights) and [Customise the rubric](/docs/rubric).

### Rubric size limits

| Limit | Value |
|---|---|
| Questions | 24. At most 5 of them can be moment questions |
| Options per list question | 2–30 |
| Levels per scale | 2–7 |
| Labels | Up to 40 characters |
| Question text | Up to 300 characters |

### Saved filters, funnels and flows

There is no limit on how many items a project can save. Each item has these limits:

| Limit | Value |
|---|---|
| Name | 1–200 characters, after spaces at the start and end are removed |
| Size | 32 KB for the conditions, steps and dates together |
| Conditions and groups | 500 in one filter, and in each funnel or flow step |
| Nested groups | 25 levels |
| Steps | 100 in a funnel or flow |
| Days | 1 to 10 in a retention question, each a whole number from 1 to 365, with no repeats |

If an item breaks a limit, Sequential does not save it. The dialog says why, for example "Couldn't save this filter: definition too large." See [Filters, date ranges and saved views](/docs/filters-and-saved-views).

## Ask

| Limit | Value | Result |
|---|---|---|
| Your description | One line, 3–200 characters | "Describe what you are looking for in at least 3 characters". The box stops at 200. |
| Sessions considered | 2,000 most recently active in your dates and filters | Older sessions are not considered. Narrow the dates or add filters. |
| Sessions judged per run | 200 | **Search N more** judges the next 200, as a new run. |
| Sessions judged together | Up to 8 | "· some sessions could not be judged". Sequential does not save that answer. |
| Saved answer | 1 hour | The same question over the same sessions uses no allowance. |
| Waiting in the browser | 60 seconds | "Ask failed". The run can still finish and use the allowance. |

**Ask** lists only likely matches. A short or empty list does not mean that nothing matching your description happened. See [Ask: find sessions by describing them](/docs/ask).

### Ask in detail

- Daily allowance: **Ask** in the app has its own. See [Daily allowances](#daily-allowances). When it is used up: "Today's judgment budget is used up · resets …"
- **Ask** does not show sessions that the judge rated below its cut-off.
- Sessions considered: each needs a session id and at least 3 events. The footer, "Searched the N most relevant of M sessions", counts only these, so M is never more than 2,000. An M of 2,000 means Sequential left out older sessions.
- Sessions judged per run: each click on **Search N more** is a new run on the daily allowance.
- Sessions judged together: Sequential judges up to 8 at a time. The footer adds "· some sessions could not be judged" if Sequential cannot judge a group.
- Waiting in the browser: after "Ask failed", **Retry** can return the saved answer of the run that finished.

### Ask from an agent

An agent runs **Ask** with the tool `ask_sessions`. The token needs the scope `ask:use`.

| Limit | Value | Result |
|---|---|---|
| Sessions judged per call | `limit`: 1–50, default 25 | Over 50: 400 `limit_too_large`, with `max`: 50. Sequential spends nothing. |
| The window | `days`: 1–30, default 7. The last N days, with no filters | A value out of range is a tool error. |
| The agent allowance of the project | 2,000,000 input tokens per UTC day. Server default. All tokens of the project share it | 402 `budget_exhausted`, with `resets_at` and `budget` |
| The allowance of one token | 500,000 input tokens per UTC day. Server default | 429 `token_daily_limit`, with `resets_at` |
| `ask_sessions` calls at the same time, per server process | 1 per project, and 2 for all projects together. Server defaults | 429 `ai_concurrency` when your project already has a call running; 503 `ai_busy` when the process is full, also with calls of other projects. `Retry-After: 10` |
| Sequential cannot read the allowances | Sequential refuses the call | 503 `ai_unavailable`, with `Retry-After: 30`. If the judge already read some sessions, the call stops instead, with `stop_reason` `ai_unavailable` |

The endpoint `/mcp/readonly` does not stop this spend. To stop an agent from running **Ask** and spending the agent allowance, give it a token without `ask:use`. Other agent tools still spend the screening allowance.

### Ask from an agent in detail

- Sequential checks the allowance of the token first, then the allowance of the project.
- Sequential estimates the tokens of each group of up to 8 sessions before the judge reads it. If the next group does not fit in an allowance, Sequential does not send it. So Sequential can refuse a call before an allowance is fully used. The estimate can also be low, for example for sessions with many ids. Then a call can take an allowance a little over its limit. Sequential charges what the judge actually used.
- If an allowance runs out after the judge has read some sessions, the call does not fail. The answer has `stopped`: `"budget"`, a `stop_reason` and a `next_cursor`. The answer keeps the matches from the sessions that the judge read. Sequential charges only what it spent. Sequential does not save an answer that stopped.
- The limits on calls at the same time count per server process, not across servers. A call holds its place from its first paid judgment to when it ends. With more servers, more calls can run at the same time.
- A saved answer uses none of the agent allowance. But Sequential first checks that the project and the token still have agent allowance left, before it reads anything. If one is used up, or Sequential cannot read the allowances, the call is refused, also when a saved answer exists. A saved answer holds no concurrency slot, so it cannot get 429 `ai_concurrency`. Screening its labels can still use the allowance for screening visitor text. The app and an agent share saved answers: the same question over the same sessions returns the saved answer.
- Screening the answer uses the allowance for screening visitor text. See [Daily allowances](#daily-allowances).
- Operators change the limits with `AGENT_DAILY_TOKENS`, `AGENT_TOKEN_DAILY_TOKENS`, `AGENT_JUDGE_MAX_CONCURRENT` and `AGENT_JUDGE_MAX_CONCURRENT_PER_PROJECT`.
- For each refusal, see [Troubleshooting](/docs/troubleshooting).

## Findings and fixes

| Limit | Value | Result |
|---|---|---|
| A new finding | A JavaScript error, or a request that fails with a 5xx or a network failure: 1 session. Every other problem: at least 3 sessions, of at least 2 people, in the last 7 days. With the Sequential SDK, PostHog or Mixpanel, one person counts once, even if they signed in between. | Below this, Sequential does not make a finding. |
| The **Findings** page | 50 findings | "Showing the top 50 findings." |
| A fix link | `https://` only, at most 500 characters, no control characters | Sequential refuses the link, for example "url: at most 500 characters". |
| Findings named on one release | 50 | POST `/api/releases` refuses more: "finding_ids: up to 50 ids like F-12". The `sequential release` command reads the first 50. |
| A release version | 1–64 printable ASCII characters | Sequential refuses the release. |
| **Open a GitHub issue** | 7,500 characters of link | Longer: the issue opens without a body, and Sequential copies the brief for you to paste. |
| Before window | 14 days before the release, or from when the finding was first seen | Counted once, then frozen. Counted again when Sequential changes how it finds that kind of problem. |
| After window | Up to 28 days after the release | Still too few sessions: **Not measured**. |
| Regression watch | 30 days after **Confirmed fixed** | After that, the result is final. |
| Measurements | About once an hour, at most 200 findings a run over all projects | Findings not measured yet go first, then the findings measured longest ago. |

- For a token without `findings:verify`, the stage of a finding is one of `new`, `handed_off`, `fix_linked` or `dismissed`. `measuring` and every result come back as `{"withheld": "needs findings:verify"}`. (`fix_released` is also allowed, but the list and one finding never show it.)
- A token cannot remove a fix link.

See [Findings and fixes](/docs/findings).

## Reading your data

Every page that reads analytics or replays counts against one limit: 300 requests a minute, per person per project. Server default. Each replay state request that a page sends counts too, for a row that comes into view or for a "Processing" row that checks again. **Latest**, **Watch**, **Ask**, the session list of a user, the sample sessions of a finding and the **Worth watching** tile send these requests. A page sends at most one such request a second, for all its lists together.

Over the limit, Sequential refuses requests for a moment: "Too many requests for this project. Try again shortly." After such a refusal, the page stops its replay state requests for that project until the time that Sequential gives, or for 1 minute.

### When the store that counts limits is unavailable

Sequential sizes the read limit so that a person who works normally does not reach it. If the store that counts the read limit is unavailable, Sequential lifts the limit, so pages keep working.

The "running at once" limits do not depend on that store.

## Sign-in and account protection

Limits count per network address, so teammates behind one office network share them. Over a limit: "Too many attempts. Wait a minute and try again."

| Action | Allowed from one network address |
|---|---|
| Sign in with email and password; enter a two-factor code, at sign-in or during set-up | 10 a minute |
| Sign up with email and password; request a password reset; enter a backup code | 5 a minute |
| Resend the verification email | 3 a minute |
| **Continue with Google**, change your password, set up or disable two-factor authentication, regenerate backup codes | 3 every 10 seconds |
| Join the waitlist | 5 every 10 minutes |
| Any other sign-in or account action | 100 a minute |

Per account, for two-factor codes:

- **Five wrong codes in one sign-in** end it: "Too many attempts. Please request a new code." Start the sign-in again.
- **Ten wrong codes in a row** lock code entry for 15 minutes. The message says "Too many attempts. Wait a few minutes and try again."

New accounts per day (a UTC day), server defaults:

- **5 from one network address**, **30 for one email domain** and **200 in total**.
- An address with a pending invitation skips the network and domain limits, but counts toward the total.
- Large free-mail domains, such as gmail.com, outlook.com, icloud.com, proton.me, gmx.de and seznam.cz, skip only the domain limit.
- Only accounts that are actually created count: an email sign-up, a first **Continue with Google**, and sign-up from an invitation.
- Over a limit: 429, with Retry-After until the end of the UTC day. If Sequential cannot check the limits: 503, try again in a minute.

Password sign-in has no per-account lockout, only the per-address limit. See [Two-factor authentication and account security](/docs/two-factor-and-security).

### Sign-in limits in detail

- Sequential limits how often each action can be tried from one network address, to slow down guessing. The limits count per address, not per person.
- Join the waitlist: over the limit, the form says "Too many attempts. Wait a few minutes and try again."
- Ten wrong codes in a row count across sign-ins. A correct code resets the count.

## Programmatic access

An agent or a CI job can use a **project access token**. Owners and admins create tokens under Settings → Projects → your project → **Access tokens**, or on the **Agents** page under **Advanced: create an access token**. See [Connect your agent](/docs/quickstart#connect-your-agent).

A token works only on the routes that its scopes allow. Every other route of the app's API needs a person's signed-in session. Sequential has no service accounts, webhooks or export endpoint.

| Scope | In the app | What it allows |
|---|---|---|
| `findings:read` | "Read findings and fix briefs" | Read the findings list, one finding, a finding's sessions and its fix brief |
| `sessions:read` | "Read session summaries" | Only the tool `get_session` |
| `sessions:explore` | "Read sessions, verdicts, the rubric and calibration" | The tools `list_watch`, `list_sessions`, `get_user_journey`, `get_session_full`, `get_session_timeline`, `list_errors`, `get_struggle_by_segment`, `get_rubric`, `get_calibration` and, from 15 October 2026, `list_heatmap_pages` and `get_heatmap`. They only read |
| `releases:write` | "Mark releases from CI" | Record a release |
| `findings:link` | "Link a pull request, commit or issue to a finding" | Add a pull request, commit or issue link to a finding. It cannot remove a link |
| `findings:verify` | "Read a finding's measurement after a release" | Read a finding's measurement after its fix release |
| `ask:use` | "Search sessions by description (spends the project's daily agent allowance)" | The tool `ask_sessions`. It runs **Ask** and spends the agent allowance of the project. See [Ask from an agent](#ask-from-an-agent) |
| `analytics:read` | "Read analytics: events, funnels, flows, users and retention". Both read presets include it; **For CI: mark a release when you deploy** does not | The eleven analytics tools: `get_overview`, `search_events`, `get_histogram`, `get_breakdown`, `funnel_analysis`, `user_flows`, `list_users`, `list_entities`, `get_event_types`, `suggest_property_values` and `retention_analysis`. They only read. See [Analytics from an agent](#analytics-from-an-agent) |
| `findings:draft` | "Ask for a draft fix (a person approves each one)". No preset includes it, and claude.ai never gets it | The tool `request_fix_draft`. It asks for a draft fix; an owner or admin approves or declines it on the finding. It writes, so it is not on `/mcp/readonly`. See [Findings and fixes](/docs/findings) |
| `insights:propose` | "Propose changes to the Insights questions (a person applies them)". It works only with `sessions:explore`: when you tick it, the form also ticks `sessions:explore` and keeps it ticked. No preset includes it. A claude.ai connection gets it only when the person ticks it on the consent page | The tool `propose_rubric`. It stores a proposal; an owner or admin applies or rejects it on the **Insights** tab. It writes, so it is not on `/mcp/readonly`. See [Proposals from an agent](/docs/rubric#proposals-from-an-agent) |

| Limit | Value | Result |
|---|---|---|
| Token requests | 120 a minute per token. Server default | 429: "Too many requests for this access token. Try again shortly." |
| The store that counts token requests is unavailable | Sequential refuses token requests | 503: "The token rate limit cannot be checked right now. Try again shortly." |
| Token reads per project | 600 a minute, for all tokens of the project together. Server default. By default, Sequential only counts them | Only when the operator turns the limit on: 429 `project_rate_limited`. See **The project read limit for tokens** below |
| Token expiry | 30, 90 or 365 days. The default is 90. No token lasts longer. The token that an agent gets with a trial lasts 3 days from setup ([Agent trials](/docs/agent-trial)) | The token stops working. |
| Scopes per token | 1 or more, each at most once. The app offers all 10 scopes | Sequential refuses the token. |
| Token name | 1–60 characters | Sequential refuses the token. |
| claude.ai connections | 10 per person per project, and 50 per project. They are not access tokens, but each one has the same request limits as a token | See [Connect claude.ai](/docs/connect-claude-ai#limits). |

**Agent: read everything, plus Ask** ticks five scopes: `sessions:explore`, `ask:use`, `findings:read`, `findings:verify` and `sessions:read`. It never ticks `releases:write` or `findings:link`. It does not tick `analytics:read`, so a token from the app cannot use the analytics tools. A new claude.ai connection gets `analytics:read`. See [Connect claude.ai](/docs/connect-claude-ai#the-consent-page). On the **Access tokens** tab, it is a button, and it replaces the scopes that were ticked.

On **Agents**, **Advanced: create an access token** is closed at first. Its form starts with a name: "Agent on" and the date of today, for example "Agent on 29 Sept 2026". Under **Access**, you choose one of four options. The scope ids of each option show in small text under it:

| Option | Scopes |
|---|---|
| **Agent: read everything, plus Ask**. Selected at first. The app says "recommended. Ask (searching sessions by description) spends the project's daily agent allowance." | The five scopes above |
| **Read everything, no Ask** | The same, without `ask:use` |
| **For CI: mark a release when you deploy** | `releases:write` |
| **Custom…** ("pick each permission") | The ones that you tick. Only this option shows a box for each of the 10 scopes. |

On the **Access tokens** tab, the name starts empty and only `findings:read` is ticked.

The **Access tokens** tab also has a **Connect an agent** card. It shows the setup for **Claude Code**, **Cursor**, **Codex**, **Other MCP clients (JSON)**, **Claude Desktop** and a **Read-only endpoint (no write tools)**. For **claude.ai**, it shows the connector URL and **Copy**. If Sequential could not check that the claude.ai sign-in is on, it shows "Couldn't check whether claude.ai is available" and **Retry**. If your server answers that the sign-in is off, it shows "Not available yet." See [Connect claude.ai](/docs/connect-claude-ai). For **ChatGPT**, it shows only "Not available yet." The card starts with "Give a coding agent or a CI job its own token, then add the Sequential endpoint to it. In the snippets that use a token, replace `<token>` with the token you created." It adds "claude.ai connects with its own sign-in, no token." only when it shows the claude.ai connector URL. See [Connect your agent](/docs/quickstart#connect-your-agent) for where each setup goes. **Agents** does not have this card. There, the **claude.ai** card has the connector URL. After **Create token**, the new token shows once, with the setups for **Claude Code**, **Cursor** and **Claude Desktop**.
- A token stops working when its project is archived.
- If Redis is down, another server can accept a revoked token for up to 30 seconds.

> **A token can never set a verdict**
>
> A verdict on a finding needs a person. No REST route and no MCP tool lets a token set one.

Ingest keys are public. They can never read events, sessions or judgments. See [Organisations, projects and keys](/docs/organisations-and-projects).

### Ingest keys and the app's API

- A request with a person's signed-in session gets exactly that person's access.
- Find the **Ingest keys** under Settings → Projects → your project → **Sources & keys**.
- Ingest keys go in your pages and apps, so treat them as public. They can send data and get the project's recording settings.

### Routes a token can use

| Route | Scope |
|---|---|
| GET `/api/findings`, `/api/findings/:n`, `/api/findings/:n/sessions`, `/api/findings/:n/brief` | `findings:read` |
| POST `/api/releases` | `releases:write` |
| POST `/api/findings/:n/links` | `findings:link` |
| GET `/api/findings/:n/verification` | `findings:verify` |
| GET `/api/projects/:id/rubric`, `/api/projects/:id/rubric/history` (from 11 October 2026) | `sessions:explore` |
| Tools `list_findings`, `get_finding`, `get_fix_brief`, `list_finding_sessions` | `findings:read` |
| Tool `get_session` | `sessions:read` |
| Tools `list_watch`, `list_sessions`, `get_user_journey`, `get_session_full`, `get_session_timeline`, `list_errors`, `get_struggle_by_segment`, `get_rubric`, `get_calibration`, `list_heatmap_pages`, `get_heatmap` | `sessions:explore` |
| Tool `record_release` | `releases:write` |
| Tool `link_fix` | `findings:link` |
| Tool `get_verification` | `findings:verify` |
| Tool `ask_sessions` | `ask:use` |
| Tool `request_fix_draft` | `findings:draft` |
| Tool `propose_rubric` | `insights:propose` |
| Tools `get_overview`, `search_events`, `get_histogram`, `get_breakdown`, `funnel_analysis`, `user_flows`, `list_users`, `list_entities`, `get_event_types`, `suggest_property_values`, `retention_analysis` | `analytics:read` |

- The table lists all 33 agent tools.
- A finding's sessions list needs `findings:read`, on REST and on MCP. `sessions:read` does not allow it.
- In a finding's sessions list, and in the `samples` of a finding's evidence (GET `/api/findings/:n` and the `get_finding` tool), each session has `replay_state` and `replay_ready_by` next to `has_replay`. `replay_state` is `ready`, `processing`, `expired` or `none`. `replay_ready_by` is the time when a `processing` recording will be ready, else null. The two fields can be absent, for example when Sequential cannot read the state within its time limit. Then use `has_replay`, which only tells if Sequential has an index of a recording.
- From 14 October 2026, for a dead end, each sample in `samples` also has `returned`: `back`, `app` or `unknown`, how the visitor came back. A sample without a kind has no `returned`. Each finding in the list and in `get_finding` has `returns`: `{ back, app, unknown }`, the dead end's sessions by how the visitor came back. It is `null` for the other kinds, and for a dead end found before the counts existed.
- For a token, each `session_id` in these lists comes as `{"id": "…", "source": "observed"}`, and a release name in a finding's sessions list comes as `{"withheld": "not screened"}`. See [Privacy at a glance](/docs/privacy-overview).
- With a token, GET `/api/projects/:id/rubric` and `/rubric/history` give the answer of the `get_rubric` tool, screened. `:id` must be the token's project, else the answer is 404. The history gives at most 20 changes and never who made them. Changing or resetting the rubric, and **Try it**, need a person's signed-in session.
- GET `/api/releases` does not accept a token.
- POST `/api/findings/:n/verdict` accepts only a person's signed-in session. So does DELETE `/api/findings/:n/links/:id`, which removes a link.
- An agent calls a tool through MCP, or with POST `/api/agent/<tool>` and the tool's arguments as a JSON object. The two give the same data. With a token, GET `/api/findings/:n/verification` runs the `get_verification` tool and gives the same answer too. It counts once toward the project read limit. If a limit refuses it, the answer keeps the status and the Retry-After of that limit. For a tool outside the token's scopes, REST answers 403 `insufficient_scope`, and MCP answers "Tool not available for this token".
- The MCP endpoint is `/mcp`. The endpoint `/mcp/readonly` never lists `record_release` or `link_fix`. It lists `ask_sessions`, so a read-only connection with an `ask:use` token can spend the agent allowance. POST `/api/agent/record_release` has no read-only form: it works with `releases:write`.
- The MCP server name is `sequential`.
- A token cannot create, list or revoke tokens. These actions need a signed-in owner or admin.

### Agent activity

- GET `/api/projects/:id/agent-activity` shows how the access tokens of a project used the agent tools. The **Agents** page in the app shows it under "Activity, last 7 days". For each token, it shows the calls, the removed and withheld counts and the last call. The page explains the two counts: "Removed: text our screen flagged and took out. Withheld: text we sent back unread because we couldn't check it." If no agent called in the 7 days, it shows "No agent calls in the last 7 days." Under **Recent calls**, it shows the newest 50 calls. If Sequential cannot read the log, the page shows "Activity isn't available right now."
- It needs the signed-in session of an owner or admin. It does not accept an access token.
- `days`: 1–30. The default is 7. Any other value gets 400 `bad_request`: "days: an integer 1-30".
- The answer has `window_days`, `state`, `per_token`, `recent`, `tokens` and `tokens_state`.
- `per_token` has one row for each token that has calls in the window. The token with the most calls is first. Each row has `token_id`, `calls`, `removed`, `withheld`, `input_tokens` and `last_call_at`.
- `recent` has the newest 50 calls, newest first. Each call has `tool`, `token_id`, `consumer` (`mcp` or `rest`), `observed`, `removed`, `withheld`, `input_tokens` and `delivered_at`.
- `observed` is the number of different observed text values in the answer. `removed` is the number that the screen removed. `withheld` is the number that Sequential withheld for another reason, for example because it could not screen them. `input_tokens` is the paid AI input tokens of the call: the screen, and the judging of `ask_sessions`. In `per_token`, the counts are totals.
- Times are in UTC, in ISO 8601 format.
- The answer counts only the calls that the agent call log records. These are the successful calls of every agent tool except `record_release`. A token's GET `/api/findings/:n/verification` runs `get_verification`, so it is counted too. The answer does not count `record_release`, a call that failed, or the REST routes GET `/api/findings` and `/api/findings/:n`.
- Sequential writes the log on a best-effort basis. A missing call does not prove that the call did not occur.
- `state` is `ok` or `not_measured`. `not_measured` means that Sequential could not read the log, for example because the read took more than 10 seconds. Then both lists and `tokens` are empty, and `tokens_state` is `unavailable`. Empty lists with `not_measured` do not mean zero calls. The status is still 200.
- `tokens` gives a name for the token ids in `per_token` and `recent`. Each entry has `id`, `name`, `kind` and `identified_as`. `name` is the name that the token got when it was created. A revoked token keeps its name. `kind` is `pat` for the tokens that you create, and `oauth` for a claude.ai connection. `identified_as` is the name that the agent's MCP client sent, at most 60 characters, or null. Sequential does not check it.
- `tokens_state` is `ok` or `unavailable`. `ok` means that the name lookup succeeded, or that there were no token ids to look up. `unavailable` means that Sequential could not look up the names, or could not read the log. Then `tokens` is empty. An empty `tokens` with `unavailable` does not mean that the tokens have no names.

### Session tools in detail

- `list_watch`: the sessions that **Watch** ranks highest, and the sessions that the judge was unsure about. `days`: 1–30, default 7. `limit`: 1–100, default 25, for the two lists together. The unsure list gets at most a quarter of `limit`. Each row has a `severity`: `broke`, `struggled` or `minor`, the Watch group of the session ([Watch](/docs/watch)). `null` means the session is not judged.
- `list_sessions`: the sessions with the most recent activity first, by the time of the last event of each session, not its start. The same `days` and `limit`. With `judged_only: true`, only judged sessions.
- **Rows and counts.** From 10 October 2026, each row of `list_watch` and `list_sessions` gives `last_page`: the page that the session ended on, not the page where a signal happened. Before, this field was `path`. Each answer also gives `sessions_total`, and `list_watch` gives `unsure_total`: how many sessions match in the whole window, or `null` when Sequential cannot count them in time. `truncated` is true when the answer leaves out sessions. Then narrow `days`, `user_id` or `belief_filters`. `beliefs_meta` counts every session in the window, before `belief_filters` and `judged_only`.
- **From 10 October 2026:**
  - A compact row's judgment also has `struggling`: true when the friction is at the middle of the friction scale or higher. This is the same rule as in `get_struggle_by_segment`.
  - `list_watch` takes `platform_os`: only the sessions with an event on that operating system, with the name that a row shows. From 12 October 2026, the case of the name does not matter: `android` and `Android` match. `get_struggle_by_segment` by `platform_os` also puts both in one group, `Android`.
  - From 12 October 2026, the filters and breakdowns of an agent also take `platform`: `web`, `ios`, `android` or `other`. It tells the website from the app. Safari on an iPhone is `web`, and the iOS app is `ios`. An app view that shows a web page also counts as `web`. A `platform` filter takes only these four values. Sequential refuses any other value. There is no device filter. For devices, use `get_struggle_by_segment` by `device`.
  - From 15 October 2026, the filters and breakdowns of an agent also take `traffic_source`: the other site that a visit came from, as its host without `www.`, such as `google.com`. A visit with no referrer, or from a page of the same site, has an empty value: direct or internal. Another domain of your project counts as another site. `utm_referer` still gives the full referrer address.
  - `list_watch` with `detail: "counts"` gives no rows, only counts over every session in the window and filters: `judged`, `unjudged`, `struggling`, `need_a_look`, `routine` and `unsure`. It does not use `limit`.
  - `list_sessions` takes `order: "asc"` for the oldest first, by the last event of each session. It cannot be used with `judged_only` or `belief_filters`.
  - A `list_sessions` row has `ended_at`, also in compact detail, and `is_first_session`: true when it is the first session of its person that Sequential holds, false when that person has an earlier one, `null` when Sequential cannot check.
- `list_watch` and `list_sessions` also take these arguments:
  - `has_errors: true` or `has_failed_requests: true`: only the sessions whose recording measured at least one JS error, or at least one failed request. A session without a recording, or without measured DevTools data, never matches. Then the answer has `devtools_meta`: the number of recorded sessions in the window, for the whole project, that were not measured or did not capture that kind. So an empty list does not prove that there were no errors. The value `false` gets a tool error. To get all sessions, leave the argument out.
  - `belief_filters`: up to 10 `{ key, min }`. Only judged sessions where each value is at least `min`, for example `friction_score` or a signal. The keys are in `get_rubric`.
  - `user_id`: only the sessions of one person. An anonymous id that was identified later finds the same person.
  - `detail`: `compact` (the default) gives the top answer of each verdict, the friction label, and the signals that are on or unclear. `full` gives every answer with its probability and the state of every signal.
  - Two shapes: an `ask_sessions` result always has the full judgment. Its `verdict_intent` and `verdict_outcome` each have `id`, `value`, `label`, `probability`, `confidence` and `options`. `list_watch` and `list_sessions` give the compact shape unless you ask for `full`, and `get_user_journey`'s `verdict` is always compact. An agent that compares sessions from these tools must read both shapes.
  - A label is a string when it comes from Sequential's default rubric. When the project edited its rubric, a label is `{"observed": "…"}`: text that a team member typed, after the screen. If the screen removed it, the label is `{"withheld": …}`. An agent must read all these forms.
  - A `compact` row of `list_watch` has no `ended_at`: use `started_at` and `duration_ms`. Its probabilities and `attention` have 2 decimals. Its `devtools` is `"none"` when the recording was measured and had nothing, or else only the counts that are not 0. A count that is not there is 0. With `suppressed: true`, Sequential dropped some entries, so the counts are lower bounds. `full` gives `ended_at` and every DevTools count.
- `get_session_full`: one session, with its judgment, its moments and its DevTools counts. If the session has a recording, each moment has a replay link.
- **Pages of one session.** From 10 October 2026, `get_session` and `get_session_full` give `pages`: up to 10 route templates, the 10 with the most events, in the order that the session first visited them. Each page has `events`, the number of events of every kind on it (not page views, and not time), and `first_offset_ms`, the time from the start of the session to its first event there. `pages_total` counts all the pages of the session. A page that the session visited again is listed once, so `pages` is not the path. For every step in order, use `get_session_timeline`.
- `get_user_journey`: from 10 October 2026, the sessions of one person in the order they started, oldest first. `user_id` is any id of the person: an anonymous id that later identified finds the same person. `days`: 1–30, default 30. It gives at most 50 sessions. With more, `truncated` is true and `sessions_total` counts all of them. Each session has `first_page`, `last_page`, `pages_total`, the compact judgment as `verdict`, `overlaps_previous` and `is_first_session`. `overlaps_previous` is true when the session started before an earlier session of the list ended, for example in two tabs or on two devices. `identified` is true when an identify call linked an anonymous id to the person. `false` does not mean anonymous. The tool gives ids only, never a name, an email, an IP address or a property.
- `get_session_timeline`: one session, event by event, in order: each page, click, form submit, custom event and error, with its time from the start of the session. From 10 October 2026, the answer also names the session's person: `user_id` after identity resolution, and `anonymous_id`, the id that the session sent, when it differs. If Sequential cannot look up the person in time, `user_id` comes as `{"withheld": "not resolved"}`. These are the events that the judge read. Sequential does not show system events, and for a long session it keeps the 255 most informative events, in order. Each event has an id, for example `E001`. A moment of `get_session_full` names the same id. `limit`: 1–120 events, default 60. `start`: 1–255, default 1. If there are more events, use `next_start` as `start` to get the next part. A session with fewer than 3 events has no timeline: `timeline_state` is `too_short`.
- **Replay links.** From 11 October 2026, `replay_url` is null when Sequential holds no recording of the session. It is also null when Sequential cannot check this in time. The tools tell the agent: "replay_url is null when Sequential holds no recording of the session." `get_session_timeline` has `has_replay`: true, false, or null when Sequential cannot check. Each session of `get_user_journey` has `has_replay`.
- `list_errors`: the JS errors and failed requests of the project, in groups. The group that the most sessions hit comes first. From 14 October 2026, a group's `page` is the page where it happened most often, the same page as its finding. Each group also has `finding`: `{ number, id, status, verdict }` when Sequential holds a finding for the same problem. `id` is like `F-12`, `status` is `open` or `dismissed`, and `verdict` is the team's latest verdict (`not_a_problem`, `wont_fix`, `confirmed` or `reopened`) or `null`. `finding` is `null` when there is no finding, `{"withheld": "needs findings:read"}` for a token without that scope, and `{"withheld": "not available"}` when Sequential could not check. The rows of `get_overview`'s `errors.top` have the same `finding`. `days`: 1–30, default 7. `limit`: 1–50 groups, default 20. Each group has up to 3 sample sessions. A sample has a replay link only when Sequential holds a recording of it. A group has no minimum count, so an error that is too rare to become a finding is in the list too. With `session_id`, it gives the errors and failed requests of that one session in time order, up to 100. Each has a replay link at that moment when Sequential holds a recording of the session. Then it reads the time of that session, not the last `days` days, and it refuses `kind` and `limit`. The errors come from recordings with DevTools on and from `$exception` events. Console messages are not included. Each sample also has `user_id`. From 12 October 2026, it is the person of that session, resolved as on a session row. Only when Sequential resolves no person for the session is it the id that the occurrence was stored with. `users` counts these people.
- `get_struggle_by_segment`: how the judged sessions went, in groups of one field (`by`): `page`, `device`, `platform_os`, `browser` or `country_code`. For each group, it gives the judged sessions, how many of them struggled, the average friction, the 3 most frequent signals and outcomes, and the 2 sessions with the most friction, each with a replay link when Sequential holds a recording of it. A session struggled when its friction is at the middle of the friction scale or higher: 1.5 or more on the default scale of 4 levels. A signal counts when the judge gives it 0.7 or more. With `page`, a session counts in each route template that it viewed, so pages overlap. `device` is `mobile` for iOS and Android, `desktop` for other operating systems, and `unknown` when there is no operating system. The other fields come from the latest event of the session. Only judged sessions count. A group with fewer than 5 judged sessions has `small_sample` set to true: its percentages are not rates. `days`: 1–30, default 7. `limit`: 1–50 groups, default 10, with the most judged first. `min_judged`: 1–1000, default 1. It reads at most 20,000 judged sessions. When it leaves out groups or sessions, `truncated` is true. An example session has `internal: true` when its person is marked internal.
- From 15 October 2026, `list_heatmap_pages` and `get_heatmap` read the counts of [Heatmaps](/docs/sessions-and-replay). `list_heatmap_pages` lists the web pages with heatmap data, up to 20 (default 10), by views or by frustration: rage bursts per 1,000 views, with pages of little data last. When every page of the window has little data, `all_low_data` is `true`. Each page has a `page_ref`. `get_heatmap` takes a `page_ref` or a page address, and one device class. It gives the most clicked elements, the elements that frustrate people, and scroll depth, up to 20 elements in a list (default 10). For up to 3 elements with rage clicks in the days that the **Sessions** list reads, the most rage clicks first, it also gives up to 5 recent sessions each, from that list. Both take `days` 1–90 (default 7).
  - The counts come from the sampled sessions of Heatmaps. A device class is the layout width of a web page: mobile below 768 px, tablet below 1,024 px, desktop from 1,024 px. Mobile apps have no heatmaps.
  - An element is named by its kind, its place and a path of tags and positions. Sequential withholds element text, class names, ids and the names of custom elements: an unknown tag shows as `…`. An agent never gets the page picture.
  - The counts include your team, and the answer says so: `internal.counts_separable` is `false`. There is no `exclude_internal`.
  - When heatmap data is off for the project, the answer is `off` with the reason. With no data in the window it is `not_measured`, and with no numbers.
- `get_rubric`: from 11 October 2026, the whole rubric as `document`: each question's id, kind, label, role and text, its options or levels with their criteria and phrases, and its weight. It also gives `limits`: the most questions, options and levels, and the longest texts, that a rubric can have. `questions`, the earlier short form, stays for now. With `history: true`, it lists the changes instead, newest first: the version, the ids that were added, removed or reworded, the time, and `changed_via` (`staff`, `agent`, or null for a person in the app). It never names who made a change. `limit`: 1–20, default 20, only with `history`. Sequential screens the texts of a custom rubric. See [Privacy at a glance](/docs/privacy-overview).
- `get_calibration`: how often the judge was right, per question, for the current wording only. `days`: 1–400, default 90.
- The session tools read the same data as the **Sessions** page.
- In `get_session` and the `sessions:explore` tools, each read of stored session data stops after 10 seconds. This does not apply to the read of the rubric. Then the tool answers "Internal error" (500 `internal_error` at POST `/api/agent/<tool>`). If only the DevTools read of `get_session_full` fails, the answer has `devtools` null and the warning `devtools_unavailable`. If only the judgments cannot be read in `list_watch` or `list_sessions`, the answer has `beliefs` null and the warning `beliefs_unavailable`.
- For how the session tools show visitor text, see [Privacy at a glance](/docs/privacy-overview).

### Analytics from an agent

The scope `analytics:read` gives an agent eleven tools: `get_overview`, `search_events`, `get_histogram`, `get_breakdown`, `funnel_analysis`, `user_flows`, `list_users`, `list_entities`, `get_event_types`, `suggest_property_values` and `retention_analysis`. The ten tools after `get_overview` read the same events as the pages under **Explore** in the app, for the project of the token only. For what they show and what they never show, see [Privacy at a glance](/docs/privacy-overview#analytics).

`get_overview` gives a briefing in one call. It compares the last `days` days with the same number of days before them. It gives:

- the sessions, people, events and page views, now and before, with the change in percent
- the median and average session length, the sessions with only one event, and the new and returning people. A returning person was also active in the days before
- the 8 pages with the most page views, by route template. Their visitors are people after identity resolution, so one person with two ids is one visitor
- setup checks for events, releases, identify, account ids, recordings, DevTools, custom events, judging, rage and dead click events, refused or dropped data (`ingest_refusals`), internal traffic (`internal_traffic`), and from 15 October 2026 your own hosts (`own_hosts`) and ids that look like email addresses (`ids_look_personal`). The state of each check is `ok`, `partial`, `missing` or `off`, or `unknown` when Sequential cannot read the refusal counts in time. The events check can also be `stopped`. See [Refused or dropped data](/docs/troubleshooting) Most checks that are not `ok` tell what to send or turn on next. The account id check names `sequential.account()` and the `account` of Pendo. From 10 October 2026, the events check gives the install line of sequential.js, with a placeholder for the ingest key, and the custom events check gives an example `sequential.capture` call. From 10 October 2026, a `missing` check for events, releases, identify, account ids, custom events, or rage and dead clicks also says one of these: the day that the last such event arrived, in the 90 days before the window; that the data Sequential holds has none; or that older data was not checked. So "none in this window" does not mean "never"
- from 15 October 2026, the events check is `stopped` when no event arrived for 24 hours, and the same 24 hours one week earlier had 20 or more events. It is never `stopped` for a project younger than 8 days. Its fix says to check that the tag still loads and uses this project's ingest key, and to read `ingest_refusals`. `traffic.newest_event_at` is the time that the newest event arrived
- from 15 October 2026, `ids_look_personal` counts how many user ids and account ids in the window look like email addresses. It never shows one. It is `partial` when some do, with the fix: send a pseudonymous id, and the email as a person property. It is `ok` when none do, and `unknown` when Sequential could not count them
- from 15 October 2026, `own_hosts` says whether the people filter hides your own site's host in agent answers, for example as `www.[person].com`. It checks the 3 most-viewed hosts of the window. It is `ok` when your **Allowed websites** keep them readable, and `missing` when some are hidden. It gives counts only, never a host
- with `sessions:explore`: the 3 error groups that the most sessions hit, and the sessions worth watching. From 10 October 2026, `watch` gives `judged`, the number of judged sessions, and `flagged_total`, the judged sessions with at least one signal on. `top` lists up to 3 flagged sessions with the most attention. Each has its person (`user_id`, and `anonymous_id` when it differs) and `last_page`, the page that the session ended on. If no session is flagged, `top` is empty. The two counts read at most the latest 10,000 sessions of the window, so with more sessions they are lower bounds. If Sequential cannot read the judgments, the two counts are `null`, not 0
- with `findings:read`: up to 3 open findings

If the token does not have the scope of a section, the section comes as `{"withheld": "needs sessions:explore"}` or `{"withheld": "needs findings:read"}`, and Sequential does not read the data of that section.

**Your team (internal traffic).** From 10 October 2026, a project can mark its own team as internal, in `data.internal` of its settings document. The app has no control for it yet: an owner or admin sets it through the settings API, with PATCH `/api/projects/:id/config`.

- `user_ids`: up to 200 user ids, as your project sends them. An anonymous id that later identified counts as the same person.
- `email_domains`: up to 20 domains, such as `mycompany.com`. The match is exact and ignores case, so a sub-domain is its own entry. A person matches when the email of their latest identify event has the domain.
- `sequential_members: true`: a person matches when the email of their latest identify event is the Sequential account email of a member of your organisation.

The tools `search_events`, `get_histogram`, `get_breakdown`, `funnel_analysis`, `user_flows`, `retention_analysis`, `list_users`, `list_entities`, `list_sessions`, `list_watch`, `list_errors`, `get_struggle_by_segment` and `get_overview` include the team by default. Each answer has `internal`, with counts only:

- `{ "configured": true, "excluded", "people", "sessions", "events" }`: the share of the team in the answer. `capped: true` means that Sequential uses only the first 2,000 internal people, so the counts are a lower bound.
- `{ "configured": false }`: nobody is marked, so `exclude_internal` changes nothing. From 11 October 2026, the tool tells the agent that Sequential then cannot tell which ids are your team, and that it must not call an id yours.
- `{ "unknown": true }`: Sequential cannot read the setting now. Then `exclude_internal: true` gets a tool error: "Sequential could not read which people are marked internal right now. Try again shortly, or call without exclude_internal."

With `exclude_internal: true`, the tool leaves the team out. An event with no user id is never internal, so it stays in. `list_watch` and `list_sessions` count `internal` before `belief_filters`, `judged_only` and `limit`. Sequential reads the team again at most every 5 minutes. Findings, judging and the pages of the app do not use the setting. `get_overview` also has the setup check `internal_traffic`: it is `missing` when one person who is not marked internal made more than half of the events in the window.

**Counts only.** No agent tool adds up, averages or takes percentiles of the values of an event property, for example a duration or an order value that you send as a property.

**Where the data is complete.** A window can start before the data that Sequential holds. Sequential deletes each event at the end of the retention period that applied when the event arrived, and a new project has no events before its first one. After the organisation's events retention gets shorter, older events stay until their own period ends, so the agent can still see them. From 11 October 2026, each tool that reads a window of days gives `window.data_from` and `window.partial`:

- `data_from` is where the data that Sequential holds is complete in the window. Before it, some rows can be missing and others can still show.
- `partial: true` means that a part of the window is older than that.
- Both are `null` when Sequential could not check.

From 12 October 2026, `list_errors` also gives `window.recordings_from`. In `list_errors`, `data_from` is where its `$exception` events are complete. `recordings_from` is where the errors and failed requests from recordings start. Sequential keeps those only for the replay retention period, so `recordings_from` can be later than `data_from`. A group first seen before `recordings_from` comes from `$exception` events. `null` means that Sequential does not know.

In `get_overview`, the window before (`previous_window`) has the same fields. When Sequential does not hold all of it, it also has a `reason`:

- If Sequential holds none of it, its counts are `null`, never 0.
- If Sequential holds a part of it, its counts stay.
- If Sequential could not check, a count of 0 is `null`, because the 0 can be data that it does not hold. A count above 0 stays.
- `change_pct`, `new_people` and `returning_people` are `null` unless Sequential holds all of the window before.

**Empty intervals in `get_histogram`.** `get_histogram` lists each interval of the window (`filled: true`). An interval without events has zeros. From 11 October 2026, an interval before `window.data_from` that has no events has `null`: Sequential did not measure it, or deleted it at the end of the retention period. An interval before `data_from` that has events keeps its counts. Some of its events can be missing. `first_event_at` is the time of the oldest event that Sequential still keeps. It is the oldest event of the project, not of the filter. If the window has more than 200 intervals, if the interval is `month`, or if Sequential cannot read the oldest event within 3 seconds, the answer lists only the intervals with events (`filled: false`).

**People in `get_breakdown`.** From 10 October 2026, a `user_id` field, at either level, groups by the person after identity resolution: the same person that `unique_users` counts. Each person bucket has `anonymous_ids`: how many other ids of that person the window put into it. It is a count, never the ids. Every bucket also has `unique_sessions`. The **Events** page in the app still groups by the id that each event was stored under.

**Times, totals and identified people in `get_breakdown`.** From 10 October 2026:

- Each bucket has `first_seen` and `last_seen`: its oldest and newest matching event in the window, in UTC. So the newest value of a property, such as a release, is the bucket with the latest `first_seen`. When `truncated` is true, a newer value can be missing.
- The answer has `total`: the events, people and sessions over all buckets, before the limit of 100 buckets. A person in two buckets counts in both. So use `total`, not a sum of the buckets.
- A person bucket has `identified`: true when an identify call linked an anonymous id to that person, false when none did, `null` when Sequential cannot check. `false` does not mean anonymous: an id that your project sent without Sequential's identify is also `false`.

**The event catalog.** From 10 October 2026, `get_event_types` gives the event types over all the events that Sequential holds. It also gives the custom event names of the last `days` days (1–30, default 30): at most 10 names, the most events first. Each name has its events, its sessions, and its first and last event in the window. It has up to 8 property names, each with its kind (`string`, `number`, `boolean` or `datetime`), how many events carry it, and that share in percent (`fill_pct`). The catalog does not list property values: for those, use `get_breakdown` by `event_prop:<key>`. A property marked `restricted` is an element-text or identity property. See [Privacy at a glance](/docs/privacy-overview#analytics).

**New people and accounts.** From 10 October 2026, each row of `list_users` and `list_entities` has `first_seen_at`: the first event in the window, not before it. `sort: "first_seen_at"` lists the newest first. `first_seen_within_days: N` keeps only the rows whose `first_seen_at` is in the last N days of the window. Both work on the rows that the list found, so at most on the 10,000 most recently active.

**Ids in `retention_analysis`.** From 10 October 2026, `include_ids: true` adds the ids of each cohort's members and of the members who came back. The whole answer gives at most 50 of each, from the earliest cohort on. So a later cohort's list can be short or empty, with its `truncated` flag true. `include_ids` needs the scope `sessions:explore` too. Without it, Sequential refuses the call. Each id is the person after identity resolution. On a large project, the call can stop at its time limit. Then call again without `include_ids`.

**The `page` field.** An agent can use `page` in a filter, and as `field` or `second_field` of `get_breakdown`. `page` is the route template of the page address. Sequential removes the scheme, the host, the query, the fragment and a slash at the end. It shows numbers, UUIDs and long hex ids as `:id`. So `/replay?session_id=…` and `/replay` are one page, and `/users/123/orders/456` is `/users/:id/orders/:id`. A mobile screen name stays as it was sent. The menus in the app do not offer `page`.

| Limit | Value | Result |
|---|---|---|
| Time window (`days`) | The last 1–30 days. Default 7 | Another value: a tool error |
| Older events | Only the events that Sequential still keeps. On Sequential's hosted service, events stay 7 to 14 days, unless Sequential support exempts your organisation. See [A server-wide limit](/docs/retention-and-deletion#a-server-wide-limit) | Older days count as empty |
| Events in `search_events` (`hits_limit`) | 1–50. Default 20 | Another value: a tool error |
| Buckets in `get_breakdown` | 100 | `truncated` is true |
| Steps in `funnel_analysis` | 2–10 | Another number: a tool error |
| Steps in `user_flows` | 1–10 | Another number: a tool error |
| Paths in `user_flows` | 100 | `paths_total` counts all paths |
| Ids in each drop-off list and in the completed list of `funnel_analysis` | 100 | The `_total` fields count all ids |
| Rows in `list_users` and `list_entities` (`limit`) | 1–100. Default 50 | `truncated` is true when rows were left out |
| Values in `suggest_property_values` | 100 | `truncated` is true |
| `retention_days` in `retention_analysis` | 1–10 different whole numbers, each 1–365 | Another value: a tool error |
| Agent tool calls that run at the same time | 4 for each project, and 16 for each server process. Server defaults | A wait of up to 3 seconds, then a tool error. See below |

- **Identity fields are refused.** A filter, a funnel or flow step, a retention event, a breakdown or a `suggest_property_values` call that names a person's or account's identity gets the tool error "Agents can't filter or break down by a person's or account's name, email or other identity fields." For the fields, see [Privacy at a glance](/docs/privacy-overview#analytics).
- **Too many calls at once.** The cap counts every agent tool call, not only the analytics tools. A call over the cap waits for a free slot for up to 3 seconds. At most 8 calls wait on each server process. When no slot comes free in time, or 8 calls already wait, Sequential refuses the call, before any read. If the client goes away while its call waits, the call runs no read. Through MCP, the answer is a tool error. POST `/api/agent/<tool>` answers 400 `tool_error`. The message is "Sequential is busy answering this project's other questions; try again in a few seconds." when 4 calls of the project are running, and "Sequential is busy answering other questions on this server; try again in a few seconds." when 16 calls are running on the server. The answer has no Retry-After header. Try again after a few seconds.
- The operator changes the caps with `AGENT_READ_MAX_CONCURRENT_PER_PROJECT` and `AGENT_READ_MAX_CONCURRENT`, and the wait with `AGENT_READ_QUEUE_MS` and `AGENT_READ_QUEUE_MAX`. Each server process counts only its own calls.
- **Properties.** The filters of the analytics tools take the property conditions of the app, with the same limits. See [Property conditions](/docs/filters-and-saved-views#property-conditions). `get_breakdown` can also group by a property: `event_prop:<name>`, `visitor_prop:<name>` or `account_prop:<name>`, for `field` or `second_field`. Events without the property get their own bucket, with a `null` key and `unset: true`. `event_prop:$utm_source` and the other `$utm_*` tags group by the campaign tags of the page address. `suggest_property_values` also lists event properties, such as `plan`. An identity property is refused, as above. An element-text property, such as `$el_text`, and PostHog's `$set`, take only **is set** and **is not set**, and breakdowns and suggestions refuse them. A filter on `selector` takes only `exists` or an exact structure.
- Each analytics call also counts toward the token limits above.

### Token errors

| Case | Status | Response |
|---|---|---|
| The token is unknown, revoked or expired | 401 | `invalid_token`: "The access token is unknown, revoked or expired" |
| A claude.ai connection calls while its project is archived | 401 | `grant_paused`: "This connection is paused while its project is archived" |
| A request to `/mcp` or `/api/agent/<tool>` has no bearer token | 401 | `unauthenticated`: "Send Authorization: Bearer <project access token>" |
| The token lacks the scope | 403 | `insufficient_scope`: "This token lacks the <scope> scope" |
| A REST route request names another project's `tenant_id` | 404 | `not_found` |
| A tool call on `/mcp` or `/api/agent/<tool>` has a `tenant_id` argument | — | A tool error: "Unknown argument: tenant_id (the token's project is used)" |
| Over the token rate limit | 429 | `rate_limited`, with a Retry-After header |
| Over the project read limit, only when the operator turned it on | 429 | `project_rate_limited`, with a Retry-After header |
| The store that counts token requests is unavailable | 503 | `rate_limit_unavailable`, with `Retry-After: 30` |
| Sequential cannot look up the token, its project or its connection | 503 | `auth_unavailable`, with `Retry-After: 30` |
| A token asks for a fix brief or a finding that Sequential could not fully screen | 503 | `screen_unavailable`, with `Retry-After: 60`. POST `/api/agent/<tool>` answers 400 `tool_error`. MCP answers a tool error |
| GET or DELETE on `/mcp` | 405 | "This MCP endpoint is stateless: POST JSON-RPC." |
| An MCP tool that the token cannot use | — | "Tool not available for this token" |
| POST `/api/agent/<tool>` names a tool that does not exist | 404 | `unknown_tool` |
| The body of POST `/api/agent/<tool>` is not a JSON object | 400 | `invalid_body`: "Send the tool's arguments as a JSON object" |
| The tool refuses the request, for example because of a wrong argument | 400 | `tool_error`, with the tool's message |
| An agent tool call starts while 4 calls of the project, or 16 calls on the server, are running | 400 | `tool_error`: "Sequential is busy answering this project's other questions; try again in a few seconds." or "Sequential is busy answering other questions on this server; try again in a few seconds." MCP answers a tool error with the same text. See [Analytics from an agent](#analytics-from-an-agent) |
| `ask_sessions` refuses or fails a call: a limit, a description Ask cannot use, judging not set up, or every judgement failed | 400, 402, 429, 502 or 503 | Its own error, for example `budget_exhausted` or `bad_query`. MCP gives the same JSON as a tool error. See [Troubleshooting](/docs/troubleshooting) |
| The tool fails | 500 | `internal_error` |

- The 401 responses carry a `WWW-Authenticate: Bearer` header. The 403 response names the missing scope in that header.
- Sequential refuses batched JSON-RPC requests on `/mcp`.
- A token request spends the rate limit before Sequential checks the project and the scope. This applies to REST and MCP.
- By default, a token does not get a fix brief or a finding that Sequential could not fully screen. An operator can turn this off with `FINDINGS_SCREEN_REQUIRED=false`. See [Privacy at a glance](/docs/privacy-overview).

### The project read limit for tokens

Sequential counts the read requests of all tokens of a project together. The limit is 600 requests a minute per project. Server default. The operator changes it with `TOKEN_PROJECT_REQUESTS_PER_MINUTE`. A value that is 0, empty or not valid gives the default.

- **By default, Sequential only counts.** It never refuses a request because of this limit.
- **The operator can turn the limit on** with `TOKEN_PROJECT_LIMIT_ENFORCE=true`. Any other value, or no value, keeps the default.
- When the limit is on and a project goes over it, Sequential answers 429 `project_rate_limited`: "Too many requests for this project's access tokens and connections. Try again shortly." The answer has a Retry-After header and `retry_after_sec`.
- When the limit is on and the store that counts it is unavailable, Sequential answers 503 `rate_limit_unavailable`, with `Retry-After: 30`.
- Through MCP, a refused tool call is a tool error, and its text is the same JSON. POST `/api/agent/<tool>` answers with the same status, body and Retry-After.

What counts:

- A token's GET `/api/findings`, `/api/findings/:n`, `/api/findings/:n/sessions`, `/api/findings/:n/brief` and `/api/findings/:n/verification`. Each request counts once. A request that gets 403 or 404 does not count.
- Each call of a tool that only reads, through `/mcp`, `/mcp/readonly` or POST `/api/agent/<tool>`. `ask_sessions` counts too.
- Write requests never count: `record_release`, `link_fix`, POST `/api/releases` and POST `/api/findings/:n/links`.

The limit of 120 requests a minute for each token still applies. A request that one of the two limits refuses does not use up the other limit: if the limit for each token refuses it, Sequential gives back its count on the project limit, and if the project limit is on and refuses it, Sequential gives back its count on the token limit (Sequential tries this once, so a count can stay one too high until the minute ends).

**Operator note:** when the project limit is on and refuses a tool call through `/mcp`, `/mcp/readonly` or POST `/api/agent/<tool>`, the call still counts toward the limit of 120 requests a minute for that token.

### How tokens work with sessions, expiry and revocation

- Sequential stores only a hash of each token. It shows the full token once, when you create it.
- If a request has a bearer token and a session cookie, Sequential uses the token. A bad token does not fall back to the cookie.
- Expiry choices in the app: **30 days**, **90 days** or **365 days**. **90 days** is selected by default.
- Revoking a token stops it on that server at once. Sequential tells its other servers through Redis. If Redis is down, another server can accept a revoked token for up to 30 seconds.
- A token stops working when its project is archived.
- On the **Access tokens** tab, the token list can show "It identified itself as" and a name. The agent's MCP client sends this name when it connects. Sequential does not check it, and keeps at most 60 characters.
- Operators change the token rate limit with `TOKEN_REQUESTS_PER_MINUTE`.
- The token list, GET `/api/projects/:id/tokens`, gives each token a `status`. It is `live`, `expired`, `revoked` or `paused:project_archived`. `paused:project_archived` means that the project is archived, so the token does not work. On the **Access tokens** tab, a token that is not `live` is dimmed and has a badge: **Revoked** or **Expired** with the date, or **Paused: project archived**. On **Agents**, the **Coding agents** card shows a paused token with "Paused: project archived" in place of "Used". A revoked or expired token moves to **History**, as "Revoked" or "Expired" and the day. Only a `live` token shows its expiry date. **Revoke** stays on a paused token. In the API, each row also has `kind`, which is `pat` for the tokens that you create. `last4` can be null, but never for a token that you create.
- A claude.ai connection is in the same list, with `kind` `oauth` and no `last4`. Its `status` can also be `pending`, `refresh_idle`, `client_missing` or `access_lost:` and a reason. The app shows these as **Connecting**, **Idle**, **Client gone** and **Access lost**. A connection that claude.ai never finished shows **Never finished connecting**, not **Expired** and a date. A connection on an archived project is paused, and it works again when you restore the project. See [Connect claude.ai](/docs/connect-claude-ai#see-the-connection-under-agents).

## Values that are not enforced

Some values look like limits, but Sequential does not apply them today.

> **Do not rely on these values**
>
> - **Concurrent** on the **Session replay** tab, shown in the summary as "up to 50 at once", does not limit how many sessions record at once.
> - The session budget in **What SDKs receive** (`session_budget` and `on_budget_exceeded`) has no control in the app. Sequential never counts or applies it. There are no per-organisation plan limits either.
> - `events_retention_days` in the same block is applied. It is the organisation's events retention period: one of 7, 30, 90, 180 or 365 days. The default is 365. If the server sets a shorter limit, the block shows the limit, and the limit applies. See [A server-wide limit](/docs/retention-and-deletion#a-server-wide-limit). Sequential keeps each event for at least that period and up to about a week longer. Only Sequential support can change it, for all the projects of the organisation. A shorter period deletes nothing. Through the settings API, a change of `events_retention_days` gets 409 `retention_set_by_organisation` and saves nothing. See [Retention and deletion](/docs/retention-and-deletion).

To control how much you record, use **Sampling**, **Max minutes** and **Max MB**. See [Recording settings](/docs/recording-settings).

## Related

- [Recording settings](/docs/recording-settings)
- [Check your install](/docs/verify)
- [DevTools in replays](/docs/devtools)
- [Judgments](/docs/judgments)
- [Session insights](/docs/session-insights)
- [Ask: find sessions by describing them](/docs/ask)
- [Two-factor authentication and account security](/docs/two-factor-and-security)
- [Retention and deletion](/docs/retention-and-deletion)
- [Troubleshooting](/docs/troubleshooting)
