https://api.trunk.io. Endpoint paths already include /v2 (for example, /v2/merge-queues), so don’t add it to the host.
Use v2 for new integrations. The v1 API keeps working unchanged. To move existing code to v2, see Migrate from the v1 API.
Before you start
Merge queues are GitHub-only. Install the Trunk GitHub App on the repository, and create a merge queue for the branch you merge into. See Install and create your queue, or create the queue with the API.Concepts
- Queue entry: a pull request’s place in a merge queue, under
queueEntryon a pull request. Itsiddiffers from the pull request’sid. Endpoints under/v2/pull-requests/{id}take the pull request’sid. - Queue entry state:
notReady(submitted, but waiting on a requirement such as passing checks or impacted targets),pending(ready, waiting to test),testing,testsPassed, andpendingFailure. The final states aremerged,failed, andcancelled.queueEntry.readinessexplains anotReadyentry. ApendingFailureentry’s tests failed, and the queue holds it to learn whether the failure is its own, for example while the pull requests ahead of it finish. See Pending failure depth. - Verification run: one CI run the queue started to test a pull request, or a batch of them. When a batch fails, the queue splits it to find the culprit (bisection). Each split is its own verification run.
- Mode:
queuemode (Single in the app) puts pull requests in one line, each tested on top of the ones ahead of it, several at a time.graphmode (Parallel in the app) gives unrelated pull requests separate lines, based on the impacted targets CI uploads for each. - Priority: lower
priorityValuenumbers test first. The names areurgent(0),high(10),medium(100), andlow(200). Send a number aspriorityValueor a name aspriorityName. Without either, a pull request getsmedium(100).urgent(orpriorityValue: 0) restarts lower-priority pull requests that are already testing, so reserve it for emergencies. See Priority merging. - Direct to queue:
direct: truesends a pull request to the queue before its branch protection is satisfied. See Direct-to-Queue.
Authentication
Authenticate automation with an API key, sent asAuthorization: Bearer <key>:
Finding IDs
Endpoints address resources byid. Look IDs up once and store them:
- Queue:
GET /v2/merge-queueslists your organization’s queues, each with itsid,repositoryId,repositoryUrl, andtargetBranch. To list one repository’s queues, get its ID fromGET /v2/repositories?providerUrl=https://github.com/<owner>/<repo>(.data[0].id), then callGET /v2/merge-queues?repositoryId=<id>&targetBranch=<branch>. - Pull request:
GET /v2/pull-requests?repositoryId=…&number=…resolves up to 50 comma-separated pull request numbers at once (setlimit=50, since the default page is 25), or one headbranch. It finds only pull requests Trunk’s GitHub App has already seen. If you just opened one, retry shortly.
Submit and wait for a merge
Submitting needs a key with the Merge and cancel PRs permission. Submit takes the pull request’snumber in the body, so it needs only the queue’s ID and has no lookup delay:
201 response is the pull request; keep its id for polling.
- If the pull request is already queued here (not yet merged, failed, or cancelled), submit returns
409 PR_ALREADY_ENQUEUEDand changes nothing. Look up itsidinstead, using the queue’srepositoryIdfromGET /v2/merge-queues/{id}. - If Trunk can’t enqueue it, submit returns
422 PR_NOT_ENQUEUEABLEwith the reason inmessage. For example:- The pull request doesn’t exist.
- It targets a different branch from the queue’s. A stacked pull request may target another pull request’s branch, as long as the stack ends at the queue’s branch.
- A repository ruleset can block it.
- It’s still in another of the repository’s queues. Look up the pull request, read
queueEntry.mergeQueueId, and dequeue it there first.
- A closed pull request is accepted but stays
notReady.
GET /v2/pull-requests/{id} every 30 to 60 seconds until queueEntry.state is merged, failed, or cancelled, or subscribe to Merge Queue webhooks. The API itself has no webhooks.
- Read
queueEntry.state, not the top-levelstate, which is the pull request’s state on GitHub. queueEntry.statecan go back tonotReadybefore the entry ends. A push to the pull request sends a queued entry back tonotReadyto wait on the new commit, and a resubmitted pull request reuses its entry and starts again atnotReady. Keep polling.- Stop if
queueEntrydisappears or itsmergeQueueIdchanges, and report the outcome as unknown. This happens when a failed or cancelled pull request is submitted to another queue, or its queue is deleted. - Send the last response’s
ETaginIf-None-Match. If nothing changed, you get304with no body. - Set a deadline of your own. A pull request can stay
notReadyfor a long time; the queue cancels it only if itsnotReadyTimeoutMinutessetting is set. - Don’t stop when
ci.pollAfterSecondsisnull. It describes CI on the pull request’s own head commit, not its place in the queue.
direction=newest). The failure reason reference explains each reason. When a required check failed, failed.failureCausingChecks names the checks, and verificationRunId leads to the verification run and its checks.
Pagination
Every list endpoint returns the same envelope:nextCursor back verbatim as cursor to get the next page, until hasMore is false. Cursors are opaque, forward-only, and bound to the endpoint and filters they came from. limit sets the page size, from 1 to 100; the default is 25. includeTotal=true adds a total count at the cost of an extra query.
List order is not queue order. A queue’s pull request list is ordered by when each pull request was first submitted to the queue, newest first, and a resubmission doesn’t move it. For the order the queue will test pull requests in, use GET /v2/merge-queues/{id}/order. Its lists carry only each pull request’s id, number, title, sha, and url. For state or priority, match by id against GET /v2/merge-queues/{id}/pull-requests?state=pending,testing,testsPassed,pendingFailure.
Errors
Every error the API itself returns has this shape:code, which is stable. message is for people and may change at any time.
Some responses don’t have this shape. Trunk’s edge answers 401, 403 for some credential problems, 429, and gateway errors such as 503 before the request reaches the API. The API itself answers 413 for a body over 512 KB and 504 for a request that runs past its time limit (usually 5 seconds), both as plain text. Read error.code only when the body is JSON with an error object, and otherwise branch on the status code. See Authentication errors.
404also means “not yours”. A read of a resource in another organization returns404, not403, so the API never reveals whether it exists.403 INSUFFICIENT_PERMISSIONSmeans your credential is valid but not permitted to take that action.422means the request can’t succeed as sent. Retrying it unchanged gets the same answer until something about the pull request or repository changes.
X-Request-Id header; edge responses may not. Include it when you contact support.
Rate limits
Most requests share one limit of 100 per second per organization, across every API key, user, and CLI session in it. Some requests have limits of their own and don’t count toward it, including:GETrequests on paths that start with/v2/pull-requests, such asGET /v2/pull-requests/{id}and its history: 5 per second per API key or user.GET /v2/merge-queues/{id}/pull-requestsuses the organization’s limit.- Metrics (
GET /v2/merge-queues/metricsandGET /v2/merge-queues/{id}/metrics): 5 per second per organization. - Impacted-target uploads from a GitHub Actions login: 10 per second per repository, with a separate allowance for fork pull requests.
429.
Retrying
- Reads are safe to retry on
429,500,502,503,504, and network errors. Back off exponentially between attempts. - Writes don’t honor
Idempotency-Keyyet. A write that times out or returns500,502,503, or504has an unknown outcome, so read the resource back before retrying. A blind retry can, for example, restart a pull request’s tests twice. Some writes, such asPATCH …/configandPUT /v2/impacted-targets, set a value and are safe to repeat.
Compatibility
Within v2, Trunk may add endpoints, optional request parameters, optional response fields, and new enum values, including error codes and queue-entry states. Removals and changes in meaning require a new major version. Tolerate values and fields you don’t recognize. Most enum values are camelCase. These are uppercase: errorcodes, a transition’s reason and pendingFailure.eventualFailureReason, a check’s providerStatus and providerConclusion, and failureCausingChecks[].conclusion.
Endpoints
Each endpoint page is also available as Markdown, including its OpenAPI definition, by adding.md to its URL.
Merge queues
List merge queues
Create a merge queue
Get a merge queue
Update a merge queue's configuration
Switch a merge queue's mode
Pause a merge queue
Resume a merge queue
Drain a merge queue
Delete a merge queue
Queue order
The order shows what the queue tests next. The graph shows why pull requests depend on each other, not when they run.Get a merge queue's dispatch order
Get a merge queue's dependency graph
Pull requests
Submit a pull request to a merge queue
List a merge queue's pull requests
Resolve pull requests by repository coordinates
Get a pull request
Reprioritize a queued pull request
Update a queued pull request's entry
Restart a queued pull request's tests
Dequeue a pull request
List a pull request's queue-entry state history
List queue-entry state history for several pull requests
Estimate when a queued pull request will merge
Testing
List a merge queue's verification runs
List a pull request's verification runs
Get a verification run
List a merge queue's completed testing
Impacted targets
A queue ingraph mode (Parallel in the app) waits for CI to upload the build targets each pull request impacts before testing it. See Parallel queues.