Skip to content

Connect a TestRail, or replace its API key

PUT
/v1/projects/{id}/integrations/testrail
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.

id
required
string

An id from GET /v1/projects

Media type application/json

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
baseUrl
required

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.

string
<= 300 characters
email
required

The user the key belongs to. Not returned to anyone but the project’s owner, and left out of the audit feed.

string
<= 254 characters
apiKey
required

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.

string
>= 8 characters <= 256 characters
Example
{
"baseUrl": "https://tr.example.com",
"email": "[email protected]",
"apiKey": "example-not-a-real-testrail-key-0123456789"
}

Saved — the same body as GET

Media type application/json

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
configured
required
boolean
baseUrl

Present exactly when configured is true, as every field below.

string
email

Owner only.

string
keySet

Always true when configured — the answer to “is there a key”, and all it says of it.

boolean
keySavedAt
string format: date-time
keySavedBy

userId of the owner who saved the key.

string
status

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.

string
Allowed values: untested ok credentials_rejected unreachable
verifiedAt
string format: date-time
nullable
Example
{
"configured": true,
"baseUrl": "https://tr.example.com",
"email": "[email protected]",
"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

Media type application/json
object
error
required
string
Examples

An address that is not https

{
"error": "validation failed - baseUrl: must be an https address without a user name or password"
}

No / invalid session — a CLI token is refused here

You are in the project, but not as its owner

Media type application/json
object
error
required
string
Example
{
"error": "project owner only"
}

No such project among yours

Media type application/json
object
error
required
string
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.

Media type application/json
object
error
required
string
Example generated
{
"error": "example"
}
Retry-After
integer

Seconds until the window rolls over

The server has no key to keep TestRail keys under; nothing is saved

Media type application/json
object
error
required
string
Example
{
"error": "the TestRail bridge is not configured on this server - contact your operator"
}