# Actions

Manage test actions (rules) that automatically modify test behavior.

Actions allow you to:

* **Skip** tests that match certain conditions
* **Quarantine** flaky tests so their failures don't fail the run
* **Tag** tests with custom labels for organization

Each action has a **matcher** that defines which tests it applies to, based on conditions like test title, file path, tags, git branch, etc.

## List actions

> Get all actions for a project with optional filtering

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Actions","description":"Manage test actions (rules) that automatically modify test behavior.\n\nActions allow you to:\n- **Skip** tests that match certain conditions\n- **Quarantine** flaky tests so their failures don't fail the run\n- **Tag** tests with custom labels for organization\n\nEach action has a **matcher** that defines which tests it applies to,\nbased on conditions like test title, file path, tags, git branch, etc."}],"servers":[{"url":"https://api.currents.dev/v1","description":"Production API"},{"url":"https://api-staging.currents.dev/v1","description":"Staging API"},{"url":"http://localhost:4000/v1","description":"Local development"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key authentication using Bearer token"}},"parameters":{"ProjectIdQuery":{"name":"projectId","in":"query","required":true,"description":"The project ID","schema":{"type":"string"}},"StatusFilter":{"name":"status","in":"query","required":false,"description":"Filter actions by status (can be specified multiple times)","schema":{"type":"array","items":{"$ref":"#/components/schemas/ActionStatus"}},"style":"form","explode":true},"SearchFilter":{"name":"search","in":"query","required":false,"description":"Search actions by name","schema":{"type":"string","maxLength":100}}},"schemas":{"ActionStatus":{"type":"string","enum":["active","disabled","archived","expired"],"description":"The current status of the action:\n- `active`: Action is enabled and will be applied to matching tests\n- `disabled`: Action is temporarily disabled\n- `archived`: Action has been soft-deleted\n- `expired`: Action has passed its expiration date"},"ActionsListResponse":{"type":"object","required":["status","data"],"properties":{"status":{"type":"string","enum":["OK"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/ActionRecord"}}}},"ActionRecord":{"type":"object","required":["actionId","name","action","matcher","status","createdAt","createdBy"],"properties":{"actionId":{"type":"string","description":"Unique identifier for the action"},"name":{"type":"string","description":"Human-readable name for the action"},"description":{"type":"string","nullable":true,"description":"Optional description"},"action":{"type":"array","items":{"$ref":"#/components/schemas/Action"},"minItems":1,"description":"Actions to perform when conditions match"},"matcher":{"$ref":"#/components/schemas/RuleMatcher"},"status":{"$ref":"#/components/schemas/ActionStatus"},"createdAt":{"type":"string","format":"date-time","description":"When the action was created"},"createdBy":{"type":"string","description":"Email of the user who created the action"},"updatedAt":{"type":"string","format":"date-time","nullable":true},"updatedBy":{"type":"string","nullable":true},"disabledAt":{"type":"string","format":"date-time","nullable":true},"disabledBy":{"type":"string","nullable":true},"archivedAt":{"type":"string","format":"date-time","nullable":true},"archivedBy":{"type":"string","nullable":true},"expiresAfter":{"type":"string","format":"date-time","nullable":true}}},"Action":{"oneOf":[{"$ref":"#/components/schemas/ActionSkip"},{"$ref":"#/components/schemas/ActionQuarantine"},{"$ref":"#/components/schemas/ActionTag"}]},"ActionSkip":{"type":"object","required":["op"],"properties":{"op":{"type":"string","enum":["skip"]}}},"ActionQuarantine":{"type":"object","required":["op"],"properties":{"op":{"type":"string","enum":["quarantine"]}}},"ActionTag":{"type":"object","required":["op","details"],"properties":{"op":{"type":"string","enum":["tag"]},"details":{"type":"object","required":["tags"],"properties":{"tags":{"type":"array","items":{"type":"string"},"maxItems":10,"description":"Tags to add to matching tests"}}}}},"RuleMatcher":{"type":"object","required":["op","cond"],"properties":{"op":{"type":"string","enum":["AND","OR"],"description":"How to combine multiple conditions"},"cond":{"type":"array","items":{"$ref":"#/components/schemas/ActionMatcherCondition"},"minItems":1,"description":"List of conditions to match"}}},"ActionMatcherCondition":{"type":"object","required":["type","op"],"properties":{"type":{"$ref":"#/components/schemas/ConditionType"},"op":{"$ref":"#/components/schemas/ConditionOperator"},"value":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"nullable":true,"description":"The value(s) to match against"}}},"ConditionType":{"type":"string","enum":["testId","project","title","file","git_branch","git_authorName","git_authorEmail","git_remoteOrigin","git_message","error_message","titlePath","annotation","tag"],"description":"The type of condition to match against.\n\n**Note:** Different condition types support different operators:\n- **Primitive types** (`testId`, `project`, `title`, `file`, `git_branch`, `git_authorName`, `git_authorEmail`, `git_remoteOrigin`, `git_message`): Support `eq`, `neq`, `any`, `empty`, `in`, `notIn`\n- **Complex types** (`error_message`, `titlePath`, `annotation`, `tag`): Support all operators including `inc`, `notInc`, `incAll`, `notIncAll`"},"ConditionOperator":{"type":"string","enum":["eq","neq","any","empty","in","notIn","inc","notInc","incAll","notIncAll"],"description":"The comparison operator:\n- `eq`: Equal to\n- `neq`: Not equal to\n- `any`: Matches any value (not null)\n- `empty`: Is empty or null\n- `in`: Value is in the list\n- `notIn`: Value is not in the list\n- `inc`: Includes substring (**only for**: error_message, titlePath, annotation, tag)\n- `notInc`: Does not include substring (**only for**: error_message, titlePath, annotation, tag)\n- `incAll`: Includes all values (**only for**: error_message, titlePath, annotation, tag)\n- `notIncAll`: Does not include all values (**only for**: error_message, titlePath, annotation, tag)"},"ErrorResponse":{"type":"object","required":["status","error"],"properties":{"status":{"type":"string","enum":["FAILED"]},"error":{"type":"string","description":"Error message"}}}},"responses":{"BadRequest":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/actions":{"get":{"summary":"List actions","description":"Get all actions for a project with optional filtering","operationId":"listActions","tags":["Actions"],"parameters":[{"$ref":"#/components/parameters/ProjectIdQuery"},{"$ref":"#/components/parameters/StatusFilter"},{"$ref":"#/components/parameters/SearchFilter"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionsListResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## Create action

> Create a new action for a project

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Actions","description":"Manage test actions (rules) that automatically modify test behavior.\n\nActions allow you to:\n- **Skip** tests that match certain conditions\n- **Quarantine** flaky tests so their failures don't fail the run\n- **Tag** tests with custom labels for organization\n\nEach action has a **matcher** that defines which tests it applies to,\nbased on conditions like test title, file path, tags, git branch, etc."}],"servers":[{"url":"https://api.currents.dev/v1","description":"Production API"},{"url":"https://api-staging.currents.dev/v1","description":"Staging API"},{"url":"http://localhost:4000/v1","description":"Local development"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key authentication using Bearer token"}},"parameters":{"ProjectIdQuery":{"name":"projectId","in":"query","required":true,"description":"The project ID","schema":{"type":"string"}}},"schemas":{"CreateActionRequest":{"type":"object","required":["name","action","matcher"],"properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":1000,"nullable":true},"action":{"type":"array","items":{"$ref":"#/components/schemas/Action"},"minItems":1},"matcher":{"$ref":"#/components/schemas/RuleMatcher"},"expiresAfter":{"type":"string","format":"date-time","nullable":true}}},"Action":{"oneOf":[{"$ref":"#/components/schemas/ActionSkip"},{"$ref":"#/components/schemas/ActionQuarantine"},{"$ref":"#/components/schemas/ActionTag"}]},"ActionSkip":{"type":"object","required":["op"],"properties":{"op":{"type":"string","enum":["skip"]}}},"ActionQuarantine":{"type":"object","required":["op"],"properties":{"op":{"type":"string","enum":["quarantine"]}}},"ActionTag":{"type":"object","required":["op","details"],"properties":{"op":{"type":"string","enum":["tag"]},"details":{"type":"object","required":["tags"],"properties":{"tags":{"type":"array","items":{"type":"string"},"maxItems":10,"description":"Tags to add to matching tests"}}}}},"RuleMatcher":{"type":"object","required":["op","cond"],"properties":{"op":{"type":"string","enum":["AND","OR"],"description":"How to combine multiple conditions"},"cond":{"type":"array","items":{"$ref":"#/components/schemas/ActionMatcherCondition"},"minItems":1,"description":"List of conditions to match"}}},"ActionMatcherCondition":{"type":"object","required":["type","op"],"properties":{"type":{"$ref":"#/components/schemas/ConditionType"},"op":{"$ref":"#/components/schemas/ConditionOperator"},"value":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"nullable":true,"description":"The value(s) to match against"}}},"ConditionType":{"type":"string","enum":["testId","project","title","file","git_branch","git_authorName","git_authorEmail","git_remoteOrigin","git_message","error_message","titlePath","annotation","tag"],"description":"The type of condition to match against.\n\n**Note:** Different condition types support different operators:\n- **Primitive types** (`testId`, `project`, `title`, `file`, `git_branch`, `git_authorName`, `git_authorEmail`, `git_remoteOrigin`, `git_message`): Support `eq`, `neq`, `any`, `empty`, `in`, `notIn`\n- **Complex types** (`error_message`, `titlePath`, `annotation`, `tag`): Support all operators including `inc`, `notInc`, `incAll`, `notIncAll`"},"ConditionOperator":{"type":"string","enum":["eq","neq","any","empty","in","notIn","inc","notInc","incAll","notIncAll"],"description":"The comparison operator:\n- `eq`: Equal to\n- `neq`: Not equal to\n- `any`: Matches any value (not null)\n- `empty`: Is empty or null\n- `in`: Value is in the list\n- `notIn`: Value is not in the list\n- `inc`: Includes substring (**only for**: error_message, titlePath, annotation, tag)\n- `notInc`: Does not include substring (**only for**: error_message, titlePath, annotation, tag)\n- `incAll`: Includes all values (**only for**: error_message, titlePath, annotation, tag)\n- `notIncAll`: Does not include all values (**only for**: error_message, titlePath, annotation, tag)"},"ActionResponse":{"type":"object","required":["status","data"],"properties":{"status":{"type":"string","enum":["OK"]},"data":{"$ref":"#/components/schemas/ActionRecord"}}},"ActionRecord":{"type":"object","required":["actionId","name","action","matcher","status","createdAt","createdBy"],"properties":{"actionId":{"type":"string","description":"Unique identifier for the action"},"name":{"type":"string","description":"Human-readable name for the action"},"description":{"type":"string","nullable":true,"description":"Optional description"},"action":{"type":"array","items":{"$ref":"#/components/schemas/Action"},"minItems":1,"description":"Actions to perform when conditions match"},"matcher":{"$ref":"#/components/schemas/RuleMatcher"},"status":{"$ref":"#/components/schemas/ActionStatus"},"createdAt":{"type":"string","format":"date-time","description":"When the action was created"},"createdBy":{"type":"string","description":"Email of the user who created the action"},"updatedAt":{"type":"string","format":"date-time","nullable":true},"updatedBy":{"type":"string","nullable":true},"disabledAt":{"type":"string","format":"date-time","nullable":true},"disabledBy":{"type":"string","nullable":true},"archivedAt":{"type":"string","format":"date-time","nullable":true},"archivedBy":{"type":"string","nullable":true},"expiresAfter":{"type":"string","format":"date-time","nullable":true}}},"ActionStatus":{"type":"string","enum":["active","disabled","archived","expired"],"description":"The current status of the action:\n- `active`: Action is enabled and will be applied to matching tests\n- `disabled`: Action is temporarily disabled\n- `archived`: Action has been soft-deleted\n- `expired`: Action has passed its expiration date"},"ErrorResponse":{"type":"object","required":["status","error"],"properties":{"status":{"type":"string","enum":["FAILED"]},"error":{"type":"string","description":"Error message"}}}},"responses":{"BadRequest":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/actions":{"post":{"summary":"Create action","description":"Create a new action for a project","operationId":"createAction","tags":["Actions"],"parameters":[{"$ref":"#/components/parameters/ProjectIdQuery"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateActionRequest"}}}},"responses":{"201":{"description":"Action created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## Get action

> Get a single action by ID. The actionId is globally unique, so projectId is not required.

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Actions","description":"Manage test actions (rules) that automatically modify test behavior.\n\nActions allow you to:\n- **Skip** tests that match certain conditions\n- **Quarantine** flaky tests so their failures don't fail the run\n- **Tag** tests with custom labels for organization\n\nEach action has a **matcher** that defines which tests it applies to,\nbased on conditions like test title, file path, tags, git branch, etc."}],"servers":[{"url":"https://api.currents.dev/v1","description":"Production API"},{"url":"https://api-staging.currents.dev/v1","description":"Staging API"},{"url":"http://localhost:4000/v1","description":"Local development"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key authentication using Bearer token"}},"parameters":{"ActionIdPath":{"name":"actionId","in":"path","required":true,"description":"The action ID","schema":{"type":"string"}}},"schemas":{"ActionResponse":{"type":"object","required":["status","data"],"properties":{"status":{"type":"string","enum":["OK"]},"data":{"$ref":"#/components/schemas/ActionRecord"}}},"ActionRecord":{"type":"object","required":["actionId","name","action","matcher","status","createdAt","createdBy"],"properties":{"actionId":{"type":"string","description":"Unique identifier for the action"},"name":{"type":"string","description":"Human-readable name for the action"},"description":{"type":"string","nullable":true,"description":"Optional description"},"action":{"type":"array","items":{"$ref":"#/components/schemas/Action"},"minItems":1,"description":"Actions to perform when conditions match"},"matcher":{"$ref":"#/components/schemas/RuleMatcher"},"status":{"$ref":"#/components/schemas/ActionStatus"},"createdAt":{"type":"string","format":"date-time","description":"When the action was created"},"createdBy":{"type":"string","description":"Email of the user who created the action"},"updatedAt":{"type":"string","format":"date-time","nullable":true},"updatedBy":{"type":"string","nullable":true},"disabledAt":{"type":"string","format":"date-time","nullable":true},"disabledBy":{"type":"string","nullable":true},"archivedAt":{"type":"string","format":"date-time","nullable":true},"archivedBy":{"type":"string","nullable":true},"expiresAfter":{"type":"string","format":"date-time","nullable":true}}},"Action":{"oneOf":[{"$ref":"#/components/schemas/ActionSkip"},{"$ref":"#/components/schemas/ActionQuarantine"},{"$ref":"#/components/schemas/ActionTag"}]},"ActionSkip":{"type":"object","required":["op"],"properties":{"op":{"type":"string","enum":["skip"]}}},"ActionQuarantine":{"type":"object","required":["op"],"properties":{"op":{"type":"string","enum":["quarantine"]}}},"ActionTag":{"type":"object","required":["op","details"],"properties":{"op":{"type":"string","enum":["tag"]},"details":{"type":"object","required":["tags"],"properties":{"tags":{"type":"array","items":{"type":"string"},"maxItems":10,"description":"Tags to add to matching tests"}}}}},"RuleMatcher":{"type":"object","required":["op","cond"],"properties":{"op":{"type":"string","enum":["AND","OR"],"description":"How to combine multiple conditions"},"cond":{"type":"array","items":{"$ref":"#/components/schemas/ActionMatcherCondition"},"minItems":1,"description":"List of conditions to match"}}},"ActionMatcherCondition":{"type":"object","required":["type","op"],"properties":{"type":{"$ref":"#/components/schemas/ConditionType"},"op":{"$ref":"#/components/schemas/ConditionOperator"},"value":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"nullable":true,"description":"The value(s) to match against"}}},"ConditionType":{"type":"string","enum":["testId","project","title","file","git_branch","git_authorName","git_authorEmail","git_remoteOrigin","git_message","error_message","titlePath","annotation","tag"],"description":"The type of condition to match against.\n\n**Note:** Different condition types support different operators:\n- **Primitive types** (`testId`, `project`, `title`, `file`, `git_branch`, `git_authorName`, `git_authorEmail`, `git_remoteOrigin`, `git_message`): Support `eq`, `neq`, `any`, `empty`, `in`, `notIn`\n- **Complex types** (`error_message`, `titlePath`, `annotation`, `tag`): Support all operators including `inc`, `notInc`, `incAll`, `notIncAll`"},"ConditionOperator":{"type":"string","enum":["eq","neq","any","empty","in","notIn","inc","notInc","incAll","notIncAll"],"description":"The comparison operator:\n- `eq`: Equal to\n- `neq`: Not equal to\n- `any`: Matches any value (not null)\n- `empty`: Is empty or null\n- `in`: Value is in the list\n- `notIn`: Value is not in the list\n- `inc`: Includes substring (**only for**: error_message, titlePath, annotation, tag)\n- `notInc`: Does not include substring (**only for**: error_message, titlePath, annotation, tag)\n- `incAll`: Includes all values (**only for**: error_message, titlePath, annotation, tag)\n- `notIncAll`: Does not include all values (**only for**: error_message, titlePath, annotation, tag)"},"ActionStatus":{"type":"string","enum":["active","disabled","archived","expired"],"description":"The current status of the action:\n- `active`: Action is enabled and will be applied to matching tests\n- `disabled`: Action is temporarily disabled\n- `archived`: Action has been soft-deleted\n- `expired`: Action has passed its expiration date"},"ErrorResponse":{"type":"object","required":["status","error"],"properties":{"status":{"type":"string","enum":["FAILED"]},"error":{"type":"string","description":"Error message"}}}},"responses":{"BadRequest":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/actions/{actionId}":{"get":{"summary":"Get action","description":"Get a single action by ID. The actionId is globally unique, so projectId is not required.","operationId":"getAction","tags":["Actions"],"parameters":[{"$ref":"#/components/parameters/ActionIdPath"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## Update action

> Update an existing action. The actionId is globally unique, so projectId is not required.

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Actions","description":"Manage test actions (rules) that automatically modify test behavior.\n\nActions allow you to:\n- **Skip** tests that match certain conditions\n- **Quarantine** flaky tests so their failures don't fail the run\n- **Tag** tests with custom labels for organization\n\nEach action has a **matcher** that defines which tests it applies to,\nbased on conditions like test title, file path, tags, git branch, etc."}],"servers":[{"url":"https://api.currents.dev/v1","description":"Production API"},{"url":"https://api-staging.currents.dev/v1","description":"Staging API"},{"url":"http://localhost:4000/v1","description":"Local development"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key authentication using Bearer token"}},"parameters":{"ActionIdPath":{"name":"actionId","in":"path","required":true,"description":"The action ID","schema":{"type":"string"}}},"schemas":{"UpdateActionRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":1000,"nullable":true},"action":{"type":"array","items":{"$ref":"#/components/schemas/Action"},"minItems":1},"matcher":{"$ref":"#/components/schemas/RuleMatcher"},"expiresAfter":{"type":"string","format":"date-time","nullable":true}}},"Action":{"oneOf":[{"$ref":"#/components/schemas/ActionSkip"},{"$ref":"#/components/schemas/ActionQuarantine"},{"$ref":"#/components/schemas/ActionTag"}]},"ActionSkip":{"type":"object","required":["op"],"properties":{"op":{"type":"string","enum":["skip"]}}},"ActionQuarantine":{"type":"object","required":["op"],"properties":{"op":{"type":"string","enum":["quarantine"]}}},"ActionTag":{"type":"object","required":["op","details"],"properties":{"op":{"type":"string","enum":["tag"]},"details":{"type":"object","required":["tags"],"properties":{"tags":{"type":"array","items":{"type":"string"},"maxItems":10,"description":"Tags to add to matching tests"}}}}},"RuleMatcher":{"type":"object","required":["op","cond"],"properties":{"op":{"type":"string","enum":["AND","OR"],"description":"How to combine multiple conditions"},"cond":{"type":"array","items":{"$ref":"#/components/schemas/ActionMatcherCondition"},"minItems":1,"description":"List of conditions to match"}}},"ActionMatcherCondition":{"type":"object","required":["type","op"],"properties":{"type":{"$ref":"#/components/schemas/ConditionType"},"op":{"$ref":"#/components/schemas/ConditionOperator"},"value":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"nullable":true,"description":"The value(s) to match against"}}},"ConditionType":{"type":"string","enum":["testId","project","title","file","git_branch","git_authorName","git_authorEmail","git_remoteOrigin","git_message","error_message","titlePath","annotation","tag"],"description":"The type of condition to match against.\n\n**Note:** Different condition types support different operators:\n- **Primitive types** (`testId`, `project`, `title`, `file`, `git_branch`, `git_authorName`, `git_authorEmail`, `git_remoteOrigin`, `git_message`): Support `eq`, `neq`, `any`, `empty`, `in`, `notIn`\n- **Complex types** (`error_message`, `titlePath`, `annotation`, `tag`): Support all operators including `inc`, `notInc`, `incAll`, `notIncAll`"},"ConditionOperator":{"type":"string","enum":["eq","neq","any","empty","in","notIn","inc","notInc","incAll","notIncAll"],"description":"The comparison operator:\n- `eq`: Equal to\n- `neq`: Not equal to\n- `any`: Matches any value (not null)\n- `empty`: Is empty or null\n- `in`: Value is in the list\n- `notIn`: Value is not in the list\n- `inc`: Includes substring (**only for**: error_message, titlePath, annotation, tag)\n- `notInc`: Does not include substring (**only for**: error_message, titlePath, annotation, tag)\n- `incAll`: Includes all values (**only for**: error_message, titlePath, annotation, tag)\n- `notIncAll`: Does not include all values (**only for**: error_message, titlePath, annotation, tag)"},"ActionResponse":{"type":"object","required":["status","data"],"properties":{"status":{"type":"string","enum":["OK"]},"data":{"$ref":"#/components/schemas/ActionRecord"}}},"ActionRecord":{"type":"object","required":["actionId","name","action","matcher","status","createdAt","createdBy"],"properties":{"actionId":{"type":"string","description":"Unique identifier for the action"},"name":{"type":"string","description":"Human-readable name for the action"},"description":{"type":"string","nullable":true,"description":"Optional description"},"action":{"type":"array","items":{"$ref":"#/components/schemas/Action"},"minItems":1,"description":"Actions to perform when conditions match"},"matcher":{"$ref":"#/components/schemas/RuleMatcher"},"status":{"$ref":"#/components/schemas/ActionStatus"},"createdAt":{"type":"string","format":"date-time","description":"When the action was created"},"createdBy":{"type":"string","description":"Email of the user who created the action"},"updatedAt":{"type":"string","format":"date-time","nullable":true},"updatedBy":{"type":"string","nullable":true},"disabledAt":{"type":"string","format":"date-time","nullable":true},"disabledBy":{"type":"string","nullable":true},"archivedAt":{"type":"string","format":"date-time","nullable":true},"archivedBy":{"type":"string","nullable":true},"expiresAfter":{"type":"string","format":"date-time","nullable":true}}},"ActionStatus":{"type":"string","enum":["active","disabled","archived","expired"],"description":"The current status of the action:\n- `active`: Action is enabled and will be applied to matching tests\n- `disabled`: Action is temporarily disabled\n- `archived`: Action has been soft-deleted\n- `expired`: Action has passed its expiration date"},"ErrorResponse":{"type":"object","required":["status","error"],"properties":{"status":{"type":"string","enum":["FAILED"]},"error":{"type":"string","description":"Error message"}}}},"responses":{"BadRequest":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/actions/{actionId}":{"put":{"summary":"Update action","description":"Update an existing action. The actionId is globally unique, so projectId is not required.","operationId":"updateAction","tags":["Actions"],"parameters":[{"$ref":"#/components/parameters/ActionIdPath"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateActionRequest"}}}},"responses":{"200":{"description":"Action updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## Delete action

> Archive an action (soft delete). The actionId is globally unique, so projectId is not required.

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Actions","description":"Manage test actions (rules) that automatically modify test behavior.\n\nActions allow you to:\n- **Skip** tests that match certain conditions\n- **Quarantine** flaky tests so their failures don't fail the run\n- **Tag** tests with custom labels for organization\n\nEach action has a **matcher** that defines which tests it applies to,\nbased on conditions like test title, file path, tags, git branch, etc."}],"servers":[{"url":"https://api.currents.dev/v1","description":"Production API"},{"url":"https://api-staging.currents.dev/v1","description":"Staging API"},{"url":"http://localhost:4000/v1","description":"Local development"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key authentication using Bearer token"}},"parameters":{"ActionIdPath":{"name":"actionId","in":"path","required":true,"description":"The action ID","schema":{"type":"string"}}},"schemas":{"ActionDeleteResponse":{"type":"object","required":["status","data"],"properties":{"status":{"type":"string","enum":["OK"]},"data":{"type":"object","required":["actionId","archived"],"properties":{"actionId":{"type":"string"},"archived":{"type":"boolean"}}}}},"ErrorResponse":{"type":"object","required":["status","error"],"properties":{"status":{"type":"string","enum":["FAILED"]},"error":{"type":"string","description":"Error message"}}}},"responses":{"BadRequest":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/actions/{actionId}":{"delete":{"summary":"Delete action","description":"Archive an action (soft delete). The actionId is globally unique, so projectId is not required.","operationId":"deleteAction","tags":["Actions"],"parameters":[{"$ref":"#/components/parameters/ActionIdPath"}],"responses":{"200":{"description":"Action archived successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionDeleteResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## Enable action

> Enable a disabled action. The actionId is globally unique, so projectId is not required.

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Actions","description":"Manage test actions (rules) that automatically modify test behavior.\n\nActions allow you to:\n- **Skip** tests that match certain conditions\n- **Quarantine** flaky tests so their failures don't fail the run\n- **Tag** tests with custom labels for organization\n\nEach action has a **matcher** that defines which tests it applies to,\nbased on conditions like test title, file path, tags, git branch, etc."}],"servers":[{"url":"https://api.currents.dev/v1","description":"Production API"},{"url":"https://api-staging.currents.dev/v1","description":"Staging API"},{"url":"http://localhost:4000/v1","description":"Local development"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key authentication using Bearer token"}},"parameters":{"ActionIdPath":{"name":"actionId","in":"path","required":true,"description":"The action ID","schema":{"type":"string"}}},"schemas":{"ActionResponse":{"type":"object","required":["status","data"],"properties":{"status":{"type":"string","enum":["OK"]},"data":{"$ref":"#/components/schemas/ActionRecord"}}},"ActionRecord":{"type":"object","required":["actionId","name","action","matcher","status","createdAt","createdBy"],"properties":{"actionId":{"type":"string","description":"Unique identifier for the action"},"name":{"type":"string","description":"Human-readable name for the action"},"description":{"type":"string","nullable":true,"description":"Optional description"},"action":{"type":"array","items":{"$ref":"#/components/schemas/Action"},"minItems":1,"description":"Actions to perform when conditions match"},"matcher":{"$ref":"#/components/schemas/RuleMatcher"},"status":{"$ref":"#/components/schemas/ActionStatus"},"createdAt":{"type":"string","format":"date-time","description":"When the action was created"},"createdBy":{"type":"string","description":"Email of the user who created the action"},"updatedAt":{"type":"string","format":"date-time","nullable":true},"updatedBy":{"type":"string","nullable":true},"disabledAt":{"type":"string","format":"date-time","nullable":true},"disabledBy":{"type":"string","nullable":true},"archivedAt":{"type":"string","format":"date-time","nullable":true},"archivedBy":{"type":"string","nullable":true},"expiresAfter":{"type":"string","format":"date-time","nullable":true}}},"Action":{"oneOf":[{"$ref":"#/components/schemas/ActionSkip"},{"$ref":"#/components/schemas/ActionQuarantine"},{"$ref":"#/components/schemas/ActionTag"}]},"ActionSkip":{"type":"object","required":["op"],"properties":{"op":{"type":"string","enum":["skip"]}}},"ActionQuarantine":{"type":"object","required":["op"],"properties":{"op":{"type":"string","enum":["quarantine"]}}},"ActionTag":{"type":"object","required":["op","details"],"properties":{"op":{"type":"string","enum":["tag"]},"details":{"type":"object","required":["tags"],"properties":{"tags":{"type":"array","items":{"type":"string"},"maxItems":10,"description":"Tags to add to matching tests"}}}}},"RuleMatcher":{"type":"object","required":["op","cond"],"properties":{"op":{"type":"string","enum":["AND","OR"],"description":"How to combine multiple conditions"},"cond":{"type":"array","items":{"$ref":"#/components/schemas/ActionMatcherCondition"},"minItems":1,"description":"List of conditions to match"}}},"ActionMatcherCondition":{"type":"object","required":["type","op"],"properties":{"type":{"$ref":"#/components/schemas/ConditionType"},"op":{"$ref":"#/components/schemas/ConditionOperator"},"value":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"nullable":true,"description":"The value(s) to match against"}}},"ConditionType":{"type":"string","enum":["testId","project","title","file","git_branch","git_authorName","git_authorEmail","git_remoteOrigin","git_message","error_message","titlePath","annotation","tag"],"description":"The type of condition to match against.\n\n**Note:** Different condition types support different operators:\n- **Primitive types** (`testId`, `project`, `title`, `file`, `git_branch`, `git_authorName`, `git_authorEmail`, `git_remoteOrigin`, `git_message`): Support `eq`, `neq`, `any`, `empty`, `in`, `notIn`\n- **Complex types** (`error_message`, `titlePath`, `annotation`, `tag`): Support all operators including `inc`, `notInc`, `incAll`, `notIncAll`"},"ConditionOperator":{"type":"string","enum":["eq","neq","any","empty","in","notIn","inc","notInc","incAll","notIncAll"],"description":"The comparison operator:\n- `eq`: Equal to\n- `neq`: Not equal to\n- `any`: Matches any value (not null)\n- `empty`: Is empty or null\n- `in`: Value is in the list\n- `notIn`: Value is not in the list\n- `inc`: Includes substring (**only for**: error_message, titlePath, annotation, tag)\n- `notInc`: Does not include substring (**only for**: error_message, titlePath, annotation, tag)\n- `incAll`: Includes all values (**only for**: error_message, titlePath, annotation, tag)\n- `notIncAll`: Does not include all values (**only for**: error_message, titlePath, annotation, tag)"},"ActionStatus":{"type":"string","enum":["active","disabled","archived","expired"],"description":"The current status of the action:\n- `active`: Action is enabled and will be applied to matching tests\n- `disabled`: Action is temporarily disabled\n- `archived`: Action has been soft-deleted\n- `expired`: Action has passed its expiration date"},"ErrorResponse":{"type":"object","required":["status","error"],"properties":{"status":{"type":"string","enum":["FAILED"]},"error":{"type":"string","description":"Error message"}}}},"responses":{"BadRequest":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/actions/{actionId}/enable":{"put":{"summary":"Enable action","description":"Enable a disabled action. The actionId is globally unique, so projectId is not required.","operationId":"enableAction","tags":["Actions"],"parameters":[{"$ref":"#/components/parameters/ActionIdPath"}],"responses":{"200":{"description":"Action enabled successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## Disable action

> Disable an active action. The actionId is globally unique, so projectId is not required.

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Actions","description":"Manage test actions (rules) that automatically modify test behavior.\n\nActions allow you to:\n- **Skip** tests that match certain conditions\n- **Quarantine** flaky tests so their failures don't fail the run\n- **Tag** tests with custom labels for organization\n\nEach action has a **matcher** that defines which tests it applies to,\nbased on conditions like test title, file path, tags, git branch, etc."}],"servers":[{"url":"https://api.currents.dev/v1","description":"Production API"},{"url":"https://api-staging.currents.dev/v1","description":"Staging API"},{"url":"http://localhost:4000/v1","description":"Local development"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key authentication using Bearer token"}},"parameters":{"ActionIdPath":{"name":"actionId","in":"path","required":true,"description":"The action ID","schema":{"type":"string"}}},"schemas":{"ActionResponse":{"type":"object","required":["status","data"],"properties":{"status":{"type":"string","enum":["OK"]},"data":{"$ref":"#/components/schemas/ActionRecord"}}},"ActionRecord":{"type":"object","required":["actionId","name","action","matcher","status","createdAt","createdBy"],"properties":{"actionId":{"type":"string","description":"Unique identifier for the action"},"name":{"type":"string","description":"Human-readable name for the action"},"description":{"type":"string","nullable":true,"description":"Optional description"},"action":{"type":"array","items":{"$ref":"#/components/schemas/Action"},"minItems":1,"description":"Actions to perform when conditions match"},"matcher":{"$ref":"#/components/schemas/RuleMatcher"},"status":{"$ref":"#/components/schemas/ActionStatus"},"createdAt":{"type":"string","format":"date-time","description":"When the action was created"},"createdBy":{"type":"string","description":"Email of the user who created the action"},"updatedAt":{"type":"string","format":"date-time","nullable":true},"updatedBy":{"type":"string","nullable":true},"disabledAt":{"type":"string","format":"date-time","nullable":true},"disabledBy":{"type":"string","nullable":true},"archivedAt":{"type":"string","format":"date-time","nullable":true},"archivedBy":{"type":"string","nullable":true},"expiresAfter":{"type":"string","format":"date-time","nullable":true}}},"Action":{"oneOf":[{"$ref":"#/components/schemas/ActionSkip"},{"$ref":"#/components/schemas/ActionQuarantine"},{"$ref":"#/components/schemas/ActionTag"}]},"ActionSkip":{"type":"object","required":["op"],"properties":{"op":{"type":"string","enum":["skip"]}}},"ActionQuarantine":{"type":"object","required":["op"],"properties":{"op":{"type":"string","enum":["quarantine"]}}},"ActionTag":{"type":"object","required":["op","details"],"properties":{"op":{"type":"string","enum":["tag"]},"details":{"type":"object","required":["tags"],"properties":{"tags":{"type":"array","items":{"type":"string"},"maxItems":10,"description":"Tags to add to matching tests"}}}}},"RuleMatcher":{"type":"object","required":["op","cond"],"properties":{"op":{"type":"string","enum":["AND","OR"],"description":"How to combine multiple conditions"},"cond":{"type":"array","items":{"$ref":"#/components/schemas/ActionMatcherCondition"},"minItems":1,"description":"List of conditions to match"}}},"ActionMatcherCondition":{"type":"object","required":["type","op"],"properties":{"type":{"$ref":"#/components/schemas/ConditionType"},"op":{"$ref":"#/components/schemas/ConditionOperator"},"value":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"nullable":true,"description":"The value(s) to match against"}}},"ConditionType":{"type":"string","enum":["testId","project","title","file","git_branch","git_authorName","git_authorEmail","git_remoteOrigin","git_message","error_message","titlePath","annotation","tag"],"description":"The type of condition to match against.\n\n**Note:** Different condition types support different operators:\n- **Primitive types** (`testId`, `project`, `title`, `file`, `git_branch`, `git_authorName`, `git_authorEmail`, `git_remoteOrigin`, `git_message`): Support `eq`, `neq`, `any`, `empty`, `in`, `notIn`\n- **Complex types** (`error_message`, `titlePath`, `annotation`, `tag`): Support all operators including `inc`, `notInc`, `incAll`, `notIncAll`"},"ConditionOperator":{"type":"string","enum":["eq","neq","any","empty","in","notIn","inc","notInc","incAll","notIncAll"],"description":"The comparison operator:\n- `eq`: Equal to\n- `neq`: Not equal to\n- `any`: Matches any value (not null)\n- `empty`: Is empty or null\n- `in`: Value is in the list\n- `notIn`: Value is not in the list\n- `inc`: Includes substring (**only for**: error_message, titlePath, annotation, tag)\n- `notInc`: Does not include substring (**only for**: error_message, titlePath, annotation, tag)\n- `incAll`: Includes all values (**only for**: error_message, titlePath, annotation, tag)\n- `notIncAll`: Does not include all values (**only for**: error_message, titlePath, annotation, tag)"},"ActionStatus":{"type":"string","enum":["active","disabled","archived","expired"],"description":"The current status of the action:\n- `active`: Action is enabled and will be applied to matching tests\n- `disabled`: Action is temporarily disabled\n- `archived`: Action has been soft-deleted\n- `expired`: Action has passed its expiration date"},"ErrorResponse":{"type":"object","required":["status","error"],"properties":{"status":{"type":"string","enum":["FAILED"]},"error":{"type":"string","description":"Error message"}}}},"responses":{"BadRequest":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/actions/{actionId}/disable":{"put":{"summary":"Disable action","description":"Disable an active action. The actionId is globally unique, so projectId is not required.","operationId":"disableAction","tags":["Actions"],"parameters":[{"$ref":"#/components/parameters/ActionIdPath"}],"responses":{"200":{"description":"Action disabled successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## List affected tests

> Get tests affected by actions (quarantine, skip, tag) for a project within a date range. Returns aggregated data grouped by test signature.

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Actions","description":"Manage test actions (rules) that automatically modify test behavior.\n\nActions allow you to:\n- **Skip** tests that match certain conditions\n- **Quarantine** flaky tests so their failures don't fail the run\n- **Tag** tests with custom labels for organization\n\nEach action has a **matcher** that defines which tests it applies to,\nbased on conditions like test title, file path, tags, git branch, etc."}],"servers":[{"url":"https://api.currents.dev/v1","description":"Production API"},{"url":"https://api-staging.currents.dev/v1","description":"Staging API"},{"url":"http://localhost:4000/v1","description":"Local development"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key authentication using Bearer token"}},"parameters":{"ProjectIdQuery":{"name":"projectId","in":"query","required":true,"description":"The project ID","schema":{"type":"string"}},"DateStartQuery":{"name":"date_start","in":"query","required":true,"description":"Start date in ISO 8601 format","schema":{"type":"string","format":"date-time"}},"DateEndQuery":{"name":"date_end","in":"query","required":true,"description":"End date in ISO 8601 format","schema":{"type":"string","format":"date-time"}},"PageQuery":{"name":"page","in":"query","required":false,"description":"Page number (0-indexed)","schema":{"type":"integer","minimum":0,"default":0}},"SortDirectionQuery":{"name":"dir","in":"query","required":false,"description":"Sort direction: `desc` (default) or `asc`.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}}},"schemas":{"ActionOp":{"type":"string","enum":["quarantine","skip","tag"],"description":"Action operation: quarantine, skip (do not run), or tag"},"ActionStatus":{"type":"string","enum":["active","disabled","archived","expired"],"description":"The current status of the action:\n- `active`: Action is enabled and will be applied to matching tests\n- `disabled`: Action is temporarily disabled\n- `archived`: Action has been soft-deleted\n- `expired`: Action has passed its expiration date"},"AffectedTestsListResponse":{"type":"object","required":["status","data"],"properties":{"status":{"type":"string","enum":["OK"]},"data":{"type":"object","required":["list","count","total","nextPage"],"properties":{"list":{"type":"array","items":{"$ref":"#/components/schemas/AffectedTestListItem"}},"count":{"type":"integer","description":"Number of items in the current page"},"total":{"type":"integer","description":"Total number of affected tests"},"nextPage":{"oneOf":[{"type":"integer"},{"type":"boolean","enum":[false]}],"description":"Next page number (0-indexed), or false if no more pages"}}}}},"AffectedTestListItem":{"type":"object","required":["signature","title","specFile","actions","lastSeen","recordingCount"],"properties":{"signature":{"type":"string","description":"Unique test signature hash"},"title":{"type":"string","description":"Test title"},"specFile":{"type":"string","description":"Spec file path"},"actions":{"type":"array","items":{"$ref":"#/components/schemas/AffectedTestAction"},"description":"Actions applied to this test"},"lastSeen":{"type":"string","format":"date-time","description":"Last time this test was seen"},"recordingCount":{"type":"integer","description":"Number of test recordings in the date range"}}},"AffectedTestAction":{"type":"object","required":["types","name","id","status","expiresAt","lastSeen","recordingCount"],"properties":{"types":{"type":"array","items":{"$ref":"#/components/schemas/ActionOp"},"description":"Action types (a single rule can have multiple operations)"},"name":{"type":"string","description":"Action/rule name"},"id":{"type":"string","description":"Action/rule ID"},"status":{"$ref":"#/components/schemas/ActionStatus"},"expiresAt":{"type":"string","format":"date-time","nullable":true,"description":"Expiration timestamp, or null if no expiration"},"tags":{"type":"array","items":{"type":"string"},"description":"Tag values (only present when types includes tag)"},"lastSeen":{"type":"string","format":"date-time","description":"Timestamp of last execution with this action (in the list date range)"},"recordingCount":{"type":"integer","description":"Number of test recordings with this action (in the list date range)"}}},"ErrorResponse":{"type":"object","required":["status","error"],"properties":{"status":{"type":"string","enum":["FAILED"]},"error":{"type":"string","description":"Error message"}}}},"responses":{"BadRequest":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/actions/tests":{"get":{"summary":"List affected tests","description":"Get tests affected by actions (quarantine, skip, tag) for a project within a date range. Returns aggregated data grouped by test signature.","operationId":"listAffectedTests","tags":["Actions"],"parameters":[{"$ref":"#/components/parameters/ProjectIdQuery"},{"$ref":"#/components/parameters/DateStartQuery"},{"$ref":"#/components/parameters/DateEndQuery"},{"$ref":"#/components/parameters/PageQuery"},{"name":"limit","in":"query","required":false,"description":"Maximum number of results (1-100)","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"search","in":"query","required":false,"description":"Search by spec file path, test title, or action name (case-insensitive)","schema":{"type":"string","maxLength":100}},{"name":"action_type","in":"query","required":false,"description":"Filter by action types (action_type)","schema":{"type":"array","items":{"$ref":"#/components/schemas/ActionOp"}},"style":"form","explode":true},{"name":"action_id","in":"query","required":false,"description":"Filter by specific action ID (action_id)","schema":{"type":"string"}},{"$ref":"#/components/parameters/SortDirectionQuery"},{"name":"status","in":"query","required":false,"description":"Filter by action status. Accepts multiple values. Omit for all statuses.","schema":{"type":"array","items":{"$ref":"#/components/schemas/ActionStatus"}},"style":"form","explode":true}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AffectedTestsListResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## Get affected test executions

> Get execution details for a specific affected test (by signature) within a date range. Returns individual test execution records with action info. Results are paginated with cursor-based pagination using the \`starting\_after\` and \`ending\_before\` query parameters. To list executions for a single rule across all tests, use \`GET /actions/{actionId}/tests\` instead of the removed \`action\_id\` query parameter.

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Actions","description":"Manage test actions (rules) that automatically modify test behavior.\n\nActions allow you to:\n- **Skip** tests that match certain conditions\n- **Quarantine** flaky tests so their failures don't fail the run\n- **Tag** tests with custom labels for organization\n\nEach action has a **matcher** that defines which tests it applies to,\nbased on conditions like test title, file path, tags, git branch, etc."}],"servers":[{"url":"https://api.currents.dev/v1","description":"Production API"},{"url":"https://api-staging.currents.dev/v1","description":"Staging API"},{"url":"http://localhost:4000/v1","description":"Local development"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key authentication using Bearer token"}},"parameters":{"ProjectIdQuery":{"name":"projectId","in":"query","required":true,"description":"The project ID","schema":{"type":"string"}},"DateStartQuery":{"name":"date_start","in":"query","required":true,"description":"Start date in ISO 8601 format","schema":{"type":"string","format":"date-time"}},"DateEndQuery":{"name":"date_end","in":"query","required":true,"description":"End date in ISO 8601 format","schema":{"type":"string","format":"date-time"}},"StartingAfterQuery":{"name":"starting_after","in":"query","required":false,"description":"Cursor for pagination. Returns items after this cursor value.","schema":{"type":"string"}},"EndingBeforeQuery":{"name":"ending_before","in":"query","required":false,"description":"Cursor for pagination. Returns items before this cursor value.","schema":{"type":"string"}}},"schemas":{"AffectedTestExecutionsResponse":{"type":"object","required":["status","data"],"properties":{"status":{"type":"string","enum":["OK"]},"data":{"type":"object","required":["executions","has_more"],"properties":{"executions":{"type":"array","items":{"$ref":"#/components/schemas/AffectedTestExecution"}},"has_more":{"type":"boolean","description":"Whether more execution rows exist after this page"}}}}},"AffectedTestExecution":{"type":"object","required":["cursor","runId","instanceId","testId","specFile","title","signature","branch","commitSha","prTitle","prId","commitMessage","executedAt"],"properties":{"cursor":{"type":"string","description":"Test document id; pass as starting_after to fetch the next page"},"runId":{"type":"string","description":"Run ID"},"instanceId":{"type":"string","description":"Instance ID"},"testId":{"type":"string","description":"Test ID"},"specFile":{"type":"string","description":"Spec file path for this test"},"title":{"type":"string","description":"Test title"},"signature":{"type":"string","description":"Stable test signature"},"branch":{"type":"string","nullable":true,"description":"Git branch"},"commitSha":{"type":"string","nullable":true,"description":"Git commit SHA"},"prTitle":{"type":"string","nullable":true,"description":"Raw pull request title from CI when present"},"prId":{"type":"string","nullable":true,"description":"Raw pull request id from CI when present"},"commitMessage":{"type":"string","nullable":true,"description":"Raw git commit message from CI when present"},"executedAt":{"type":"string","format":"date-time","description":"When the test was executed"}}},"ErrorResponse":{"type":"object","required":["status","error"],"properties":{"status":{"type":"string","enum":["FAILED"]},"error":{"type":"string","description":"Error message"}}}},"responses":{"BadRequest":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/actions/tests/{signature}":{"get":{"summary":"Get affected test executions","description":"Get execution details for a specific affected test (by signature) within a date range. Returns individual test execution records with action info. Results are paginated with cursor-based pagination using the `starting_after` and `ending_before` query parameters. To list executions for a single rule across all tests, use `GET /actions/{actionId}/tests` instead of the removed `action_id` query parameter.","operationId":"getAffectedTestExecutions","tags":["Actions"],"parameters":[{"$ref":"#/components/parameters/ProjectIdQuery"},{"name":"signature","in":"path","required":true,"description":"Test signature hash","schema":{"type":"string"}},{"$ref":"#/components/parameters/DateStartQuery"},{"$ref":"#/components/parameters/DateEndQuery"},{"name":"limit","in":"query","required":false,"description":"Maximum number of executions (1-50)","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"$ref":"#/components/parameters/StartingAfterQuery"},{"$ref":"#/components/parameters/EndingBeforeQuery"},{"name":"search","in":"query","required":false,"description":"Search by action name (case-insensitive)","schema":{"type":"string","maxLength":100}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AffectedTestExecutionsResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## Get affected test executions for an action

> List test executions where this rule/action was applied, within a date range. Same cursor pagination and filters as \`GET /actions/tests/{signature}\` except \`projectId\` is taken from the rule (after org ownership checks).

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Actions","description":"Manage test actions (rules) that automatically modify test behavior.\n\nActions allow you to:\n- **Skip** tests that match certain conditions\n- **Quarantine** flaky tests so their failures don't fail the run\n- **Tag** tests with custom labels for organization\n\nEach action has a **matcher** that defines which tests it applies to,\nbased on conditions like test title, file path, tags, git branch, etc."}],"servers":[{"url":"https://api.currents.dev/v1","description":"Production API"},{"url":"https://api-staging.currents.dev/v1","description":"Staging API"},{"url":"http://localhost:4000/v1","description":"Local development"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key authentication using Bearer token"}},"parameters":{"ActionIdPath":{"name":"actionId","in":"path","required":true,"description":"The action ID","schema":{"type":"string"}},"DateStartQuery":{"name":"date_start","in":"query","required":true,"description":"Start date in ISO 8601 format","schema":{"type":"string","format":"date-time"}},"DateEndQuery":{"name":"date_end","in":"query","required":true,"description":"End date in ISO 8601 format","schema":{"type":"string","format":"date-time"}},"StartingAfterQuery":{"name":"starting_after","in":"query","required":false,"description":"Cursor for pagination. Returns items after this cursor value.","schema":{"type":"string"}},"EndingBeforeQuery":{"name":"ending_before","in":"query","required":false,"description":"Cursor for pagination. Returns items before this cursor value.","schema":{"type":"string"}}},"schemas":{"AffectedTestExecutionsResponse":{"type":"object","required":["status","data"],"properties":{"status":{"type":"string","enum":["OK"]},"data":{"type":"object","required":["executions","has_more"],"properties":{"executions":{"type":"array","items":{"$ref":"#/components/schemas/AffectedTestExecution"}},"has_more":{"type":"boolean","description":"Whether more execution rows exist after this page"}}}}},"AffectedTestExecution":{"type":"object","required":["cursor","runId","instanceId","testId","specFile","title","signature","branch","commitSha","prTitle","prId","commitMessage","executedAt"],"properties":{"cursor":{"type":"string","description":"Test document id; pass as starting_after to fetch the next page"},"runId":{"type":"string","description":"Run ID"},"instanceId":{"type":"string","description":"Instance ID"},"testId":{"type":"string","description":"Test ID"},"specFile":{"type":"string","description":"Spec file path for this test"},"title":{"type":"string","description":"Test title"},"signature":{"type":"string","description":"Stable test signature"},"branch":{"type":"string","nullable":true,"description":"Git branch"},"commitSha":{"type":"string","nullable":true,"description":"Git commit SHA"},"prTitle":{"type":"string","nullable":true,"description":"Raw pull request title from CI when present"},"prId":{"type":"string","nullable":true,"description":"Raw pull request id from CI when present"},"commitMessage":{"type":"string","nullable":true,"description":"Raw git commit message from CI when present"},"executedAt":{"type":"string","format":"date-time","description":"When the test was executed"}}},"ErrorResponse":{"type":"object","required":["status","error"],"properties":{"status":{"type":"string","enum":["FAILED"]},"error":{"type":"string","description":"Error message"}}}},"responses":{"BadRequest":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/actions/{actionId}/tests":{"get":{"summary":"Get affected test executions for an action","description":"List test executions where this rule/action was applied, within a date range. Same cursor pagination and filters as `GET /actions/tests/{signature}` except `projectId` is taken from the rule (after org ownership checks).","operationId":"getAffectedTestExecutionsByAction","tags":["Actions"],"parameters":[{"$ref":"#/components/parameters/ActionIdPath"},{"$ref":"#/components/parameters/DateStartQuery"},{"$ref":"#/components/parameters/DateEndQuery"},{"name":"limit","in":"query","required":false,"description":"Maximum number of executions (1-50)","schema":{"type":"integer","minimum":1,"maximum":50,"default":25}},{"$ref":"#/components/parameters/StartingAfterQuery"},{"$ref":"#/components/parameters/EndingBeforeQuery"},{"name":"search","in":"query","required":false,"description":"Search by action name (case-insensitive)","schema":{"type":"string","maxLength":100}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AffectedTestExecutionsResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.currents.dev/api/resources/actions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
