Connect a TestRail, or replace its API key
const url = 'https://beta-api.plune.ai/v1/projects/example/integrations/testrail';const options = { method: 'PUT', headers: { cookie: 'plune_session=<plune_session>', 'Content-Type': 'application/json' }, body: '{"baseUrl":"https://tr.example.com","email":"[email protected]","apiKey":"example-not-a-real-testrail-key-0123456789"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url https://beta-api.plune.ai/v1/projects/example/integrations/testrail \ --header 'Content-Type: application/json' \ --cookie plune_session=<plune_session> \ --data '{ "baseUrl": "https://tr.example.com", "email": "[email protected]", "apiKey": "example-not-a-real-testrail-key-0123456789" }'Owner only. Saves the address, the e-mail and the API key: the key encrypted with the server’s key for TestRail, bound to this project, never returned. Nothing is sent to TestRail here — the address is only checked (https, a public address) — so the answer has status: untested until POST …/test or an import finds the key works. A save over an existing connection replaces the ciphertext in place. Recorded in the audit feed of the project as a testrail_connection entry: the key masked, the e-mail left out. Session cookie only.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters ”An id from GET /v1/projects
Request Body required
Section titled “Request Body required ”A TestRail instance and the user whose API key Plune reads it with. A field this API does not know is refused, and no refusal quotes a value.
object
The address of the instance: https://<name>.testrail.io, or a TestRail Server’s own, with its sub-folder if it has one. Kept without a trailing / and without index.php…. Only https, only a public address: the same guard as a custom AI provider’s (loopback, private ranges, link-local and metadata addresses are refused) — at saving, and again at the start of every step of an import.
The user the key belongs to. Not returned to anyone but the project’s owner, and left out of the audit feed.
Write-only: an API key from TestRail’s My Settings → API Keys (a password is not accepted). Stored encrypted with a key of the platform’s own (TESTRAIL_ENCRYPTION_KEY), bound to this project, and in no response, no log, no error message and no audit entry — not in full and not in part. Replacing it replaces the ciphertext; deleting the connection erases it. Create a TestRail user that may only read the project for it: the key has that user’s rights, and that is the only real limit on what Plune can see.
Example
{ "baseUrl": "https://tr.example.com", "apiKey": "example-not-a-real-testrail-key-0123456789"}Responses
Section titled “ Responses ”Saved — the same body as GET
The TestRail connection of a project, as a member of it reads it. With none it is { "configured": false }. The key is not in it, nor any part of it.
object
Present exactly when configured is true, as every field below.
Owner only.
Always true when configured — the answer to “is there a key”, and all it says of it.
userId of the owner who saved the key.
untested after a save; ok after a check or a step that went through; credentials_rejected when TestRail refused the key; unreachable when the check could not talk to the instance.
Example
{ "configured": true, "baseUrl": "https://tr.example.com", "keySet": true, "keySavedAt": "2026-09-16T09:12:04.151Z", "keySavedBy": "u-shop", "status": "untested", "verifiedAt": null}Invalid body, or an address the guard refuses; the message names the field and never a value. Nothing was saved
object
Examples
An address that is not https
{ "error": "validation failed - baseUrl: must be an https address without a user name or password"}An address that is not public
{ "error": "validation failed - baseUrl: the address is not allowed - it must be https and resolve to a public address"}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
object
Example
{ "error": "project 'u-shop::default' not found"}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; nothing is saved
object
Example
{ "error": "the TestRail bridge is not configured on this server - contact your operator"}