Create a merge queue
Requires the Update Merge Queue settings permission. Creates a merge queue for a repository and target branch. At most one queue exists per pair, so a second create returns QUEUE_ALREADY_EXISTS.
This operation is not atomic. bisectionConcurrency and enqueueingLabel are applied by a second write, so an error response does not guarantee that no queue was created — if the first write succeeded and the second failed, the queue exists with those two fields at their defaults and this call still returns the second write’s error. Do not blindly retry: a retry returns 409 QUEUE_ALREADY_EXISTS. Instead read the queue back (GET /v2/merge-queues?repositoryId=…&targetBranch=…) and, if it exists, finish the configuration with PATCH /v2/merge-queues/{id}/config.
Authorizations
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 permissions it holds. A key with none can read merge queues but change nothing in them. Permissions cover merge queues and test-result uploads, including the quarantine lookups a CI run makes before it uploads; any key can call the other Flaky Tests and Dynamic CI endpoints, including their writes.
Body
Omitting mode creates a queue-mode queue, and omitting concurrency sets it to 5.
The repository to create the queue for. Resolve it with GET /v2/repositories?providerUrl=….
The branch the queue merges into. At most one queue exists per repository and target branch.
1queue (shown as Single in the app) or graph (Parallel). Omitted, queue.
queue, graph How many entries the queue may verify at once. Higher values merge faster and cost more CI.
1 <= x <= 1000How many verification runs the engine may use in parallel when bisecting a failed batch. 0 means bisection gets no dedicated capacity and shares concurrency.
0 <= x <= 1000The label that submits a pull request to this queue when areLabelCommandsEnabled is true. May not collide with a Trunk-reserved trunk-* state label.
1Response
The created merge queue
"xK9mP2nQ"
Resolve with GET /v2/repositories/{id}.
"7c9e6679-7425-40de-944b-e07fc1f90ae7"
"main"
The queue's lifecycle state. switchingModes is a transient conversion state during which config and mode writes are refused.
running, paused, draining, switchingModes "running"
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.
queue, graph "queue"
Who owns the queue's configuration. terraform — the last write came from Terraform, identified on any queue write (create, config, pause/resume/drain, mode switch) by a User-Agent or X-Source header containing terraform or opentofu, case-insensitively — the same rule as v1. terraformWithDrift — Terraform owned it and a later write was not identified as Terraform's, so the live configuration may differ from the plan. Any such write counts, including pause/resume from other automation. manual — never written by Terraform.
manual, terraform, terraformWithDrift When the queue was created.
"2026-07-24T20:26:04.000Z"
When the queue's own record last changed — its state or configuration. Not affected by entries moving through it.
"2026-07-28T11:02:31.000Z"
Absolute browsable URL of the repository at its provider (not a Trunk API URL).
"https://github.com/acme/widgets"
Path — not an absolute URL — of this queue's pull-request collection on the Trunk API. Resolve it against the server URL; do not fetch it as-is.
"/v2/merge-queues/xK9mP2nQ/pull-requests"
A queue's full configuration. requiredStatuses (what must pass) is a merge-protection control rather than a tuning knob, so treat write access to this object as security-relevant.
The queue's page in the Trunk web app. Absent when the repository has no keyed organization (no slug to address it by).
"https://app.trunk.io/acme/merge-queue/xK9mP2nQ"