Trunk emits webhooks for Merge Queue events so you can react to PR and batch lifecycle changes from your own systems. Subscriptions are managed in the Trunk web app under Merge Queue > Settings > Webhooks and are powered by Svix. The full event catalog with JSON schemas lives in the Svix portal.Documentation Index
Fetch the complete documentation index at: https://trunk-4cab4936-sam-gutentag-webhook-lifecycle.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Webhook Events | trunk.io - Svix
Subscribing to events
Merge Queue events fall into two families and each must be subscribed to explicitly:pull_request.*— events about an individual PR moving through the queue (queued, testing, merged, failed).pull_request_batch.*— events about a batch of PRs being tested together (for example,pull_request_batch.pending_failure).
If you only see
pull_request.* events arriving at your endpoint, you likely haven’t subscribed to the batch family. Edit the Events list on your webhook subscription in the Trunk web app and enable pull_request_batch.* entries.Event lifecycle reference
A typical PR moves through the queue as follows:- The PR is added to the queue and a
pull_request.queuedevent fires. - Once Trunk starts testing the PR (either alone or as part of a batch), a
pull_request.testingevent fires. - On a clean run, the PR merges and
pull_request.mergedfires. - If the PR is kicked from the queue at any point,
pull_request.failedfires.
pull_request_batch.pending_failure fires for the batch. This does not always lead to bisection. If a PR higher in the queue fails first, the PRs above it can get kicked out and the surviving PRs are re-queued. The PRs that show up in subsequent pull_request.queued events won’t necessarily map back to the original pending_failure batch.
When Trunk does run a bisection to identify the failing PR in a batch, there is no dedicated bisection_completed event. Instead, watch the reason field on pull_request.queued:
BISECTION_REQUIRED— the PR is entering bisection.BISECTION_TEST_RUN_PASSED— the PR passed its bisection test run and is returning to the queue.
Multiple PRs in a batch
For most events the PR lifecycle and the batch lifecycle are the same — events fire per PR even when PRs are tested together. A 4-PR batch produces fourpull_request.testing events, one per PR in the batch. pull_request.failed fires for each PR that is kicked out of the queue.
Payload notes
Webhook payloads currently do not include an event timestamp. The practical workaround is to treat the time your endpoint receives the webhook as the event time. If you need precise event ordering, persist the receive-time on your side as soon as the payload arrives.test_case.status_changed v1 vs v2
The original test_case.status_changed event is being phased out in favor of v2.test_case.status_changed. The v2 event intentionally omits aggregate metrics like failure_rate_last_7d — those fields will be 0 or missing on the v1 event today and are not present in v2 at all.
To enrich a status-change webhook with current metrics, call the flaky-tests/get-test-details API from your webhook handler using the test_case.id from the payload.
See the Flaky Tests webhooks reference for the full v2.test_case.status_changed payload schema and other flaky-tests event types.
Quarantining events
test_case.quarantining_setting_changed fires only when a quarantining setting is manually overridden to ALWAYS or NEVER. It does not fire when Trunk auto-quarantines a test based on flakiness.
To react to auto-quarantine, listen to test_case.status_changed (or v2.test_case.status_changed) and check for current_status == FLAKY in the payload.
AI investigation events
test_case.investigation_completed fires only when an AI/autofix flaky test analysis finishes — this is a beta feature scoped to AI investigations, not general status changes.
For “this test just became flaky” reactions (Linear ticket creation, Slack alerts, and so on), subscribe to v2.test_case.status_changed instead.