The merge call now starts a job.
GitHub made its asynchronous merge API generally available on October 1. The endpoint can merge one pull request, process a stack, or place a pull request in a merge queue. GitHub now recommends it over the synchronous REST endpoint and GraphQL merge mutations for programmatic merges.[1]
The request uses PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge-async. A new background request returns HTTP 202 and a UUID. A later GET uses that UUID to fetch the result.[2]
The first response proves that work entered the system. It does not prove that code entered the branch.
Enqueued is a handoff, not a finish line.
The result endpoint reports pending, merged, enqueued, or failed. GitHub's documentation is explicit about the queue case. An enqueued result is final for the async request, but it does not change after the queue later merges the pull request. The client must check the pull request's eventual merged state separately.[2]
That boundary belongs in the interface. Do not turn the first green response into a "Merged" toast. Show "Request accepted" for 202. Show "Queue entry confirmed" for enqueued. Reserve "Merged" for a merge commit object ID or a later endpoint that says the pull request merged.
Pin the head before you hand it over.
The async endpoint accepts a head SHA. If the pull request changes between the request and execution, GitHub cancels the merge. If the client omits the SHA, GitHub uses the current head at request time. Save that expected SHA in the receipt so a reviewer can tell which candidate entered the lane.[2]
The endpoint also accepts a merge action and a rules-bypass flag. A default action may use a configured merge queue or merge directly. Bypass remains false unless the caller requests it and has permission. Put both values in the receipt. A result without the requested route and bypass choice is hard to audit.
Poll the job, not the whole garage.
GitHub says API clients should prefer webhooks to broad polling. If polling is necessary, clients should use a fixed schedule, honor x-poll-interval, make conditional requests, and request only needed data.[3] The async result record expires 24 hours after its most recent update, so retain the result before that window closes.[2]
A practical loop is small. Submit once. Save the UUID and expected SHA. Poll that UUID until the async result leaves pending. If it says enqueued, switch to the pull request's merged-state check or a relevant webhook. Save the final commit object ID or the failure message.