Trunk Merge Queue API

REST API to control the flake-aware parallel Merge Queue - submit, cancel, restart, and inspect pull requests; set impacted targets; create, get, update, and delete queues; and read merge-queue testing details and Prometheus metrics. Authenticated with the x-api-token header.

OpenAPI Specification

trunk-io-openapi.yml Raw ↑
openapi: 3.0.1
info:
  title: Trunk API
  description: >-
    HTTP REST API for the Trunk platform. Covers the Flaky Tests API (query
    test-case state, list quarantined / unhealthy / failing tests, link
    external tickets) and the Merge Queue API (control the flake-aware parallel
    merge queue and read its metrics). All requests are authenticated with an
    organization API token passed in the x-api-token header and return JSON.
  termsOfService: https://trunk.io/legal/terms
  contact:
    name: Trunk Support
    url: https://docs.trunk.io
  version: '1.0'
servers:
  - url: https://api.trunk.io/v1
    description: Trunk REST API
security:
  - ApiKeyAuth: []
tags:
  - name: Flaky Tests
    description: Query Flaky Tests state and link tickets.
  - name: Merge Queue
    description: Control the Trunk Merge Queue.
paths:
  /flaky-tests/get-test-details:
    post:
      operationId: getTestDetails
      tags:
        - Flaky Tests
      summary: Get the details of a test case
      description: >-
        Fetch detailed metadata for a single test case, including its current
        status, recent failure rates, most common failures, codeowners, and
        quarantine state.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - repo
                - org_url_slug
                - test_id
              properties:
                repo:
                  $ref: '#/components/schemas/Repo'
                org_url_slug:
                  type: string
                  description: Organization slug from Trunk settings.
                  example: my-trunk-org-slug
                test_id:
                  type: string
                  format: uuid
                  description: Stable unique test-case identifier.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  test:
                    $ref: '#/components/schemas/TestDetail'
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '404': { $ref: '#/components/responses/NotFound' }
        '500': { $ref: '#/components/responses/ServerError' }
  /flaky-tests/list-quarantined-tests:
    post:
      operationId: listQuarantinedTests
      tags:
        - Flaky Tests
      summary: Get a list of quarantined tests
      description: List tests currently quarantined in a repository, with pagination.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - repo
                - org_url_slug
                - page_query
              properties:
                repo:
                  $ref: '#/components/schemas/Repo'
                org_url_slug:
                  type: string
                page_query:
                  $ref: '#/components/schemas/PageQuery'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  quarantined_tests:
                    type: array
                    items:
                      $ref: '#/components/schemas/TestDetail'
                  page:
                    $ref: '#/components/schemas/Page'
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '500': { $ref: '#/components/responses/ServerError' }
  /flaky-tests/list-unhealthy-tests:
    post:
      operationId: listUnhealthyTests
      tags:
        - Flaky Tests
      summary: Get a list of unhealthy tests
      description: >-
        List unhealthy tests in a repository, filtered by status (FLAKY or
        BROKEN), with pagination.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - repo
                - org_url_slug
                - page_query
                - status
              properties:
                repo:
                  $ref: '#/components/schemas/Repo'
                org_url_slug:
                  type: string
                page_query:
                  $ref: '#/components/schemas/PageQuery'
                status:
                  type: string
                  enum: [FLAKY, BROKEN]
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  tests:
                    type: array
                    items:
                      $ref: '#/components/schemas/TestDetail'
                  page:
                    $ref: '#/components/schemas/Page'
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '500': { $ref: '#/components/responses/ServerError' }
  /flaky-tests/list-failing-tests:
    post:
      operationId: listFailingTests
      tags:
        - Flaky Tests
      summary: Get a list of distinct tests that failed in the given time range
      description: >-
        List distinct tests that failed within an inclusive start / exclusive
        end time range, with pagination.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - repo
                - org_url_slug
                - start_time
                - end_time
                - page_query
              properties:
                repo:
                  $ref: '#/components/schemas/Repo'
                org_url_slug:
                  type: string
                start_time:
                  type: string
                  format: date-time
                  description: Inclusive start of the time range.
                end_time:
                  type: string
                  format: date-time
                  description: Exclusive end of the time range.
                page_query:
                  $ref: '#/components/schemas/PageQuery'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  tests:
                    type: array
                    items:
                      $ref: '#/components/schemas/TestDetail'
                  page:
                    $ref: '#/components/schemas/Page'
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '500': { $ref: '#/components/responses/ServerError' }
  /flaky-tests/link-ticket-to-test-case:
    post:
      operationId: linkTicketToTestCase
      tags:
        - Flaky Tests
      summary: Link a ticket to a test case
      description: >-
        Associate an external ticket (e.g. Jira "KAN-123" or Linear "TRUNK-1234")
        with a Trunk test case.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - repo
                - test_case_id
                - external_ticket_id
              properties:
                repo:
                  $ref: '#/components/schemas/Repo'
                test_case_id:
                  type: string
                  format: uuid
                external_ticket_id:
                  type: string
                  example: KAN-123
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '404': { $ref: '#/components/responses/NotFound' }
        '500': { $ref: '#/components/responses/ServerError' }
  /submitPullRequest:
    post:
      operationId: submitPullRequest
      tags:
        - Merge Queue
      summary: Submit a pull request to the merge queue
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PullRequestRef'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PullRequestState'
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '500': { $ref: '#/components/responses/ServerError' }
  /cancelPullRequest:
    post:
      operationId: cancelPullRequest
      tags:
        - Merge Queue
      summary: Cancel a pull request in the merge queue
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PullRequestRef'
      responses:
        '200':
          description: OK
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '500': { $ref: '#/components/responses/ServerError' }
  /getSubmittedPullRequest:
    post:
      operationId: getSubmittedPullRequest
      tags:
        - Merge Queue
      summary: Get the state of a submitted pull request
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PullRequestRef'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PullRequestState'
        '401': { $ref: '#/components/responses/Unauthorized' }
        '404': { $ref: '#/components/responses/NotFound' }
        '500': { $ref: '#/components/responses/ServerError' }
  /restartTestsOnPullRequest:
    post:
      operationId: restartTestsOnPullRequest
      tags:
        - Merge Queue
      summary: Restart tests on a pull request
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PullRequestRef'
      responses:
        '200':
          description: OK
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '500': { $ref: '#/components/responses/ServerError' }
  /setImpactedTargets:
    post:
      operationId: setImpactedTargets
      tags:
        - Merge Queue
      summary: Set the impacted targets for a pull request
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/PullRequestRef'
                - type: object
                  required:
                    - impactedTargets
                  properties:
                    impactedTargets:
                      type: array
                      items:
                        type: string
      responses:
        '200':
          description: OK
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '500': { $ref: '#/components/responses/ServerError' }
  /getMergeQueueTestingDetails:
    post:
      operationId: getMergeQueueTestingDetails
      tags:
        - Merge Queue
      summary: Get in-progress merge queue testing details
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QueueRef'
      responses:
        '200':
          description: OK
        '401': { $ref: '#/components/responses/Unauthorized' }
        '500': { $ref: '#/components/responses/ServerError' }
  /createQueue:
    post:
      operationId: createQueue
      tags:
        - Merge Queue
      summary: Create a merge queue
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QueueRef'
      responses:
        '200':
          description: OK
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '500': { $ref: '#/components/responses/ServerError' }
  /getQueue:
    post:
      operationId: getQueue
      tags:
        - Merge Queue
      summary: Get a merge queue
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QueueRef'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  state:
                    type: string
                    enum: [RUNNING, PAUSED, DRAINING, SWITCHING_MODES]
        '401': { $ref: '#/components/responses/Unauthorized' }
        '404': { $ref: '#/components/responses/NotFound' }
        '500': { $ref: '#/components/responses/ServerError' }
  /updateQueue:
    post:
      operationId: updateQueue
      tags:
        - Merge Queue
      summary: Update a merge queue configuration
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QueueRef'
      responses:
        '200':
          description: OK
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '500': { $ref: '#/components/responses/ServerError' }
  /deleteQueue:
    post:
      operationId: deleteQueue
      tags:
        - Merge Queue
      summary: Delete a merge queue
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QueueRef'
      responses:
        '200':
          description: OK
        '401': { $ref: '#/components/responses/Unauthorized' }
        '404': { $ref: '#/components/responses/NotFound' }
        '500': { $ref: '#/components/responses/ServerError' }
  /getMergeQueueMetrics:
    get:
      operationId: getMergeQueueMetrics
      tags:
        - Merge Queue
      summary: Get merge queue metrics (Prometheus text exposition format)
      parameters:
        - name: repo
          in: query
          required: false
          schema:
            type: string
        - name: repoHost
          in: query
          required: false
          schema:
            type: string
      responses:
        '200':
          description: OK
          content:
            text/plain:
              schema:
                type: string
        '401': { $ref: '#/components/responses/Unauthorized' }
        '500': { $ref: '#/components/responses/ServerError' }
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-token
      description: Organization API token from Settings > Organization > General > API.
  schemas:
    Repo:
      type: object
      required:
        - host
        - owner
        - name
      properties:
        host:
          type: string
          description: Repository host, e.g. github.com or gitlab.com.
          example: github.com
        owner:
          type: string
          example: my-org
        name:
          type: string
          example: my-repo
    PageQuery:
      type: object
      required:
        - page_size
      properties:
        page_size:
          type: integer
          minimum: 1
          maximum: 100
        page_token:
          type: string
    Page:
      type: object
      properties:
        total_rows:
          type: integer
        total_pages:
          type: integer
        page_index:
          type: integer
        next_page_token:
          type: string
        prev_page_token:
          type: string
        last_page_token:
          type: string
    Status:
      type: object
      properties:
        value:
          type: string
          enum: [HEALTHY, FLAKY, BROKEN]
        reason:
          type: string
        timestamp:
          type: string
          format: date-time
    TestDetail:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        variant:
          type: string
        classname:
          type: string
        file_path:
          type: string
        status:
          $ref: '#/components/schemas/Status'
        failure_rate_last_7d:
          type: number
        failure_rate_last_24h:
          type: number
        most_common_failures:
          type: array
          items:
            type: object
            properties:
              summary:
                type: string
              count:
                type: integer
        quarantined:
          type: boolean
        codeowners:
          type: array
          items:
            type: string
        pull_requests_impacted_last_7d:
          type: integer
        html_url:
          type: string
        ticket:
          type: object
          properties:
            html_url:
              type: string
    PullRequestRef:
      type: object
      required:
        - repo
        - targetBranch
        - pr
      properties:
        repo:
          $ref: '#/components/schemas/Repo'
        targetBranch:
          type: string
          example: main
        pr:
          type: object
          required:
            - number
          properties:
            number:
              type: integer
    QueueRef:
      type: object
      required:
        - repo
        - targetBranch
      properties:
        repo:
          $ref: '#/components/schemas/Repo'
        targetBranch:
          type: string
          example: main
    PullRequestState:
      type: object
      properties:
        state:
          type: string
          enum:
            - NOT_READY
            - PENDING
            - TESTING
            - TESTS_PASSED
            - MERGED
            - FAILED
            - CANCELLED
            - PENDING_FAILURE
    Error:
      type: object
      properties:
        message:
          type: string
  responses:
    BadRequest:
      description: Bad Request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Not Found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    ServerError:
      description: Internal Server Error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'