Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Currents Dev Integrations API
version: 1.0.0
contact:
name: Currents Support
url: https://currents.dev
description: 'Operations tagged Integrations across 2 of this provider''s published API definitions: currents-dev-openapi.json, currents-dev-openapi.yml. Each path carries the servers of the definition it was published in.'
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: []
tags:
- name: Integrations
description: Manage third-party integrations such as Jira.
paths:
/projects/{projectId}/jira/issues:
post:
summary: Create Jira issue from a run test
description: Creates a Jira issue using the organization Jira integration, with title and description built from the specified run and test (same linking behavior as the dashboard). Identifies the Jira site via `jiraInstallationId` (shown in the dashboard as Installation ID). Requires a write-scoped API key. On 404, the `error` field indicates whether the Currents project, Jira installation, run, or test was not found.
operationId: createJiraIssueFromRunTest
security:
- BearerAuth: []
- OAuth2:
- issues:write
tags:
- Integrations
parameters:
- $ref: '#/components/parameters/ProjectIdPath'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateJiraIssueFromRunTestRequest'
responses:
'201':
description: Jira issue created and linked to the test
content:
application/json:
schema:
$ref: '#/components/schemas/CreateJiraIssueFromRunTestResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
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
/projects/{projectId}/jira/issues/{jiraIssueKey}/link:
post:
summary: Link existing Jira issue to a run test
description: 'Creates a link between an existing Jira issue (identified by `jiraIssueKey` in the path, e.g. PROJ-123) and the specified run and test. Same behavior as the dashboard link flow: resolves the test entity, builds the Currents issue title and Jira comment from the test (optionally prefixed with your `comment`), posts the comment on the Jira issue, and attaches the Jira ticket to the Currents issue. Identifies the Jira site via `jiraInstallationId` (Installation ID in the dashboard). `jiraIssueType` is stored on the ticket metadata (use the same value as when creating issues via the REST API, typically the issue type ID from issue type discovery). Requires a write-scoped API key. On 404, the `error` field indicates whether the Currents project, Jira installation, run, or test was not found.'
operationId: linkJiraIssueFromRunTest
security:
- BearerAuth: []
- OAuth2:
- issues:write
tags:
- Integrations
parameters:
- $ref: '#/components/parameters/ProjectIdPath'
- $ref: '#/components/parameters/JiraIssueKeyPath'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LinkJiraIssueFromRunTestRequest'
responses:
'200':
description: Jira issue linked to the test
content:
application/json:
schema:
$ref: '#/components/schemas/LinkJiraIssueFromRunTestResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
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
/integrations/jira/projects:
get:
summary: List Jira projects
description: Lists Jira projects available for the organization Jira integration (via Atlassian project search). Use returned project IDs as `jiraProjectId` when creating or linking Jira issues.
operationId: listJiraProjects
security:
- BearerAuth: []
- OAuth2:
- issues:write
tags:
- Integrations
parameters:
- $ref: '#/components/parameters/JiraInstallationIdQuery'
- $ref: '#/components/parameters/JiraDiscoverySearchQuery'
- $ref: '#/components/parameters/PageQuery'
- $ref: '#/components/parameters/JiraDiscoveryLimitQuery'
responses:
'200':
description: Jira projects returned successfully
content:
application/json:
schema:
$ref: '#/components/schemas/JiraProjectsDiscoveryResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
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
/integrations/jira/projects/{jiraProjectId}/issue-types:
get:
summary: List Jira issue types
description: Lists Jira issue types available for a Jira project and embeds custom fields required to create issues through the REST API.
operationId: listJiraIssueTypes
security:
- BearerAuth: []
- OAuth2:
- issues:write
tags:
- Integrations
parameters:
- $ref: '#/components/parameters/JiraProjectIdPath'
- $ref: '#/components/parameters/JiraInstallationIdQuery'
- $ref: '#/components/parameters/JiraDiscoverySearchQuery'
- $ref: '#/components/parameters/PageQuery'
- $ref: '#/components/parameters/JiraDiscoveryLimitQuery'
responses:
'200':
description: Jira issue types returned successfully
content:
application/json:
schema:
$ref: '#/components/schemas/JiraIssueTypesDiscoveryResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
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
components:
parameters:
ProjectIdPath:
name: projectId
in: path
required: true
description: The project ID
schema:
type: string
example: proj_abc123
JiraDiscoveryLimitQuery:
name: limit
in: query
required: false
description: Page size for Jira discovery list endpoints (default 50, max 100)
schema:
type: integer
minimum: 1
maximum: 100
default: 50
JiraInstallationIdQuery:
name: jira_installation_id
in: query
required: true
description: Atlassian Jira installation ID for the org integration (same as Installation ID in the dashboard)
schema:
type: string
minLength: 1
example: abc-123-atlassian-installation
JiraDiscoverySearchQuery:
name: search
in: query
required: false
description: Case-insensitive search filter for Jira metadata
schema:
type: string
example: bug
PageQuery:
name: page
in: query
required: false
description: Page number (0-indexed)
schema:
type: integer
minimum: 0
default: 0
JiraIssueKeyPath:
name: jiraIssueKey
in: path
required: true
description: Jira issue key to link (e.g. PROJ-123), as shown in Jira. Must be 1–255 characters after trimming. If missing, empty, or longer than 255 characters, the server responds with HTTP 400 and an `ErrorResponse`.
schema:
type: string
minLength: 1
maxLength: 255
JiraProjectIdPath:
name: jiraProjectId
in: path
required: true
description: 'Jira project ID (from project search or Jira). Must be 1–128 characters. If missing, empty, or longer than 128 characters, the server responds with HTTP 400 and an `ErrorResponse` (`status: FAILED`, `error` describing the validation failure).'
schema:
type: string
minLength: 1
maxLength: 128
example: '10000'
schemas:
LinkJiraIssueFromRunTestResponse:
type: object
required:
- status
- data
properties:
status:
type: string
enum:
- OK
data:
$ref: '#/components/schemas/JiraIssueFromRunTestResult'
JiraIssueTypeDiscovery:
type: object
required:
- id
- name
- description
- iconUrl
- projectId
- customFields
properties:
id:
type: string
description: Jira issue type ID used as jiraIssueType in create-issue body
example: '10001'
name:
type: string
description: Jira issue type name
example: Bug
description:
type:
- string
- 'null'
description: Jira issue type description
iconUrl:
type:
- string
- 'null'
description: Jira issue type icon URL
projectId:
type:
- string
- 'null'
description: Jira project ID for project-scoped issue types, or null for global issue types
customFields:
type: array
items:
$ref: '#/components/schemas/JiraCustomFieldDiscovery'
JiraIssueFromRunTestResult:
type: object
required:
- jiraIssueKey
- currentsIssueId
- jiraIssueUrl
- currentsIssueUrl
properties:
jiraIssueKey:
type: string
description: Jira issue key (e.g. PROJ-123)
currentsIssueId:
type: string
description: Currents issue record ID
jiraIssueUrl:
type:
- string
- 'null'
description: URL to the Jira issue in the linked Jira instance
currentsIssueUrl:
type: string
description: URL to the Currents dashboard issue modal for the linked test entity
JiraIssueTypesDiscoveryResponse:
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/JiraIssueTypeDiscovery'
count:
type: integer
description: Number of items in the current response
total:
type: integer
description: Total number of matching Jira issue types
nextPage:
oneOf:
- type: integer
- type: boolean
enum:
- false
description: Next page index (0-based), or false if there is no next page
JiraFieldType:
type: string
enum:
- TEXT
- SELECT
- MULTI_SELECT
- CHECKBOX
- LABELS
- NUMBER
- DATE
- DATETIME
- USER
- MULTI_USER
- UNSUPPORTED
ErrorResponse:
type: object
required:
- status
- error
properties:
status:
type: string
enum:
- FAILED
error:
type: string
description: Error message
code:
type: string
description: Stable machine-readable discriminator, present on refusals a client is expected to branch on (for example `AI_CONSENT_REQUIRED`). The `error` text is free-form; branch on `code`.
candidates:
type: array
description: 'With `code: ambiguous_target`: the runs, spec files or tests the request matched. Send one of their IDs.'
items:
type: object
properties:
runId:
type: string
ciBuildId:
type: string
instanceId:
type: string
groupId:
type: string
spec:
type: string
machineId:
type:
- string
- 'null'
testId:
type: string
title:
type: array
items:
type: string
LinkJiraIssueFromRunTestRequest:
type: object
required:
- runId
- testId
- jiraInstallationId
- jiraProjectId
- jiraIssueType
properties:
runId:
type: string
minLength: 1
description: Currents run ID containing the test
testId:
type: string
minLength: 1
description: Test ID within the run (client test id)
jiraInstallationId:
type: string
minLength: 1
description: Atlassian Jira installation ID for the org integration (same as Installation ID in the dashboard)
jiraProjectId:
type: string
minLength: 1
description: Jira project ID for the linked issue
jiraIssueType:
type: string
minLength: 1
description: Jira issue type identifier stored on the Currents ticket (same as `jiraIssueType` when creating issues; use issue type discovery when unsure)
comment:
type: string
description: Optional text prepended to the Jira comment and Currents issue description before the automated test context (when `includeContextInComment` is true)
includeContextInComment:
type: boolean
default: true
description: When true (default), appends the same automated test context used when creating Jira issues from a run test. When false, `comment` must be non-empty and is used alone for the Jira comment and issue description.
allOf:
- if:
properties:
includeContextInComment:
const: false
required:
- includeContextInComment
then:
required:
- comment
properties:
comment:
type: string
minLength: 1
description: Required when `includeContextInComment` is false; used alone for the Jira comment and issue description
JiraProjectDiscovery:
type: object
required:
- id
- key
- name
- description
- avatarUrl
properties:
id:
type: string
description: Jira project ID used as jiraProjectId in create-issue body
example: '10000'
key:
type: string
description: Jira project key
example: ENG
name:
type: string
description: Jira project name
example: Engineering
description:
type:
- string
- 'null'
description: Jira project description
avatarUrl:
type:
- string
- 'null'
description: Jira project avatar URL
CreateJiraIssueFromRunTestResponse:
type: object
required:
- status
- data
properties:
status:
type: string
enum:
- OK
data:
$ref: '#/components/schemas/JiraIssueFromRunTestResult'
JiraProjectsDiscoveryResponse:
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/JiraProjectDiscovery'
count:
type: integer
description: Number of items in the current response
total:
type: integer
description: Total number of matching Jira projects
nextPage:
oneOf:
- type: integer
- type: boolean
enum:
- false
description: Next page index (0-based), or false if there is no next page
CreateJiraIssueFromRunTestRequest:
type: object
required:
- runId
- testId
- jiraInstallationId
- jiraProjectId
- jiraIssueType
properties:
runId:
type: string
minLength: 1
description: Currents run ID containing the test
testId:
type: string
minLength: 1
description: Test ID within the run (client test id)
jiraInstallationId:
type: string
minLength: 1
description: Atlassian Jira installation ID for the org integration (same as Installation ID in the dashboard)
jiraProjectId:
type: string
minLength: 1
description: Jira project ID in which to create the issue
jiraIssueType:
type: string
minLength: 1
description: Jira issue type ID
customFields:
type: array
items:
type: object
required:
- fieldId
- value
properties:
fieldId:
type: string
minLength: 1
description: Jira field ID (matches `fieldId` from issue type discovery)
value:
type: string
minLength: 1
description: String representation for the field value (encoding depends on field type; see Jira custom field docs)
description: Optional Jira custom fields
JiraCustomFieldDiscovery:
type: object
required:
- fieldId
- key
- name
- required
- fieldType
- allowedValues
- originalType
properties:
fieldId:
type: string
description: Jira field ID to use in customFields.fieldId
example: customfield_10010
key:
type: string
example: customfield_10010
name:
type: string
example: Severity
required:
type: boolean
fieldType:
$ref: '#/components/schemas/JiraFieldType'
allowedValues:
type: array
items:
type: object
required:
- id
- name
properties:
id:
type: string
name:
type: string
originalType:
type:
- string
- 'null'
description: Original Jira schema type
responses:
Conflict:
description: Request could not be completed due to a conflict
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
status: FAILED
error: Conflict
Forbidden:
description: 'The credential authenticated but is not permitted to use this endpoint. Five refusals share the status: a `read` API key on an endpoint that writes, an OAuth token that was not granted the scope the endpoint needs (`insufficient_scope`), an OAuth token that was granted it but whose holder no longer has a role permitting it (`insufficient_role`), an OAuth token on an endpoint that accepts an API key and nothing else (`api_key_required`), and an API key on an endpoint that answers for a user (`user_credential_required`). Discriminate on `code` rather than on the message, which is free-form. The first refusal predates the codes and sets none. Only `insufficient_scope` carries the challenge header, because it is the only one a client can act on by re-authorizing.'
headers:
WWW-Authenticate:
description: 'Present on the `insufficient_scope` refusal only, naming the scope to re-authorize for (RFC 6750 3.1): `Bearer error="insufficient_scope", scope="webhooks:read"`. Absent on `insufficient_role`, where the scope is already granted, and on `api_key_required` and `user_credential_required`, where no scope would help.'
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
examples:
apiKeyIsReadOnly:
summary: A read API key on an endpoint that writes
value:
status: FAILED
error: 'Insufficient permissions: write access required'
scopeNotGranted:
summary: An OAuth token missing the endpoint's scope
value:
status: FAILED
error: 'Insufficient permissions: this endpoint requires the webhooks:read scope'
code: insufficient_scope
scopeAboveRole:
summary: An OAuth token holding the scope, whose holder was since demoted
value:
status: FAILED
error: 'Insufficient permissions: the webhooks:write scope requires the admin role in this organization'
code: insufficient_role
apiKeyRequired:
summary: An OAuth token on an endpoint that takes an API key
value:
status: FAILED
error: This endpoint accepts an API key, not an OAuth access token
code: api_key_required
userCredentialRequired:
summary: An API key on an endpoint that answers for a user
value:
status: FAILED
error: This endpoint requires an OAuth access token or a personal access token; an API key belongs to an organization, not a user
code: user_credential_required
Unauthorized:
description: Authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
status: FAILED
error: Invalid authentication credentials
InternalServerError:
description: Unexpected server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
status: FAILED
error: Internal server error
BadRequest:
description: Invalid request parameters
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
status: FAILED
error: 'Invalid request body: name is required'
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
status: FAILED
error: Not found
TooManyRequests:
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
status: FAILED
error: Too many requests
securitySchemes:
RecordKey:
type: apiKey
in: header
name: x-currents-key
description: An organization's record key, the one a reporter sends. Accepted only by the two attachment routes under `/runs`, `POST /runs/{runId}/context-links`, `POST /sessions`, `POST /sessions/{sessionId}/attachments` and, for a session, `POST /share`, so a CI job can attach files, link its failed and flaky tests, record a session and share it with the key it already has.
BearerAuth:
type: http
scheme: bearer
description: 'An organization API key, sent as `Authorization: Bearer <key>`. A key carries one scope for the whole API: a `read` key reaches the GET endpoints, a `write` key reaches all of them. A `crnts_pat_` personal access token is accepted as a Bearer while its owner remains an eligible administrator in its active organization. Each operation requires the corresponding scope stored on that token.'
OAuth2:
type: oauth2
description: 'An access token from the Currents authorization server, for an application acting as a user in one organization. Unlike an API key it is confined per endpoint: the operation lists the scope it needs, and a token that was not granted that scope gets 403.
**The endpoints below are production''s.** They are written out so this specification can be exercised against production, and they are wrong for every other deployment — a token minted by `id.currents.dev` is refused by a staging or on-premise API, whose `OAUTH_ISSUER` and `OAUTH_API_AUDIENCE` are its own. Against anything but production, and in a client generated from this document, discover them instead: `GET {api origin}/.well-known/oauth-protected-resource`, then the `authorization_servers[0]` document.
**The audience named here is the REST API''s.** `POST /mcp` is a second resource server on the same origin, identified by `{api origin}/mcp` and described by its own document at `/.well-known/oauth-protected-resource/mcp`. Every operation below refuses a token minted for it, and it refuses every token minted for these, so a client of this specification wants the audience above and not that one.'
flows:
authorizationCode:
authorizationUrl: https://id.currents.dev/api/auth/oauth2/authorize
tokenUrl: https://id.currents.dev/api/auth/oauth2/token
refreshUrl: https://id.currents.dev/api/auth/oauth2/token
scopes:
projects:read: See which projects exist and their names
projects:write: Change project configuration, including a project's tags
results:read: See runs, specs and failure detail — errors, stacks and artifacts
analytics:read: 'See aggregate metrics: flake and failure rates, error counts, durations and trends'
actions:read: See quarantine and skip rules, and the tests they affect
actions:write: Create, edit, enable, disable and archive quarantine and skip rules
issues:write: Create and link issues in a connected issue tracker, and list its projects and issue types
runs:write: Cancel and reset runs, and permanently delete runs and their artifacts
webhooks:read: See webhook configuration, including destination URLs and headers
webhooks:write: Create, edit and delete webhooks
shares:write: Create public links to test results that anyone with the link can open until they expire
x-refined-from:
- currents-dev-openapi.json
- currents-dev-openapi.yml