A practical guide to API improvements from TestRail 10.4 through 10.9
TestRail now offers more ways to batch operations, retrieve only relevant data, and avoid extra lookups. This guide shows which capabilities to adopt and how they can reduce requests in your automation, helping avoid 429 (Too Many Requests/API Rate Limit reached) responses that interrupt your workflows.
Your existing integrations need to use these capabilities to benefit. Review them as CI workloads grow and before adding AI tools through the Model Context Protocol (MCP). All integrations share your instance’s API limit: 180 requests per minute on Cloud Professional and 300 on Cloud Enterprise.
Batch writes and reuse existing runs
| From | API improvement | How it reduces requests |
|---|---|---|
| 10.4 | add_cases | Create up to 500 cases per request, grouped by section. For 1,000 cases in one section, replace 1,000 creation calls with 2. |
| 10.5 | Bulk label operations | Batch label creation and updates instead of maintaining each label individually. Valid labels are saved and failed entries are reported by index, so retry only the failures. Label names are limited to 20 characters. |
| 10.8 | update_results | Edit multiple existing results in one request. The batch is applied atomically: if any item is invalid or fails, none of the edits are saved, so correct the failing item and resubmit the batch. |
| 10.9 | rerun_plan and rerun_run | Recreate a plan or run with one request instead of retrieving and reconstructing its structure. Optionally copy assignees. |
| 10.9 | add_cases_to_run | Append cases without fetching and resubmitting the existing selection. Duplicate IDs are ignored; the updated run is returned. Not available for completed runs or for runs that belong to a plan, and has no effect on runs that already include all cases. |
Remove follow up lookups
| From | Response or endpoint | What you can stop fetching |
|---|---|---|
| 10.4 | case_id in get_results_for_run | Avoid fetching tests solely to map execution results to test cases. |
| 10.5 | case_title in get_results_for_run | Avoid case lookups used only to display titles. get_tests returns case_id and the test title in title, so no separate case lookup is needed there. |
| 10.5 | get_case_titles | Resolve up to 500 case IDs to titles in one lightweight request. |
| 10.5 | plan_id in get_runs | Determine plan membership directly from run-list responses. |
Learn more Cases API Results API Runs API Release notes
Retrieve only the data you need
Filters and incremental synchronization can reduce the number of pages your integration retrieves. Bulk reads still paginate; combine requests where possible and follow the response’s next-page link.
| From | API improvement | Recommended use |
|---|---|---|
| 10.4 | Dynamic run and plan filters | Send selection criteria when creating or updating supported runs and plans, rather than downloading cases and assembling case IDs locally. |
| 10.4 | refs on get_runs and get_plans | Retrieve runs or plans linked to a requirement instead of scanning all records. |
| 10.5 | label_id and refs on get_cases | Filter cases to the labels or requirement relevant to your workflow. Single-value refs filtering predates this release. |
| 10.5 | get_bdds | Retrieve Gherkin content for multiple cases instead of making one get_bdd request per case. Apply suite, section, label or reference filters. |
| 10.7 | refs[] on get_cases and get_bdds | Query up to 500 reference IDs together instead of making one request per issue, using either an array (refs[]=ENG-101&refs[]=ENG-102) or a comma-separated string (refs=ENG-101,ENG-102). This is a read filter, not a new format for writing references. |
| 10.8 | Expanded server-side filters | Use supported status, priority, section, assignee, label, creator, updater and milestone filters to narrow results before retrieval. |
| 10.8 | Expanded updated_after support | Synchronize changed records on supported case, result and BDD endpoints instead of repeatedly retrieving complete datasets. |
| 10.9 | updated_after for runs, plans and milestones | Retrieve only changed entities. Result activity also advances the associated run timestamp, helping identify execution data to refresh. |
| 10.9 | get_test_states_for_run | Retrieve the latest result for each test when you need current execution state, rather than complete result history. |
| 10.9 | get_cases_count and get_bdds_count | Retrieve filtered counts without downloading every page. Skip a separate count call when you will retrieve the full dataset anyway. |
Combine reference queries
For example, query three issue keys together with get_cases instead of sending three separate reference queries (a comma-separated refs=ENG-101,ENG-102,ENG-103 is equivalent):
index.php?/api/v2/get_cases/42&refs[]=ENG-101&refs[]=ENG-102&refs[]=ENG-103Persist a synchronization timestamp only after successfully processing all pages. Check endpoint-specific filter support and version requirements before changing a production integration.
Learn more Cases API Runs API Dynamic filter fields
Improve how your integrations use the API
The following capabilities support efficient integrations. Some reduce payload size or simplify setup rather than directly reducing the number of requests.
| From | Supporting improvement | How to use it |
|---|---|---|
| 10.4 | Partial edits with edit_result | Update known result fields directly where a preparatory read is unnecessary. |
| 10.6 | System fields in get_case_fields and get_result_fields | Use the richer field definitions for introspection. Cache metadata rather than fetching it for every record. |
| 10.6 | get_version | Detect available capabilities and cache the version for the integration session. |
| 10.8 | fields= selection | Return only the fields you need. This reduces payload size and processing; it does not itself reduce request count. |
| 10.8 | API Management Dashboard | Review per-credential call counts to identify high-volume integrations and prioritize optimization. |
Guidelines for your automation
- Batch writes. Group case creation, result edits and supported label operations. Follow each endpoint’s batch limits and retry only failed items where partial success is supported.
- Reduce repeated reads. Use IDs and titles already present in responses. Cache reusable configuration and metadata, and request current states or counts when full records are unnecessary.
- Filter and synchronize changes. Replace full-library scans with targeted queries and updated_after where supported. Combine references with refs[] and retain pagination handling.
- Coordinate traffic. Pace requests across CI jobs, synchronization services and MCP integrations. Stagger scheduled jobs so they do not all consume the shared instance limit at once.
- Handle 429 responses. When a request exceeds the limit, TestRail returns HTTP 429 with a Retry-After header containing the number of seconds to wait. Your client must wait before retrying. Immediate retries add traffic; correct waiting helps prevent repeated throttling.
- Measure adoption. Compare requests per workflow, peak request volume and 429 frequency before and after changes. Start with the integrations that generate the most calls.
Documentation API limits and pagination Results API Release notes