> ## Documentation Index
> Fetch the complete documentation index at: https://docs.signalmd.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Limits and quotas

> Plan credits, API rate limits, the plan limit error, import size, copilot limits and when a version comparison can give a verdict.

SignalMD has two kinds of limit. Plan credits follow your plan and count volume. Rate limits and sizes protect the service and are the same on every plan. This page lists both and what you see when you reach one. [Pricing](/billing/pricing) has the counting rules and the worked example.

## Plan credits

| | Free | Starter | Growth | Scale | Enterprise |
| - | - | - | - | - | - |
| Price per month, billed monthly | \$0 | \$49 | \$179 | \$499 | From \$1,500 |
| Price per month, billed yearly | \$0 | \$39 | \$149 | \$425 | Custom |
| Charged once a year | \$0 | \$468 | \$1,788 | \$5,100 | Custom |
| Credits a month | None | 6,000 | 20,000 | 55,000 | Set by contract |
| One-minute calls observed | None | 6,000 | 20,000 | 55,000 | Set by contract |
| Or about this many simulated tests | None | 1,000 | 3,300 | 9,200 | Set by contract |
| Or about this many copilot answers | None | 300 | 1,000 | 2,800 | Set by contract |
| Agents | 1 | 3 | 10 | 25 | Unlimited |
| Seats | 2 | 3 | 10 | 20 | Unlimited |
| Signed DPA | No | Yes | Yes | Yes | Yes |

Every plan includes the board, flow, traces, versions, the REST API and the MCP server. Growth and Scale also include Slack support. Credits pay for processed calls, simulated and phone tests, and the copilot. The calls, tests and answers rows are each what the whole month's credits buy if they are spent on that one thing alone, counting every call as one minute. Longer calls use more, and a month that mixes them gets a share of each. They reset each month and do not carry over. Prices are in US dollars. Agents and seats are totals. Paid plans cost less per month when billed yearly, and the yearly bill is charged once.

| Allowance | What counts | At the limit |
| - | - | - |
| Credits | One monthly balance. Each processed minute of call audio uses 1 credit, and again when a call is analysed again. Each simulated test uses 6 credits for each test and persona in a run. A phone test uses 6 credits a minute, and at least 6. A copilot answer uses about 20. Quick checks and the brief's Calibrate chat draw on the same balance | Calls keep importing and wait unanalysed, with no error. Tests and the copilot pause. Calls analysed again are read by rules alone. A run the balance does not cover is refused whole with a 402 |
| Agents | Agents in the workspace now, not a monthly count. The demo agent is excluded | Connecting another is refused with a 402 |
| Seats | People in your organization | Set by your plan. SignalMD does not count or remove members |

A paid workspace's credits reset at the start of each billing period, every month, annual plans included. Unused credits do not carry over. Free has no credits. **Plan and usage** under **Settings** shows the balance against its limit.

## Plan limit errors

A request that the credits do not cover is refused with HTTP 402 and the code `quota_exceeded`. The API and the MCP server return the same fields as the app, in the API's error object. `error.quota` says which limit, how much is used and which plan.

```json 402 from POST /v1/agents/{agentId}/runs theme={null}
{
  "error": {
    "type": "budget_error",
    "code": "quota_exceeded",
    "message": "This needs 72 credits and Starter has 40 of 6,000 left this month. Run fewer tests or upgrade.",
    "param": null,
    "requestId": "req_3f9a1c07d2b84e6a5c1d9b30",
    "quota": {
      "metric": "credits",
      "activity": "testing",
      "requested": 72,
      "limit": 6000,
      "used": 5960,
      "plan": "starter",
      "upgradePath": "/billing"
    }
  }
}
```

An MCP tool returns the same object as a tool error, with the status beside it:

```json Tool error from start_run theme={null}
{
  "status": 402,
  "error": {
    "type": "budget_error",
    "code": "quota_exceeded",
    "message": "This needs 72 credits and Starter has 40 of 6,000 left this month. Run fewer tests or upgrade.",
    "param": null,
    "requestId": "req_3f9a1c07d2b84e6a5c1d9b30",
    "quota": { "metric": "credits", "activity": "testing", "requested": 72, "limit": 6000, "used": 5960, "plan": "starter", "upgradePath": "/billing" }
  }
}
```

| Field | Meaning |
| - | - |
| `quota.metric` | The allowance that ran out: `credits` for a run or the copilot, or `agents` for connecting an agent |
| `quota.activity` | With `credits`: what the request would have spent them on: `observation`, `testing` or `chat` |
| `quota.requested` | With `credits`: the credits the request needed to start |
| `quota.limit` | What the plan includes for that metric |
| `quota.used` | What the workspace has used in the period (agents: the number connected) |
| `quota.plan` | The plan: `free_org`, `starter`, `growth`, `scale` or `enterprise` |
| `quota.upgradePath` | The app page to change plan: `/billing`, which is **Plan and usage**, under the app address |

Through the API and the MCP server, the limit you can reach is a run the credits do not cover. Starting a run, or calibrating from a signed-in session, draws on credits. The copilot, the brief chat and connecting agents exist in the app only, and calls past your credits wait instead of failing. In the app, the same refusal shows as a notice with **See plans**. On Enterprise the message ends "Contact us to raise the limit."

Do not retry a 402 `quota_exceeded` as it is. Nothing changes until the month resets, you upgrade, or you start a run that needs fewer credits.

Two other 402 codes are budgets and settings, not the plan:

* `budget_exceeded`: your key's monthly budget or the agent's test budget did not cover the request.
* `testing_not_configured`: testing is not set up for the agent.

## API rate limits

Rate limits count requests in token buckets. A bucket holds the burst size and refills steadily at the rate, so after a quiet spell you can send a burst, then the sustained rate.

| Limit | Applies to | Rate a minute | Burst |
| - | - | - | - |
| All requests | Each API key, or each signed-in person | 600 | 120 |
| Writes (a write route also draws from the all-requests bucket) | Each API key, or each signed-in person | 60 | 20 |
| Workspace | Every key, person and MCP call together, shared with the app | 600 | 600 |
| AI-backed routes (brief chat, test generation, persona drafts, rescore) | The workspace | 10 | 10 |
| MCP endpoint | Each client address | 600 | 120 |
| Failed authentication | Each client address, across the app, the API and MCP | 30 | 30 |

Every `/v1` response carries the tighter of the key's buckets:

| Header | Meaning |
| - | - |
| `RateLimit-Limit` | The bucket size |
| `RateLimit-Remaining` | Requests left in the bucket |
| `RateLimit-Reset` | Seconds until the bucket is full again |
| `Retry-After` | On a 429 only: seconds to wait before the next request |
| `Request-Id` | The id of this request, also in `error.requestId`. Quote it when you ask for help |

A refused request returns HTTP 429 with the code `rate_limited`. A client address that has failed authentication too often gets `too_many_failed_authentications` instead, with or without a valid key, until its failures age out.

```json 429 theme={null}
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limited",
    "message": "Too many requests. Retry after 1 second(s).",
    "param": null,
    "requestId": "req_b41e7c90a2d85f3617e0c9a4"
  }
}
```

Wait for `Retry-After`, then retry. Treat the numbers as a guide to sustained use, not a guarantee.

Calibrating tests needs a signed-in session. Every API key is refused with 403 and the code `people_only`.

## Import limits

These are the limits on the hosted service. They bound how much one import brings in. They are not the plan credits.

| Limit | Value |
| - | - |
| How far back an import reaches | 30 days |
| Calls in one import | 1,000 |
| First import, on connecting the agent | The latest 500 calls from the last 30 days |

After that, new calls arrive on their own, within minutes of ending, and are not held to the import size. You can keep only a percent of them, or cap them per day, week or month, in **Import settings** on **Agent config**. How many are analysed depends on the credits left. A call that runs past them is stored and waits. The import status on **Agent config** says how many are waiting, such as "120 analysed, 30 waiting for next month or an upgrade." See [Connect Retell](/guides/connect-retell).

## Copilot limits

| Limit | Value |
| - | - |
| Message length | 8,000 characters |
| Answers at a time | One. **Stop** ends an answer early |

A copilot answer uses about 20 credits, about any agent, the demo included. More lookups or a longer answer use more of them, and each quick check uses credits too. A question that needs too many lookups, a very long call or a very large lookup is cut short, and the copilot answers from what it read. Narrow the question if that happens. See [Copilot overview](/copilot/overview) for what the copilot reads.

## Version comparisons

A comparison needs enough calls on each version before it gives a verdict. With too few, the measure reads **Not enough calls** and no verdict is given, however large the difference looks. Wait for more calls on the new version.

An issue's fix verdict also waits until the live version has taken calls for the agent's grace period, 7 days by default. You can change it with **Resolved after** on the **Issues** page. See [Versions](/concepts/versions).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.