> ## 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.

# API

> Upload impacted targets, read testing details, and handle the common gotchas

## Uploading impacted targets

Impacted Targets should be computed for every PR. The list of impacted targets should be computed by comparing two different SHAs: the **head of the target branch**, and the **merge commit of the pr**.

<Info>
  Our [reference implementation](https://github.com/trunk-io/bazel-action/tree/main/src/scripts) may be useful in guiding your implementation.
</Info>

**POST** the list of impacted targets here:`https://api.trunk.io:443/v1/setImpactedTargets`.

```ssml theme={null}
HEADERS:
	Content-Type: application/json,
	x-api-token: <organization API token>, <!-- only for non forked PRs -->
	x-forked-workflow-run-id: ${{github.run_id}}, <!-- only for forked PRs -->

BODY: {
	repo: {
		host: "github.com",
		owner: <repo owner>, <!--- For example, "trunk-io" --->
		name: <repo name>, <!--- For example, "merge-action" --->
	},
	pr: {
		number: <pr number>, <!-- For example, 5 -->
		sha: <pr sha>, <!-- For example, "07fc773f16c0353bc3820fed65d89afddb9f81c3" -->
	},
	targetBranch: <merge instance branch>, <!-- For example, "main" -->
	impactedTargets: ["target-1", "target-2", ...] OR "ALL" <!--- see notes on "ALL" below --->
      }
```

`impactedTargets` allows specifying either an array of strings representing the impacted targets from the PR or the string "ALL" (note that this is explicitly not in an array and is just the string "ALL"). Specifying "ALL" is the equivalent of saying that everything that comes into the graph after this PR should be based on this one, which is useful when your PR contains changes that affect the whole repo (such as editing `trunk.yaml` or a GitHub workflow).

### Handling forked pull requests

The HTTP POST must contain the `x-api-token` to prove that it is a valid request from a workflow your org controls. *Workflows that come from forked PRs most likely will not have access to the Trunk org token* required for the HTTP POST above. In this case, you should provide the **run ID** of the workflow as the `x-forked-workflow-run-id` header in place of the `x-api-token`. This ID can be obtained from [the GitHub context](https://docs.github.com/en/actions/learn-github-actions/contexts#github-context) as <code>{'${{ github.run_id }}'}</code>. Trunk Merge Queue will verify that the ID belongs to a currently running workflow originating from a forked PR with a SHA that matches the one provided in the request and allow it through.

<Warning>
  We do not recommend using an event trigger like `pull_request_target.` This would allow workflows from forked PRs to get secrets, which is a security risk and would open your repo to attackers making forks, adding malicious code, and then running it against your repo to exfiltrate information. (see[ Keeping your GitHub Actions and workflows secure](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/)).
</Warning>

## Reading testing details with `/getMergeQueueTestingDetails`

Once a PR is in the queue, `/getMergeQueueTestingDetails` returns the testing batch
that contains it, including the impacted targets being tested. Two response fields
describe targets, and they are not interchangeable:

* `impactedTargetsForTestedPrs` — the union of impacted targets for **only the PRs in
  this test run**. This is the batch being predictively tested together.
* `impactedTargets` — `impactedTargetsForTestedPrs` **plus** the impacted targets of
  every PR ahead of this batch in the queue. Use this when you need to know everything
  that the predictive build is implicitly built on top of.

If you're driving a CI job that should only run the targets owned by the current batch,
read `impactedTargetsForTestedPrs`. If you need the full set of targets the predictive
build state covers (for example, to decide whether to skip a cache rebuild), read
`impactedTargets`.

## Deriving `testRunId` from the merge branch name

Trunk Merge Queue creates a branch per predictive test run with the shape
`trunk-merge/pr-<PR_NUMBER>/<TEST_RUN_UUID>`. The trailing UUID **is** the `testRunId`
used by the API. CI jobs running against a `trunk-merge/*` branch can parse it directly
from `GITHUB_REF` (or the equivalent ref variable on other CI providers) without an
extra API call.

```bash theme={null}
# trunk-merge/pr-1234/9c3a5b1e-7f02-4b6a-9d11-3a5e8f0c4d22
TEST_RUN_ID="${GITHUB_REF##*/}"
```

## Recipes and gotchas

### "ALL" does not short-circuit the rest of the queue

Uploading `"ALL"` for a PR signals that the PR is impacting every target, so any other
PR in the queue should be considered to overlap with it. It does **not** override or
replace the impacted targets that other PRs upload. If PR A uploads `"ALL"` and PR B
uploads `["frontend"]`, B's frontend targets still matter — A simply joins every lane
B (and every other PR) lives on.

Use `"ALL"` for PRs that genuinely touch the whole graph (editing `trunk.yaml`, a
shared GitHub workflow, or a root-level config). Don't use it as a shortcut for "I
don't want to compute targets for this PR" — you will serialize the queue.

### Last upload wins per head SHA

If you upload impacted targets multiple times for the same PR head SHA, the most
recent upload replaces the earlier ones. There is no merge or union performed
server-side. If your CI recomputes targets after an amend or a force-push, the new
upload is authoritative.

### Reuse `bazel-diff` output between PR and MQ jobs

The `bazel-diff` result that produces your impacted-targets list for a PR build is
the same artifact you'd recompute inside the merge queue's test job. Most Bazel orgs
reuse it: compute once on PR open, upload it to `/setImpactedTargets`, and have the
`trunk-merge/*` CI job pull the same artifact (via `actions/upload-artifact` /
`download-artifact`, an artifact store, or an S3 cache) rather than recomputing.

### Request body size limit

<Info>
  The request body limit is 20 MB. If your target list exceeds the limit, send `"ALL"` as the `impactedTargets` value instead of a full list.
</Info>
