> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trunk.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Get a merge queue's dispatch order

> Returns the queue's batches with a verification run, what is admitted and waiting in the order the engine will consider it, and what has not been admitted yet.

**A batch in `batches` is not necessarily still testing** — one that has passed, is merging, or is holding others back after a failure still has a run and is still listed. Read its `state`.

**The order is one of consideration, not of execution, and array position is not a wait estimate.** `predictedBatch` repeats across every pull request predicted to start testing together, and in `graph` mode several predicted batches commonly start at once — so the pull requests ahead of yours may all start with it, and may sit on unrelated branches that never block yours. `directlyAhead` is what actually precedes a pull request; use it rather than counting.

It is a point-in-time prediction. A new submission, a priority change or a failure regroups it, and four things outside this response still gate dispatch: `queueState: paused` stops it entirely, the queue's testing-concurrency cap bounds how many start, a batch whose predecessors have no usable test branch is skipped over rather than blocking, and bisections dispatch on their own budget.

Pull requests that are not ready are deliberately absent — they are not admitted, so they hold no position. Read one through `GET /v2/pull-requests/{id}`.

Unpaginated: the engine caps its own graph, so the admitted set is bounded. `awaitingAdmission` is not, and is truncated.



## OpenAPI

````yaml /openapi-v2.json get /v2/merge-queues/{id}/order
openapi: 3.1.0
info:
  title: Trunk API
  version: 2.0.0
  description: >-
    The Trunk public API. Every endpoint is scoped to a single organization and
    requires a credential.


    ## Authentication


    For automation, send an API key as `Authorization: Bearer <key>`. An
    organization admin creates one in the Trunk app under **Settings → Developer
    → API Keys**, and chooses the merge-queue permissions it holds. A key with
    no permissions can read merge queues but change nothing. Those permissions
    scope merge queue only: every key can use the Flaky Tests and Dynamic CI
    endpoints, including their writes, whatever permissions it holds.


    A short-lived first-party token in the `x-trunk-token` header is what the
    `trunk` CLI sends after `trunk auth login`.


    A GitHub Actions job can upload impacted targets with no Trunk secret: the
    `trunk-io/login` action exchanges the run's own GitHub credential (its OIDC
    token, or on a pull request from a fork its `GITHUB_TOKEN`) for a
    short-lived first-party token. That token is accepted only by `PUT
    /v2/impacted-targets`, for the run's own repository — and on a fork pull
    request, only for that pull request and its head sha.


    ## Errors


    Every 4xx and 5xx response is a `ErrorResponse`: `{ "error": { "code",
    "message" } }`. Switch on `code`, which is stable; `message` is prose and
    may change at any time.


    **An authorization denial on a read is reported as `404`, not `403`** —
    whether a resource exists must not leak across organizations, so a resource
    in another organization is indistinguishable from one that does not exist.
    `403 INSUFFICIENT_PERMISSIONS` means the credential is valid but is not
    permitted the action (or carries no organization).


    Every response carries an `X-Request-Id` header. Quote it in support
    requests.


    ## Rate limiting


    Requests are limited per organization (currently 100 requests/second).
    Exceeding it returns `429` with `RATE_LIMIT_EXCEEDED`; retry with backoff.
    Note that the limit is enforced at the edge, which does not yet wrap its
    `429` in the `ErrorResponse` envelope described above — treat any `429` as
    rate limiting regardless of body.


    ## Compatibility


    Within v2, Trunk may add: new endpoints, new **optional** response fields,
    new members to any enum (including new `code` values, new queue-entry
    states, and new providers), and new optional request parameters. **Clients
    must tolerate values and fields they do not recognize** rather than failing
    closed — a client that switches exhaustively over an enum will break when a
    member is added. Removals and semantic changes require a new major version.


    ## Provider support


    Merge queues, verification runs and checks are **GitHub-only** today;
    `Check.provider` has a single member for that reason. Impacted-target
    uploads additionally require a `github.com` repository named `owner/repo`.
    The `Provider` enum lists values the repository index can store, not
    surfaces that are fully supported.


    ## Not yet available


    A pull request's numeric **position** in its queue is not exposed, and list
    responses are not ordered by queue position. `GET
    /v2/merge-queues/{id}/order` returns the order the engine will consider pull
    requests in, but an array index there is not a wait: use a pending entry's
    `directlyAhead` rather than counting, and `GET
    /v2/pull-requests/{id}/queue-entry-estimate` for when it is expected to
    merge (on queues that serve estimates). This API delivers no events of its
    own — poll it, or subscribe to [Merge Queue's
    webhooks](https://docs.trunk.io/merge-queue/webhooks). `Idempotency-Key` is
    not yet honored, so a mutation that times out must be reconciled by reading
    the resource back rather than blindly retried.
  contact:
    name: Trunk Support
    url: https://docs.trunk.io
servers:
  - url: https://api.trunk.io
    description: Production
security:
  - apiKey: []
  - trunkToken: []
tags:
  - name: mergeQueues
    x-group: Merge Queues
  - name: pullRequests
    x-group: Pull Requests
  - name: mergeQueueVerificationRuns
    x-group: Verification Runs
  - name: impactedTargets
    x-group: Impacted Targets
  - name: repositories
    x-group: Repositories
  - name: dynamicCi
    x-group: Dynamic CI
  - name: ciJobs
    x-group: CI Jobs
  - name: ciWorkflowRuns
    x-group: CI Workflow Runs
  - name: ciFailureClusters
    x-group: CI Failure Clusters
  - name: testCollections
    x-group: Test Collections
  - name: tests
    x-group: Tests
  - name: testUploads
    x-group: Test Uploads
paths:
  /v2/merge-queues/{id}/order:
    get:
      tags:
        - mergeQueues
      summary: Get a merge queue's dispatch order
      description: >-
        Returns the queue's batches with a verification run, what is admitted
        and waiting in the order the engine will consider it, and what has not
        been admitted yet.


        **A batch in `batches` is not necessarily still testing** — one that has
        passed, is merging, or is holding others back after a failure still has
        a run and is still listed. Read its `state`.


        **The order is one of consideration, not of execution, and array
        position is not a wait estimate.** `predictedBatch` repeats across every
        pull request predicted to start testing together, and in `graph` mode
        several predicted batches commonly start at once — so the pull requests
        ahead of yours may all start with it, and may sit on unrelated branches
        that never block yours. `directlyAhead` is what actually precedes a pull
        request; use it rather than counting.


        It is a point-in-time prediction. A new submission, a priority change or
        a failure regroups it, and four things outside this response still gate
        dispatch: `queueState: paused` stops it entirely, the queue's
        testing-concurrency cap bounds how many start, a batch whose
        predecessors have no usable test branch is skipped over rather than
        blocking, and bisections dispatch on their own budget.


        Pull requests that are not ready are deliberately absent — they are not
        admitted, so they hold no position. Read one through `GET
        /v2/pull-requests/{id}`.


        Unpaginated: the engine caps its own graph, so the admitted set is
        bounded. `awaitingAdmission` is not, and is truncated.
      operationId: mergeQueues.order
      parameters:
        - schema:
            type: string
            description: The merge queue's id.
            example: xK9mP2nQ
          required: true
          description: The merge queue's id.
          name: id
          in: path
      responses:
        '200':
          description: The queue's dispatch order
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MergeQueueOrder'
        '401':
          description: '`AUTHENTICATION_REQUIRED` | `INVALID_TOKEN`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                AUTHENTICATION_REQUIRED:
                  summary: AUTHENTICATION_REQUIRED
                  value:
                    error:
                      code: AUTHENTICATION_REQUIRED
                      message: No credential was supplied
                INVALID_TOKEN:
                  summary: INVALID_TOKEN
                  value:
                    error:
                      code: INVALID_TOKEN
                      message: The supplied token failed verification
        '403':
          description: '`INSUFFICIENT_PERMISSIONS`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                INSUFFICIENT_PERMISSIONS:
                  summary: INSUFFICIENT_PERMISSIONS
                  value:
                    error:
                      code: INSUFFICIENT_PERMISSIONS
                      message: >-
                        The supplied credential is missing the required
                        permission
        '404':
          description: '`MERGE_QUEUE_NOT_FOUND`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                MERGE_QUEUE_NOT_FOUND:
                  summary: MERGE_QUEUE_NOT_FOUND
                  value:
                    error:
                      code: MERGE_QUEUE_NOT_FOUND
                      message: Merge queue not found
        '429':
          description: '`RATE_LIMIT_EXCEEDED`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                RATE_LIMIT_EXCEEDED:
                  summary: RATE_LIMIT_EXCEEDED
                  value:
                    error:
                      code: RATE_LIMIT_EXCEEDED
                      message: Rate limit exceeded; retry after the Retry-After delay
        '500':
          description: '`INTERNAL_ERROR`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                INTERNAL_ERROR:
                  summary: INTERNAL_ERROR
                  value:
                    error:
                      code: INTERNAL_ERROR
                      message: An unexpected error occurred
        '502':
          description: '`UPSTREAM_ERROR`'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                UPSTREAM_ERROR:
                  summary: UPSTREAM_ERROR
                  value:
                    error:
                      code: UPSTREAM_ERROR
                      message: An upstream service did not respond
components:
  schemas:
    MergeQueueOrder:
      type: object
      properties:
        mode:
          $ref: '#/components/schemas/MergeQueueMode'
        queueState:
          $ref: '#/components/schemas/MergeQueueState'
        batchingEnabled:
          type: boolean
          description: >-
            Batching is configured. When false every pull request forms its own
            predicted batch, and `directlyAhead` is empty throughout.
          example: true
        isolationResolved:
          type: boolean
          description: >-
            False when an `ISOLATE` batching rule could apply to this queue.
            Resolving those costs one impacted-target lookup per pull request,
            so this read skips it — which can move an isolated pull request into
            an earlier predicted batch, and so earlier in `pending`, than the
            engine will actually consider it.
          example: true
        hasCycle:
          type: boolean
          description: >-
            The queue's graph has a cycle and the engine fell back to a degraded
            ordering. `directlyAhead` and `heldBy` are empty, and a held pull
            request reports as `schedulable`.
          example: false
        batches:
          type: array
          items:
            $ref: '#/components/schemas/OrderedBatch'
          maxItems: 10000
          description: >-
            Batches that have a verification run, in dependency order — a batch
            appears after the batches it builds on, with bisections last. **Not
            start order**, and not all of them are still testing: read each
            batch's `state`.
        pending:
          type: array
          items:
            $ref: '#/components/schemas/OrderedPendingItem'
          maxItems: 10000
          description: >-
            Admitted pull requests, in the order the engine will consider them;
            held ones come after schedulable ones. A `schedulable` entry's index
            **is** the number of admitted, schedulable pull requests the engine
            will consider before it — with batching off that is exactly the
            index — but that is not a wait: see `predictedBatch`.
        awaitingAdmission:
          type: array
          items:
            $ref: '#/components/schemas/QueuedPullRequest'
          maxItems: 10000
          description: >-
            Pull requests past the engine's graph soft cap, which hold no
            position yet. Ordered by a DIFFERENT comparator than `pending`, so
            the two lists are not one sequence, and truncated — see
            `awaitingAdmissionTotal`.
        awaitingAdmissionTotal:
          type: integer
          description: >-
            How many are awaiting admission in total. The engine truncates the
            list, so compare this with `awaitingAdmission.length` to detect it;
            read a specific pull request through `GET /v2/pull-requests/{id}`
            rather than scanning.
          example: 0
      required:
        - mode
        - queueState
        - batchingEnabled
        - isolationResolved
        - hasCycle
        - batches
        - pending
        - awaitingAdmission
        - awaitingAdmissionTotal
      description: >-
        The queue's dispatch order: what is testing, what is admitted and
        waiting, and what has not been admitted. Pull requests that are not
        ready are deliberately absent — they hold no position — and are readable
        through `GET /v2/pull-requests/{id}`.
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              $ref: '#/components/schemas/ErrorCode'
            message:
              type: string
              description: >-
                Human-readable description of what went wrong. Not stable — do
                not parse.
              example: An unexpected error occurred
          required:
            - code
            - message
      required:
        - error
      description: >-
        The uniform error envelope. Every 4xx and 5xx response in this API has
        this shape.
    MergeQueueMode:
      type: string
      enum:
        - queue
        - graph
      description: >-
        The engine a queue runs. `queue` tests entries in strict arrival order,
        one line. `graph` builds a dependency graph and may test entries
        speculatively in parallel, which merges faster but can require bisection
        to attribute a failure. Changing mode is a real conversion, not a flag
        flip — see `mergeQueues.switchModes`.
      example: queue
    MergeQueueState:
      type: string
      enum:
        - running
        - paused
        - draining
        - switchingModes
      description: >-
        The queue's lifecycle state. `switchingModes` is a transient conversion
        state during which config and mode writes are refused.
      example: running
    OrderedBatch:
      type: object
      properties:
        verificationRunId:
          type: string
          description: >-
            The run testing this batch — pass it to `GET
            /v2/merge-queue-verification-runs/{id}`.
          example: 4f3e2d1c-0b9a-4876-9543-210fedcba987
        state:
          $ref: '#/components/schemas/QueueEntryState'
        isBisection:
          type: boolean
          description: >-
            This batch is a bisection, splitting a failed batch to find the
            culprit. Bisections dispatch on their own concurrency budget, so one
            can start ahead of a lower-numbered `predictedBatch`.
          example: false
        pullRequests:
          type: array
          items:
            $ref: '#/components/schemas/QueuedPullRequest'
          maxItems: 10000
          description: The pull requests this run is testing together.
      required:
        - verificationRunId
        - state
        - isBisection
        - pullRequests
      description: >-
        A batch with a verification run — testing, passed, merging, or holding
        others back after a failure. `state` says which.
    OrderedPendingItem:
      type: object
      properties:
        pullRequest:
          $ref: '#/components/schemas/QueuedPullRequest'
        schedulability:
          $ref: '#/components/schemas/PendingSchedulability'
        predictedBatch:
          type: integer
          description: >-
            1-based, and REPEATS across every pull request predicted to start
            testing together. Absent for a held item, which is excluded from the
            prediction. This is an order of CONSIDERATION, not of execution:
            several predicted batches commonly start at once, so a lower number
            is not a shorter wait.
          example: 1
        directlyAhead:
          type: array
          items:
            $ref: '#/components/schemas/QueuedPullRequest'
          maxItems: 10000
          description: >-
            The pull requests immediately in front of this one in the queue's
            graph. Reduced-DAG adjacency, not a conflict set: edges encode
            impacted-target overlap, so an indirect overlap is represented
            through the item between them. Empty when `batchingEnabled` is false
            or `hasCycle` is true.
        heldBy:
          type: array
          items:
            $ref: '#/components/schemas/QueuedPullRequest'
          maxItems: 10000
          description: >-
            The failing pull requests holding this one back, when
            `schedulability` is `heldBehindFailure`.
      required:
        - pullRequest
        - schedulability
        - directlyAhead
        - heldBy
      description: A pull request admitted to the queue but not yet testing.
    QueuedPullRequest:
      type: object
      properties:
        id:
          type: string
          description: >-
            The pull request's id in this API — pass it to `GET
            /v2/pull-requests/{id}`.
          example: 6f1d2c3b-4a59-4e6f-8a7b-9c0d1e2f3a4b
        number:
          type: integer
          example: 4901
        sha:
          type: string
          description: >-
            The head commit that was included in this run. Compare with the pull
            request's current `sha` to detect that its branch moved since.
          example: 9c58bf40e5c1a2b3d4e5f60718293a4b5c6d7e8f
        title:
          type: string
          example: Add the widget endpoint
        url:
          type: string
          description: >-
            The pull request on its provider. Absent until Trunk's sync has
            populated it.
          example: https://github.com/acme/widgets/pull/4901
      required:
        - id
        - number
        - sha
        - title
      description: A pull request in the queue's dispatch order.
    ErrorCode:
      type: string
      enum:
        - AUTHENTICATION_REQUIRED
        - INVALID_TOKEN
        - INSUFFICIENT_PERMISSIONS
        - INTERNAL_ERROR
        - VALIDATION_FAILED
        - NOT_FOUND
        - INVALID_CURSOR
        - MERGE_QUEUE_NOT_FOUND
        - PR_ALREADY_ENQUEUED
        - PR_NOT_ENQUEUEABLE
        - UPSTREAM_ERROR
        - VERIFICATION_RUN_NOT_FOUND
        - PR_NOT_FOUND
        - REPOSITORY_NOT_FOUND
        - IMPACTED_TARGETS_UNSUPPORTED
        - QUEUE_ALREADY_EXISTS
        - QUEUE_HAS_ACTIVE_ENTRIES
        - MODE_CHANGE_IN_PROGRESS
        - PR_NOT_IN_ACTIVE_STATE
        - MERGE_QUEUE_NOT_CREATABLE
        - PR_TESTS_NOT_RESTARTABLE
        - ALLOWED_BOT_SUBMITTERS_FROZEN
        - ESTIMATE_NOT_ENABLED
        - PROVIDER_URL_NOT_FOUND
        - CI_HOST_UNSUPPORTED
        - CI_SCOPE_NOT_FOUND
        - CI_JOB_NOT_FOUND
        - CI_FAILURE_CLUSTER_NOT_FOUND
        - TEST_COLLECTION_NOT_FOUND
        - TEST_NOT_FOUND
        - TEST_UPLOAD_NOT_FOUND
        - TICKETING_NOT_CONFIGURED
        - TICKETING_CREDENTIALS_INVALID
        - TICKETING_SITE_REFUSED
        - TICKET_NOT_FOUND
        - TICKET_LINK_CONFLICT
        - TEST_ALREADY_LINKED
        - TICKET_FIELDS_REJECTED
        - TICKET_CONTENT_UNAVAILABLE
        - TICKETING_CREATE_REFUSED
        - RATE_LIMIT_EXCEEDED
      description: >-
        Stable machine-readable error identifier. Switch on this, never on
        `message`. A shipped code's meaning never changes, but **new codes may
        be added within v2** — treat an unrecognized code as a generic failure
        of its HTTP status rather than failing closed.
      example: INTERNAL_ERROR
    QueueEntryState:
      type: string
      enum:
        - notReady
        - pending
        - testing
        - testsPassed
        - merged
        - failed
        - cancelled
        - pendingFailure
      description: >-
        Where a pull request sits in its queue's lifecycle.


        | Value | Meaning |

        | --- | --- |

        | `notReady` | Enqueued but not yet eligible to test — a readiness
        condition is unmet (see `QueueEntry.readiness`). |

        | `pending` | Ready and waiting for a test slot, or waiting on an
        earlier entry. |

        | `testing` | A verification run is in flight for this entry. |

        | `testsPassed` | Verification succeeded; waiting to merge. |

        | `merged` | Terminal — merged into the target branch. |

        | `failed` | Terminal — verification or the merge itself failed. |

        | `cancelled` | Terminal — removed from the queue (dequeued, or
        cancelled by the engine). |

        | `pendingFailure` | A failure is expected because an entry ahead
        failed, but this entry has not been re-tested yet. Not terminal: it
        usually returns to `pending` or `testing`. |


        New members may be added within v2.
      example: testing
    PendingSchedulability:
      type: string
      enum:
        - schedulable
        - heldBehindFailure
      description: >-
        `schedulable` means eligible for the next scheduling pass, NOT that it
        will run next — the pass is still gated by `queueState`, the queue's
        testing-concurrency cap, and predecessors lacking a usable test branch.
        `heldBehindFailure` means a `PENDING_FAILURE` ancestor is holding it;
        `heldBy` names which.
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >-
        An API key, sent as `Authorization: Bearer <key>`. An organization admin
        creates one in the Trunk app under **Settings → Developer → API Keys**
        and chooses the merge-queue permissions it holds; a key with none can
        read merge queues but change nothing. Those permissions scope merge
        queue only: every key can use the Flaky Tests and Dynamic CI endpoints,
        including their writes, whatever permissions it holds.
    trunkToken:
      type: apiKey
      in: header
      name: x-trunk-token
      description: >-
        A short-lived first-party token, sent in the `x-trunk-token` header. The
        `trunk` CLI sends one after `trunk auth login`, and the `trunk-io/login`
        action obtains one for a GitHub Actions run.


        **A token from a GitHub Actions run can only upload impacted targets**
        (`PUT /v2/impacted-targets`), for the repository the run belongs to;
        every other endpoint refuses it.

````