Cancel a dry run or an import
const url = 'https://beta-api.plune.ai/v1/projects/example/integrations/testrail/imports/example/cancel';const options = {method: 'POST', headers: {cookie: 'plune_session=<plune_session>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://beta-api.plune.ai/v1/projects/example/integrations/testrail/imports/example/cancel \ --cookie plune_session=<plune_session>Owner only. Stops the job after the step in hand (the same move as Cancel in the queue panel, with its audit entry). What was imported stays; the next import goes on from what is there. A job that is not running (409) cannot be cancelled. Session cookie only.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters ”An id from GET /v1/projects
The id the start answered with
Responses
Section titled “ Responses ”The job, cancelled
A dry run or an import. Its id is the id of its job in the queue (GET /v1/jobs); this is the part the queue has no place for.
object
paused_rate_limit: TestRail asked Plune to wait (429) for longer than a step takes — the next step goes on after the pause. credentials_rejected: the key was refused, no retry was made; replace the key and press Retry on the job.
Where the cursor { phase, id, offset } is: the lookups (priorities, shared steps), the suites, the sections, the tree in Plune, the cases, with history the runs (the lists) and the results (a page of 250 a step), and for a sync the cases no full pass found (gone).
Every counter, 0 when it did not happen. A dry run’s are what the import after it does, from the same code. cases_seen is what the instance listed; cases_created, cases_updated, cases_unchanged and cases_conflict (changed in TestRail and in Plune since the import: left as they are, listed in conflicts) sum with the cases_skipped_* (bin: the case is in the Bin and stays there; deleted: TestRail marks it deleted; bdd: Plune has no Gherkin steps; ceiling: the project has no room; invalid: Plune refused the case, or its section was not listed) to cases_seen. nodes_created / nodes_existing: the folders and suites of the tree. The rest count what the mapping leaves out or makes up: steps_shared_expanded, steps_shared_missing, cases_placeholder_expected, cases_exploratory, cases_estimate (the TestRail estimate was read into the case’s estimate: 30s 2m is 2m 30s; written for a new case and, where the case has none, for one that exists) and cases_estimate_not_transferred (text that is not an estimate: left out), cases_type_not_transferred, cases_custom_fields_not_transferred (cases with a value in a field that was not chosen or cannot be carried), priorities_unknown; an import that chose fields adds cases_custom_values (values that came across), cases_custom_values_skipped (a value the Plune field cannot hold: an option it does not have, a date in a local spelling) and custom_fields_refused (a chosen field that could not be made or mapped: it is left out, the warnings say why), and counts fields_created / fields_existing for the fields it set up; cases_refs is how many carried refs (kept in a custom field); cases_same_title is how many repeat the title of an earlier case of the same TestRail section (the same folder): they are imported all, never merged. A sync adds cases_gone (listed in gone), cases_detached (of those, moved to detached), cases_reattached (found again), fields_created and fields_existing; a sync deletes nothing. History (an import that asked for it): runs_listed = runs_beyond_plan + runs_binned (in the Bin: not brought back) + runs_already_imported (finished in Plune) + runs_to_import; runs_imported is how many of those an import has finished (0 in a dry run), runs_finished the closed ones among them. results_estimated and results_untested come from the lists of runs (a dry run reads no results). The import reads results_seen: results_accepted (new), results_duplicate (the key and the content are there), results_conflict (the key is there with other content), results_no_case (the case is not in Plune: not imported, in the Bin), results_skipped_untested, results_skipped_invalid; results_status_unknown (a status the instance did not list: skipped, the id in the raw status), substatuses_added and substatus_overflow (past the ten a status takes: the result stays skipped without one, the word is in the raw status), dates_clamped (times cut to 2004 … now), dates_missing (a run or result came without a time: dated by the import), runs_skipped_invalid (a run listed without an id or a creation time), descriptions_truncated (a run description longer than 200 characters is kept cut to 200), results_elapsed_unparsed (not a time, or longer than 24 days), results_attachments_not_transferred. A run counts the newest result of each case; older ones stay as the case’s history.
object
The cases left alone because both sides changed them — at most 100 of them. A sync also says when each side last changed the case (the case stays as it is in Plune).
object
A sync (or its dry run): what it was asked. null for an import.
object
A sync, or its dry run: the cases it made (created) or rewrote (updated, with the fields of the case the import owns that changed) — at most 100. caseId is absent for a case a dry run would make.
object
What history was asked for, and the dates it reaches back to; null for a sync, and for an import that asked for none. since is the oldest creation date of a run it brings (null: no limit; set once the first step of the runs is done), planDays the days of runs the plan of the account keeps (null: all).
object
The case fields of the instance (#1930): read by get_case_fields (one request) in a dry run, and in an import that was asked for fields; null otherwise, and for a sync. Not the fields the mapping reads itself, the system fields, the inactive, nor those that belong to other TestRail projects. cases is the number of cases with a value in it (an unticked checkbox, a dropdown on “None” and a zero are no value), complete when the cases are read. Every member sees the list; only the owner chooses (customFields of the import).
object
text, dropdown, checkbox, date, integer; or the TestRail type that is not carried: multi-select, user, milestone, steps, scenario.
Not supported: <type> when supported is false.
A dropdown’s options.
An import: what it was asked; pluneFieldId is the Plune field it used (null until the lookups made it).
object
A sync: the cases a full pass of the TestRail project did not find — at most 100. Nothing is deleted. detached: the case was moved to the detached state (only an active case may be; a draft stays a draft and is only listed).
object
At most 20 sentences about what the instance did not list or could not give.
When the job first reached each phase (the keys are those of phase): lookups is startedAt, done is finishedAt, a phase the job skipped is absent. A phase lasts until the next stamp. Jobs started before this field have only lookups and the stamps of the steps after it.
object
The job in the queue: its state, how many cases it has seen of how many it knows of so far (null until the cases begin), and why it stopped.
object
object
Example
{ "id": "b1f0c6e2-6c1e-4b0e-9a49-3f6f1c1a9d11", "dryRun": true, "status": "cancelled", "trProjectId": 1, "trProjectName": "Project Alpha", "phase": "done", "counters": { "cases_seen": 4, "cases_created": 3, "cases_updated": 0, "cases_unchanged": 0, "cases_conflict": 0, "cases_skipped_bin": 0, "cases_skipped_deleted": 1, "cases_skipped_bdd": 0, "cases_skipped_ceiling": 0, "cases_skipped_invalid": 0, "nodes_created": 6, "nodes_existing": 0, "steps_shared_expanded": 1, "steps_shared_missing": 0, "cases_placeholder_expected": 0, "cases_exploratory": 1, "cases_estimate": 1, "cases_estimate_not_transferred": 0, "cases_refs": 1, "cases_same_title": 0, "cases_type_not_transferred": 3, "cases_custom_fields_not_transferred": 0, "priorities_unknown": 0, "cases_gone": 0, "cases_detached": 0, "cases_reattached": 0, "fields_created": 0, "fields_existing": 0, "cases_custom_values": 0, "cases_custom_values_skipped": 0, "custom_fields_refused": 0, "runs_listed": 0, "runs_beyond_plan": 0, "runs_binned": 0, "runs_already_imported": 0, "runs_to_import": 0, "runs_imported": 0, "runs_finished": 0, "results_estimated": 0, "results_untested": 0, "results_seen": 0, "results_accepted": 0, "results_duplicate": 0, "results_conflict": 0, "results_no_case": 0, "results_skipped_untested": 0, "results_skipped_invalid": 0, "results_status_unknown": 0, "substatuses_added": 0, "substatus_overflow": 0, "dates_clamped": 0, "results_elapsed_unparsed": 0, "results_attachments_not_transferred": 0, "runs_skipped_invalid": 0, "dates_missing": 0, "descriptions_truncated": 0 }, "conflicts": [], "warnings": [], "sync": null, "changes": [], "gone": [], "history": null, "fields": [ { "systemName": "custom_ai_type", "label": "AI Type", "type": "dropdown", "supported": true, "reason": null, "cases": 2, "options": [ "RAG", "ML", "LLM" ], "choice": null }, { "systemName": "custom_case_is_automated", "label": "Is Automated", "type": "checkbox", "supported": true, "reason": null, "cases": 1, "options": [], "choice": null }, { "systemName": "custom_platforms", "label": "Platforms", "type": "multi-select", "supported": false, "reason": "Not supported: multi-select", "cases": 1, "options": [], "choice": null } ], "phaseAt": { "lookups": "2026-09-16T09:12:04.151Z", "suites": "2026-09-16T09:12:04.151Z", "sections": "2026-09-16T09:12:04.151Z", "nodes": "2026-09-16T09:12:04.151Z", "cases": "2026-09-16T09:12:04.151Z", "done": "2026-09-16T09:12:04.151Z" }, "startedAt": "2026-09-16T09:12:04.151Z", "finishedAt": "2026-09-16T09:12:04.151Z", "job": { "state": "cancelled", "progress": null, "reason": "Cancelled by Shop Owner" }}No / invalid session — a CLI token is refused here
You are in the project, but not as its owner
object
Example
{ "error": "project owner only"}No such project among yours, or no such import in it
object
Example
{ "error": "import not found"}The job is not running any more
object
Example
{ "error": "the import is not running any more"}Rate-limited: the per-route throttle, or the per-minute request limit of the plan an API token counts by (#1442; the body names the plan, #2092). Retry-After carries the seconds until the window rolls over.
object
Example generated
{ "error": "example"}Headers
Section titled “Headers ”Seconds until the window rolls over
The server has no key to keep TestRail keys under
object
Example
{ "error": "the TestRail bridge is not configured on this server - contact your operator"}