> For the complete documentation index, see [llms.txt](https://docs.currents.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.currents.dev/api/resources/projects.md).

# Projects

Manage and query projects in your organization.

Projects are the top-level containers for test runs, specs, and test results. Each project has a unique project ID and can be configured with various settings.

## List projects

> Get all projects for your organization with optional pagination

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Projects","description":"Manage and query projects in your organization.\n\nProjects are the top-level containers for test runs, specs, and test results.\nEach project has a unique project ID and can be configured with various settings."}],"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":{"LimitQuery":{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return (default: 10, max: 50)","schema":{"type":"integer","minimum":1,"maximum":50,"default":10}},"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":{"ProjectsListResponse":{"type":"object","required":["status","has_more","data"],"properties":{"status":{"type":"string","enum":["OK"]},"has_more":{"type":"boolean","description":"Whether there are more items to fetch"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ProjectWithCursor"}}}},"ProjectWithCursor":{"allOf":[{"$ref":"#/components/schemas/Project"},{"type":"object","properties":{"cursor":{"type":"string","description":"Cursor for pagination"}}}]},"Project":{"type":"object","required":["projectId","name","createdAt"],"properties":{"projectId":{"type":"string","description":"Unique identifier for the project"},"name":{"type":"string","description":"Human-readable name for the project"},"createdAt":{"type":"string","format":"date-time","description":"When the project was created"},"failFast":{"type":"boolean","nullable":true,"description":"Whether fail-fast is enabled for this project"},"inactivityTimeoutSeconds":{"type":"integer","nullable":true,"description":"Timeout in seconds after which inactive runs are marked as timed out"},"defaultBranchName":{"type":"string","nullable":true,"description":"Default branch name for the project"}}},"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"}}}}}},"paths":{"/projects":{"get":{"summary":"List projects","description":"Get all projects for your organization with optional pagination","operationId":"listProjects","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/LimitQuery"},{"$ref":"#/components/parameters/StartingAfterQuery"},{"$ref":"#/components/parameters/EndingBeforeQuery"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectsListResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}}}}
```

## Get project

> Get a single project by ID

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Projects","description":"Manage and query projects in your organization.\n\nProjects are the top-level containers for test runs, specs, and test results.\nEach project has a unique project ID and can be configured with various settings."}],"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":{"ProjectIdPath":{"name":"projectId","in":"path","required":true,"description":"The project ID","schema":{"type":"string"}}},"schemas":{"ProjectResponse":{"type":"object","required":["status","data"],"properties":{"status":{"type":"string","enum":["OK"]},"data":{"$ref":"#/components/schemas/Project"}}},"Project":{"type":"object","required":["projectId","name","createdAt"],"properties":{"projectId":{"type":"string","description":"Unique identifier for the project"},"name":{"type":"string","description":"Human-readable name for the project"},"createdAt":{"type":"string","format":"date-time","description":"When the project was created"},"failFast":{"type":"boolean","nullable":true,"description":"Whether fail-fast is enabled for this project"},"inactivityTimeoutSeconds":{"type":"integer","nullable":true,"description":"Timeout in seconds after which inactive runs are marked as timed out"},"defaultBranchName":{"type":"string","nullable":true,"description":"Default branch name for the project"}}},"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":{"/projects/{projectId}":{"get":{"summary":"Get project","description":"Get a single project by ID","operationId":"getProject","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/ProjectIdPath"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## List project runs

> Get all runs for a project with optional pagination and filtering. Supports filtering by branch, tags, environment, status, completion state, date range, search text, author, and pull request id (pr\_id maps to meta.pr.id).

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Projects","description":"Manage and query projects in your organization.\n\nProjects are the top-level containers for test runs, specs, and test results.\nEach project has a unique project ID and can be configured with various settings."},{"name":"Runs","description":"Query and manage test runs.\n\nA run represents a single execution of your test suite. Runs contain spec files\nwhich are executed across multiple instances. You can query run details, cancel\nruns, reset failed specs, and delete runs.\n\nPer-test outcome counters on specs (`results.stats`) use the `RecordedTestOutcome` vocabulary—see **components/schemas** for how **pending** and **skipped** differ from **failures**."}],"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":{"ProjectIdPath":{"name":"projectId","in":"path","required":true,"description":"The project ID","schema":{"type":"string"}},"LimitQuery":{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return (default: 10, max: 50)","schema":{"type":"integer","minimum":1,"maximum":50,"default":10}},"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"}},"TagsQuery":{"name":"tags[]","in":"query","required":false,"description":"Filter by tags (can be specified multiple times using bracket notation, e.g., tags[]=value1&tags[]=value2)","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},"BranchesQuery":{"name":"branches[]","in":"query","required":false,"description":"Filter by git branch. Use trailing `*` for prefix match (e.g. `release/*`). Max 250 characters per value.","schema":{"type":"array","items":{"$ref":"#/components/schemas/BranchFilterQueryValue"}},"style":"form","explode":true},"AuthorsQuery":{"name":"authors[]","in":"query","required":false,"description":"Filter by git authors (can be specified multiple times using bracket notation, e.g., authors[]=author1&authors[]=author2)","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},"EnvironmentsQuery":{"name":"environments[]","in":"query","required":false,"description":"Filter by environment (can be specified multiple times using bracket notation, e.g., environments[]=staging&environments[]=production)","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},"RunFeedBranchQuery":{"name":"branch","in":"query","required":false,"deprecated":true,"description":"Deprecated. Use branches[] instead. Filter runs by git branch name (single branch). Supports a trailing `*` for prefix search (e.g., `release/*`). Branch value is limited to 250 characters (exact or wildcard).","schema":{"$ref":"#/components/schemas/BranchFilterQueryValue"}},"RunFeedTagQuery":{"name":"tag","in":"query","required":false,"deprecated":true,"description":"Deprecated. Use tags[] instead. Filter runs by tags (can be specified multiple times). Use tag_operator to control matching behavior.","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},"TagOperatorQuery":{"name":"tag_operator","in":"query","required":false,"description":"Logical operator for tag filtering. AND requires all tags to be present (default), OR requires any tag to be present.","schema":{"type":"string","enum":["AND","OR"],"default":"AND"}},"RunFeedSearchQuery":{"name":"search","in":"query","required":false,"description":"Search runs by ciBuildId or commit message. Case-insensitive.","schema":{"type":"string","maxLength":200}},"RunFeedPrIdQuery":{"name":"pr_id","in":"query","required":false,"description":"Filter runs by normalized pull request id (stored as meta.pr.id). Printable ASCII only, max 128 characters.","schema":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[!-~]+$"}},"RunFeedAuthorQuery":{"name":"author","in":"query","required":false,"deprecated":true,"description":"Deprecated. Use authors[] instead. Filter runs by git commit author name (can be specified multiple times).","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},"RunStatusQuery":{"name":"status","in":"query","required":false,"description":"Filter runs by status (can be specified multiple times). PASSED: all tests passed, FAILED: some tests failed, RUNNING: run is in progress and passing, FAILING: run is in progress but has failures.","schema":{"type":"array","items":{"type":"string","enum":["PASSED","FAILED","RUNNING","FAILING"]}},"style":"form","explode":true},"RunCompletionStateQuery":{"name":"completion_state","in":"query","required":false,"description":"Filter runs by completion state (can be specified multiple times). COMPLETE: run finished normally, IN_PROGRESS: run is still executing, CANCELED: run was canceled, TIMEOUT: run timed out.","schema":{"type":"array","items":{"type":"string","enum":["COMPLETE","IN_PROGRESS","CANCELED","TIMEOUT"]}},"style":"form","explode":true},"OptionalDateStartQuery":{"name":"date_start","in":"query","required":false,"description":"Filter runs created on or after this date (ISO 8601 format).","schema":{"type":"string","format":"date-time"}},"OptionalDateEndQuery":{"name":"date_end","in":"query","required":false,"description":"Filter runs created before this date (ISO 8601 format).","schema":{"type":"string","format":"date-time"}}},"schemas":{"BranchFilterQueryValue":{"description":"Branch filter value: an exact branch name, or a trailing `*` for prefix match (e.g. `release/*`). Max 250 characters.","oneOf":[{"type":"string","description":"Exact branch name (must not contain `*` or spaces).","pattern":"^[!-)+-~]+$","maxLength":250},{"type":"string","description":"Prefix match: branch prefix followed by `*`.","pattern":"^[!-)+-~]+\\*$","maxLength":250}]},"RunsListResponse":{"type":"object","required":["status","has_more","data"],"properties":{"status":{"type":"string","enum":["OK"]},"has_more":{"type":"boolean","description":"Whether there are more items to fetch"},"data":{"type":"array","items":{"$ref":"#/components/schemas/RunFeedItem"}}}},"RunFeedItem":{"allOf":[{"type":"object","properties":{"runId":{"type":"string"},"projectId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"durationMs":{"type":"integer","nullable":true},"tags":{"type":"array","items":{"type":"string"}},"environments":{"type":"array","items":{"type":"string"},"nullable":true},"previousRunId":{"type":"string","nullable":true},"cursor":{"type":"string"},"timeout":{"type":"object","properties":{"isTimeout":{"type":"boolean"},"timeoutValueMs":{"type":"integer","nullable":true}}},"cancellation":{"type":"object","nullable":true},"groups":{"type":"array","items":{"$ref":"#/components/schemas/RunGroup"}},"meta":{"$ref":"#/components/schemas/RunMeta"},"completionState":{"type":"string"},"status":{"type":"string"}}}]},"RunGroup":{"type":"object","properties":{"groupId":{"type":"string"},"platform":{"type":"object","properties":{"osName":{"type":"string"},"osVersion":{"type":"string"},"browserName":{"type":"string"},"browserVersion":{"type":"string"}}},"tags":{"type":"array","items":{"type":"string"}},"environment":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time","nullable":true},"coverageEnabled":{"type":"boolean"},"durationMs":{"type":"integer"},"specCount":{"type":"integer"},"instances":{"type":"object","properties":{"overall":{"type":"integer"},"claimed":{"type":"integer"},"complete":{"type":"integer"},"passes":{"type":"integer"},"failures":{"type":"integer"}}},"tests":{"type":"object","description":"Test counts for this group. Use `total` (scheduled suite size) and `recorded` (tests with a reported outcome so far). `tests` and `overall` are deprecated aliases.","properties":{"total":{"type":"integer","description":"Total tests scheduled/expected in this group, including tests still running or not yet started."},"recorded":{"type":"integer","description":"Tests in this group that have reported an outcome so far (passes + failures + pending + skipped). Less than or equal to `total` while the group is in progress."},"tests":{"type":"integer","deprecated":true,"description":"Deprecated alias of `total` (scheduled suite size). Use `total`."},"overall":{"type":"integer","deprecated":true,"description":"Deprecated alias of `recorded`. Despite the name this is NOT the suite total — use `recorded` for the reported-outcome count, or `total` for the suite size."},"passes":{"type":"integer"},"failures":{"type":"integer"},"pending":{"type":"integer","description":"**pending** outcomes (intentional skips)."},"retries":{"type":"integer"},"skipped":{"type":"integer","description":"**skipped** outcomes (separate from `failures` here; see schema for Tests Explorer difference)."},"flaky":{"type":"integer"}}}}},"RunMeta":{"type":"object","properties":{"ciBuildId":{"type":"string","description":"CI build identifier"},"pr":{"type":"object","nullable":true,"description":"Normalized pull request metadata when the run is associated with a PR","properties":{"id":{"type":"string","nullable":true},"link":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"source":{"type":"string","nullable":true},"destination":{"type":"string","nullable":true}}},"commit":{"type":"object","properties":{"sha":{"type":"string"},"branch":{"type":"string"},"authorName":{"type":"string"},"authorEmail":{"type":"string"},"message":{"type":"string"},"remoteOrigin":{"type":"string"}}},"framework":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"}}}}},"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":{"/projects/{projectId}/runs":{"get":{"summary":"List project runs","description":"Get all runs for a project with optional pagination and filtering. Supports filtering by branch, tags, environment, status, completion state, date range, search text, author, and pull request id (pr_id maps to meta.pr.id).","operationId":"listProjectRuns","tags":["Projects","Runs"],"parameters":[{"$ref":"#/components/parameters/ProjectIdPath"},{"$ref":"#/components/parameters/LimitQuery"},{"$ref":"#/components/parameters/StartingAfterQuery"},{"$ref":"#/components/parameters/EndingBeforeQuery"},{"$ref":"#/components/parameters/TagsQuery"},{"$ref":"#/components/parameters/BranchesQuery"},{"$ref":"#/components/parameters/AuthorsQuery"},{"$ref":"#/components/parameters/EnvironmentsQuery"},{"$ref":"#/components/parameters/RunFeedBranchQuery"},{"$ref":"#/components/parameters/RunFeedTagQuery"},{"$ref":"#/components/parameters/TagOperatorQuery"},{"$ref":"#/components/parameters/RunFeedSearchQuery"},{"$ref":"#/components/parameters/RunFeedPrIdQuery"},{"$ref":"#/components/parameters/RunFeedAuthorQuery"},{"$ref":"#/components/parameters/RunStatusQuery"},{"$ref":"#/components/parameters/RunCompletionStateQuery"},{"$ref":"#/components/parameters/OptionalDateStartQuery"},{"$ref":"#/components/parameters/OptionalDateEndQuery"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunsListResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## List pull requests

> Lists pull requests for this project together with summarized run activity. Each result includes rollup stats for the PR, its most recent run, and an optional preview of additional runs (\`runs\_per\_pr\`: default 1, max 10). Optional filters narrow the list by branches\[], tags\[], authors\[], or run status; the status shown corresponds to each pull request’s latest run that matches your filters. Branch values may end with \`\*\` for a prefix match. Pagination uses opaque tokens: advance with \`starting\_after\`, go back with \`ending\_before\`; use the returned \`cursor\` from each item as the token and keep the same filter set across pages. Sending both cursor parameters at once is not supported. Because new runs can arrive while you page, a pull request can occasionally move between pages or appear twice in sequence—repeat the same filters on every request so results stay consistent.

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Projects","description":"Manage and query projects in your organization.\n\nProjects are the top-level containers for test runs, specs, and test results.\nEach project has a unique project ID and can be configured with various settings."},{"name":"Runs","description":"Query and manage test runs.\n\nA run represents a single execution of your test suite. Runs contain spec files\nwhich are executed across multiple instances. You can query run details, cancel\nruns, reset failed specs, and delete runs.\n\nPer-test outcome counters on specs (`results.stats`) use the `RecordedTestOutcome` vocabulary—see **components/schemas** for how **pending** and **skipped** differ from **failures**."}],"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":{"ProjectIdPath":{"name":"projectId","in":"path","required":true,"description":"The project ID","schema":{"type":"string"}},"LimitQuery":{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return (default: 10, max: 50)","schema":{"type":"integer","minimum":1,"maximum":50,"default":10}},"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"}},"PullRequestRunsPerPrQuery":{"name":"runs_per_pr","in":"query","required":false,"description":"How many most recent runs to include in each card’s `timelinePreview` (does not cap total stats).","schema":{"type":"integer","minimum":1,"maximum":10,"default":1}},"TagsQuery":{"name":"tags[]","in":"query","required":false,"description":"Filter by tags (can be specified multiple times using bracket notation, e.g., tags[]=value1&tags[]=value2)","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},"BranchesQuery":{"name":"branches[]","in":"query","required":false,"description":"Filter by git branch. Use trailing `*` for prefix match (e.g. `release/*`). Max 250 characters per value.","schema":{"type":"array","items":{"$ref":"#/components/schemas/BranchFilterQueryValue"}},"style":"form","explode":true},"AuthorsGlobQuery":{"name":"authors[]","in":"query","required":false,"description":"Filter by git author name. Use trailing `*` for prefix match (e.g. `Adam*`). May contain spaces. Max 250 characters per value.","schema":{"type":"array","items":{"$ref":"#/components/schemas/AuthorGlobFilterQueryValue"}},"style":"form","explode":true},"TagOperatorQuery":{"name":"tag_operator","in":"query","required":false,"description":"Logical operator for tag filtering. AND requires all tags to be present (default), OR requires any tag to be present.","schema":{"type":"string","enum":["AND","OR"],"default":"AND"}},"RunStatusQuery":{"name":"status","in":"query","required":false,"description":"Filter runs by status (can be specified multiple times). PASSED: all tests passed, FAILED: some tests failed, RUNNING: run is in progress and passing, FAILING: run is in progress but has failures.","schema":{"type":"array","items":{"type":"string","enum":["PASSED","FAILED","RUNNING","FAILING"]}},"style":"form","explode":true}},"schemas":{"BranchFilterQueryValue":{"description":"Branch filter value: an exact branch name, or a trailing `*` for prefix match (e.g. `release/*`). Max 250 characters.","oneOf":[{"type":"string","description":"Exact branch name (must not contain `*` or spaces).","pattern":"^[!-)+-~]+$","maxLength":250},{"type":"string","description":"Prefix match: branch prefix followed by `*`.","pattern":"^[!-)+-~]+\\*$","maxLength":250}]},"AuthorGlobFilterQueryValue":{"description":"Author name filter value: an exact name, or a trailing `*` for prefix match (e.g. `Adam*`). May contain spaces. Max 250 characters.","oneOf":[{"type":"string","description":"Exact author name (must not contain `*`).","pattern":"^[ -)+-~]+$","maxLength":250},{"type":"string","description":"Prefix match: name prefix followed by `*`.","pattern":"^[ -)+-~]+\\*$","maxLength":250}]},"PullRequestsListResponse":{"type":"object","required":["status","has_more","data"],"properties":{"status":{"type":"string","enum":["OK"]},"has_more":{"type":"boolean","description":"Whether more PR rows exist after this page"},"data":{"type":"array","items":{"$ref":"#/components/schemas/PullRequestCard"}}}},"PullRequestCard":{"type":"object","required":["pr","stats","latestRun","timelinePreview","hasMoreRuns","cursor"],"properties":{"pr":{"type":"object","required":["id"],"properties":{"id":{"type":"string","description":"Canonical pull request id (`meta.pr.id`)"},"prNumber":{"type":"string","nullable":true,"description":"Numeric PR/MR number extracted from the canonical id (e.g. \"42\" from \"github:github.com/org/repo#42\")"},"link":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"source":{"type":"string","nullable":true},"destination":{"type":"string","nullable":true}}},"stats":{"$ref":"#/components/schemas/PullRequestStats"},"latestRun":{"$ref":"#/components/schemas/RunFeedItem"},"timelinePreview":{"type":"array","description":"Most recent runs for this PR (newest first), up to `runs_per_pr` from the request (default 1, max 10)","items":{"$ref":"#/components/schemas/RunFeedItem"}},"hasMoreRuns":{"type":"boolean","description":"True when more runs exist for this PR than returned in `timelinePreview`"},"cursor":{"type":"string","description":"Opaque pagination cursor for this PR row; pass as `starting_after` for the next page"}}},"PullRequestStats":{"type":"object","required":["total","passed","failed","running","failing"],"properties":{"total":{"type":"integer","description":"Number of runs grouped under this pull request"},"passed":{"type":"integer","description":"Runs with PASSED status"},"failed":{"type":"integer","description":"Runs with FAILED status"},"running":{"type":"integer","description":"Runs with RUNNING status"},"failing":{"type":"integer","description":"Runs with FAILING status"}}},"RunFeedItem":{"allOf":[{"type":"object","properties":{"runId":{"type":"string"},"projectId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"durationMs":{"type":"integer","nullable":true},"tags":{"type":"array","items":{"type":"string"}},"environments":{"type":"array","items":{"type":"string"},"nullable":true},"previousRunId":{"type":"string","nullable":true},"cursor":{"type":"string"},"timeout":{"type":"object","properties":{"isTimeout":{"type":"boolean"},"timeoutValueMs":{"type":"integer","nullable":true}}},"cancellation":{"type":"object","nullable":true},"groups":{"type":"array","items":{"$ref":"#/components/schemas/RunGroup"}},"meta":{"$ref":"#/components/schemas/RunMeta"},"completionState":{"type":"string"},"status":{"type":"string"}}}]},"RunGroup":{"type":"object","properties":{"groupId":{"type":"string"},"platform":{"type":"object","properties":{"osName":{"type":"string"},"osVersion":{"type":"string"},"browserName":{"type":"string"},"browserVersion":{"type":"string"}}},"tags":{"type":"array","items":{"type":"string"}},"environment":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time","nullable":true},"coverageEnabled":{"type":"boolean"},"durationMs":{"type":"integer"},"specCount":{"type":"integer"},"instances":{"type":"object","properties":{"overall":{"type":"integer"},"claimed":{"type":"integer"},"complete":{"type":"integer"},"passes":{"type":"integer"},"failures":{"type":"integer"}}},"tests":{"type":"object","description":"Test counts for this group. Use `total` (scheduled suite size) and `recorded` (tests with a reported outcome so far). `tests` and `overall` are deprecated aliases.","properties":{"total":{"type":"integer","description":"Total tests scheduled/expected in this group, including tests still running or not yet started."},"recorded":{"type":"integer","description":"Tests in this group that have reported an outcome so far (passes + failures + pending + skipped). Less than or equal to `total` while the group is in progress."},"tests":{"type":"integer","deprecated":true,"description":"Deprecated alias of `total` (scheduled suite size). Use `total`."},"overall":{"type":"integer","deprecated":true,"description":"Deprecated alias of `recorded`. Despite the name this is NOT the suite total — use `recorded` for the reported-outcome count, or `total` for the suite size."},"passes":{"type":"integer"},"failures":{"type":"integer"},"pending":{"type":"integer","description":"**pending** outcomes (intentional skips)."},"retries":{"type":"integer"},"skipped":{"type":"integer","description":"**skipped** outcomes (separate from `failures` here; see schema for Tests Explorer difference)."},"flaky":{"type":"integer"}}}}},"RunMeta":{"type":"object","properties":{"ciBuildId":{"type":"string","description":"CI build identifier"},"pr":{"type":"object","nullable":true,"description":"Normalized pull request metadata when the run is associated with a PR","properties":{"id":{"type":"string","nullable":true},"link":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"source":{"type":"string","nullable":true},"destination":{"type":"string","nullable":true}}},"commit":{"type":"object","properties":{"sha":{"type":"string"},"branch":{"type":"string"},"authorName":{"type":"string"},"authorEmail":{"type":"string"},"message":{"type":"string"},"remoteOrigin":{"type":"string"}}},"framework":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"}}}}},"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":{"/projects/{projectId}/pull-requests":{"get":{"summary":"List pull requests","description":"Lists pull requests for this project together with summarized run activity. Each result includes rollup stats for the PR, its most recent run, and an optional preview of additional runs (`runs_per_pr`: default 1, max 10). Optional filters narrow the list by branches[], tags[], authors[], or run status; the status shown corresponds to each pull request’s latest run that matches your filters. Branch values may end with `*` for a prefix match. Pagination uses opaque tokens: advance with `starting_after`, go back with `ending_before`; use the returned `cursor` from each item as the token and keep the same filter set across pages. Sending both cursor parameters at once is not supported. Because new runs can arrive while you page, a pull request can occasionally move between pages or appear twice in sequence—repeat the same filters on every request so results stay consistent.","operationId":"listProjectPullRequests","tags":["Projects","Runs"],"parameters":[{"$ref":"#/components/parameters/ProjectIdPath"},{"$ref":"#/components/parameters/LimitQuery"},{"$ref":"#/components/parameters/StartingAfterQuery"},{"$ref":"#/components/parameters/EndingBeforeQuery"},{"$ref":"#/components/parameters/PullRequestRunsPerPrQuery"},{"$ref":"#/components/parameters/TagsQuery"},{"$ref":"#/components/parameters/BranchesQuery"},{"$ref":"#/components/parameters/AuthorsGlobQuery"},{"$ref":"#/components/parameters/TagOperatorQuery"},{"$ref":"#/components/parameters/RunStatusQuery"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PullRequestsListResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## Get project insights

> Get aggregated run and test metrics for a project within a date range

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Projects","description":"Manage and query projects in your organization.\n\nProjects are the top-level containers for test runs, specs, and test results.\nEach project has a unique project ID and can be configured with various settings."}],"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":{"ProjectIdPath":{"name":"projectId","in":"path","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"}},"ResolutionQuery":{"name":"resolution","in":"query","required":false,"description":"Time resolution for histogram data","schema":{"type":"string","enum":["1d","1w"],"default":"1d"}},"TagsQuery":{"name":"tags[]","in":"query","required":false,"description":"Filter by tags (can be specified multiple times using bracket notation, e.g., tags[]=value1&tags[]=value2)","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},"BranchesQuery":{"name":"branches[]","in":"query","required":false,"description":"Filter by git branch. Use trailing `*` for prefix match (e.g. `release/*`). Max 250 characters per value.","schema":{"type":"array","items":{"$ref":"#/components/schemas/BranchFilterQueryValue"}},"style":"form","explode":true},"GroupsQuery":{"name":"groups[]","in":"query","required":false,"description":"Filter by groups (can be specified multiple times using bracket notation, e.g., groups[]=group1&groups[]=group2)","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},"AuthorsQuery":{"name":"authors[]","in":"query","required":false,"description":"Filter by git authors (can be specified multiple times using bracket notation, e.g., authors[]=author1&authors[]=author2)","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true}},"schemas":{"BranchFilterQueryValue":{"description":"Branch filter value: an exact branch name, or a trailing `*` for prefix match (e.g. `release/*`). Max 250 characters.","oneOf":[{"type":"string","description":"Exact branch name (must not contain `*` or spaces).","pattern":"^[!-)+-~]+$","maxLength":250},{"type":"string","description":"Prefix match: branch prefix followed by `*`.","pattern":"^[!-)+-~]+\\*$","maxLength":250}]},"ProjectInsightsResponse":{"type":"object","required":["status","data"],"properties":{"status":{"type":"string","enum":["OK"]},"data":{"type":"object","properties":{"projectId":{"type":"string"},"orgId":{"type":"string"},"dateStart":{"type":"string","format":"date-time"},"dateEnd":{"type":"string","format":"date-time"},"resolution":{"type":"string"},"results":{"type":"object","properties":{"overall":{"type":"object","properties":{"runs":{"$ref":"#/components/schemas/RunMetrics"},"tests":{"$ref":"#/components/schemas/TestMetrics"}}},"timeline":{"type":"array","items":{"type":"object","additionalProperties":{"type":"object","properties":{"runs":{"$ref":"#/components/schemas/RunMetrics"},"tests":{"$ref":"#/components/schemas/TestMetrics"}}}}}}}}}}},"RunMetrics":{"type":"object","properties":{"total":{"type":"integer","description":"Total number of runs"},"cancelled":{"type":"integer","description":"Cancelled runs"},"timeouts":{"type":"integer","description":"Timed out runs"},"completed":{"type":"integer","description":"Fully completed runs"},"failed":{"type":"integer","description":"Failed runs"},"passed":{"type":"integer","description":"Passed runs"},"nonFullyReported":{"type":"integer","description":"Runs that did not fully report"},"avgDurationSeconds":{"type":"number","description":"Average run duration in seconds"},"avgSuccessRate":{"type":"number","description":"Average success rate (0-1)"}}},"TestMetrics":{"type":"object","properties":{"total":{"type":"integer","description":"Total test executions"},"failed":{"type":"integer","description":"Failed tests"},"passed":{"type":"integer","description":"Passed tests"},"pending":{"type":"integer","description":"**pending** outcomes (intentional skips). See `RecordedTestOutcome`."},"skipped":{"type":"integer","description":"**skipped** outcomes (runner skip / interrupted). See `RecordedTestOutcome`."},"flaky":{"type":"integer","description":"Flaky tests"}}},"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":{"/projects/{projectId}/insights":{"get":{"summary":"Get project insights","description":"Get aggregated run and test metrics for a project within a date range","operationId":"getProjectInsights","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/ProjectIdPath"},{"$ref":"#/components/parameters/DateStartQuery"},{"$ref":"#/components/parameters/DateEndQuery"},{"$ref":"#/components/parameters/ResolutionQuery"},{"$ref":"#/components/parameters/TagsQuery"},{"$ref":"#/components/parameters/BranchesQuery"},{"$ref":"#/components/parameters/GroupsQuery"},{"$ref":"#/components/parameters/AuthorsQuery"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectInsightsResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```

## List project terms for a single type

> Returns cursor-paginated terms for one kind (\`tag\`, \`branch\`, \`authorName\`, etc.). Rows are ordered by each term's last update time; use \`dir\` as \`asc\` or \`desc\` (default \`desc\`, most recently updated first). Page with \`starting\_after\` or \`ending\_before\` using the opaque \`cursor\` value from a returned item; do not send both cursors in one request. Reuse the same \`dir\`, \`limit\`, search filter, and path when requesting additional pages.

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Projects","description":"Manage and query projects in your organization.\n\nProjects are the top-level containers for test runs, specs, and test results.\nEach project has a unique project ID and can be configured with various settings."}],"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":{"ProjectIdPath":{"name":"projectId","in":"path","required":true,"description":"The project ID","schema":{"type":"string"}},"TermTypePath":{"name":"termType","in":"path","required":true,"description":"Term kind to list","schema":{"type":"string","enum":["tag","group","branch","authorName","authorEmail","framework","frameworkVersion","clientVersion","ann_type","ann_desc"]}},"TermsLimitQuery":{"name":"limit","in":"query","required":false,"description":"Maximum number of terms to return (default: 100, max: 100)","schema":{"type":"integer","minimum":1,"maximum":100,"default":100}},"SortDirectionQuery":{"name":"dir","in":"query","required":false,"description":"Sort direction: `desc` (default) or `asc`.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},"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"}},"TermsSearchQuery":{"name":"search","in":"query","required":false,"description":"Optional case-insensitive prefix filter on term values (up to 128 characters)","schema":{"type":"string","maxLength":128}}},"schemas":{"ProjectTermsListResponse":{"type":"object","required":["status","has_more","data"],"properties":{"status":{"type":"string","enum":["OK"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ProjectTermsTermItem"},"description":"Ordered term rows for the requested type"}}},"ProjectTermsTermItem":{"type":"object","required":["id","name","count","updated_at","cursor"],"properties":{"id":{"type":"string","description":"Unique identifier for this term"},"name":{"type":"string","description":"Term value"},"count":{"type":"integer","description":"Number of times this term was used"},"updated_at":{"type":"string","format":"date-time","nullable":true,"description":"Last time the term stats were updated"},"cursor":{"type":"string","description":"Opaque pagination token for this row. Pass as `starting_after` or `ending_before` on follow-up requests to fetch the next or previous page along the same sort order."}}},"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":{"/projects/{projectId}/terms/{termType}":{"get":{"summary":"List project terms for a single type","description":"Returns cursor-paginated terms for one kind (`tag`, `branch`, `authorName`, etc.). Rows are ordered by each term's last update time; use `dir` as `asc` or `desc` (default `desc`, most recently updated first). Page with `starting_after` or `ending_before` using the opaque `cursor` value from a returned item; do not send both cursors in one request. Reuse the same `dir`, `limit`, search filter, and path when requesting additional pages.","operationId":"listProjectTermsByType","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/ProjectIdPath"},{"$ref":"#/components/parameters/TermTypePath"},{"$ref":"#/components/parameters/TermsLimitQuery"},{"$ref":"#/components/parameters/SortDirectionQuery"},{"$ref":"#/components/parameters/StartingAfterQuery"},{"$ref":"#/components/parameters/EndingBeforeQuery"},{"$ref":"#/components/parameters/TermsSearchQuery"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectTermsListResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.currents.dev/api/resources/projects.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
