build_beta_detail_external_build_state_updated

Learn about the BUILD_BETA_DETAIL_EXTERNAL_BUILD_STATE_UPDATED webhook event. Fired when a TestFlight external beta build is approved, rejected, or expires.

App Store ConnectTestFlight
build_beta_detail_external_build_state_updated

The BUILD_BETA_DETAIL_EXTERNAL_BUILD_STATE_UPDATED event fires when the state of a TestFlight external beta build changes. External beta builds require Apple's review before they can be distributed to external testers, and this event tracks that process.


When does it fire?


This event triggers on external beta build state transitions:


  • Waiting for Beta Review — the build is queued for Apple's TestFlight review
  • In Beta Review — Apple is reviewing the build
  • Approved — the build passed review and can be distributed to external testers
  • Rejected — the build was rejected (requires changes before resubmission)
  • Expired — the build's 90-day testing window has elapsed

Payload highlights


The payload carries the old and new external build state and the timestamp of the change, plus a reference to the beta detail record — the build number and version string are not in it. The timestamp lets you track exactly when builds become available for external testing.


How Yeethook helps


TestFlight beta review is typically faster than App Store review, but it can still take hours. Yeethook sends a Slack or Discord notification the moment your build is approved for external testing, so you can start distributing to testers immediately.


Common use cases


  • Notify your QA team when a build is approved for external TestFlight testing
  • Catch beta review rejections early so you can fix and resubmit
  • Track build expiration dates to avoid gaps in testing availability
  • Coordinate beta release cycles with your external tester community

Example payload

The state lives under oldExternalBuildState and newExternalBuildState, not the newValue or newState names the app version and build upload events use. relationships.instance points at the buildBetaDetails record rather than the build, so the build number has to be resolved separately.

{
  "data": {
    "type": "buildBetaDetailExternalBuildStateUpdated",
    "id": "4a9eacca-e53f-4006-85db-aa18c515663a",
    "version": 1,
    "attributes": {
      "oldExternalBuildState": "WAITING_FOR_BETA_REVIEW",
      "newExternalBuildState": "READY_FOR_BETA_TESTING",
      "timestamp": "2026-09-12T11:04:38.512Z"
    },
    "relationships": {
      "instance": {
        "data": {
          "type": "buildBetaDetails",
          "id": "ad7e6298-2570-4ca6-b3cc-f81788e40bdc"
        }
      }
    }
  }
}

What it looks like in Slack

Success

TestFlight 4821 ready for beta testing

Build
4821
External state
Ready For Beta Testing
Internal state
In Beta Testing
Min OS
17.0
Audience
App Store Eligible

The same event arrives with different values depending on what changed. Yeethook rewrites the headline to match:

  • WAITING_FOR_BETA_REVIEW→ TestFlight 4821 waiting for beta review
  • IN_BETA_REVIEW→ TestFlight 4821 in beta review
  • BETA_REJECTED→ TestFlight 4821 beta rejected
  • EXPIRED→ TestFlight 4821 expired

Enrichment with p8 key

With a p8 key, Yeethook enriches this event with the build number, the external and internal build states, the minimum OS version, and the build audience from the App Store Connect API.

Questions about build_beta_detail_external_build_state_updated

Why does my webhook parser miss the state on this event?

Attribute naming. This family uses newExternalBuildState and oldExternalBuildState, while app version events use newValue and build upload events use newState. Code that reads only newValue sees an empty change and logs nothing useful.

Does this event cover internal TestFlight testers?

No, it reports the external build state only. The Internal state row in the message comes from the enriched buildBetaDetails record, and Apple publishes no webhook for internal state changes, so the API is the only way to watch that one.

How is this different from BUILD_UPLOAD_STATE_UPDATED?

That event tracks Apple processing the uploaded binary and resolves to a buildUploads record; this one tracks external beta review and resolves to a buildBetaDetails record. A single upload normally produces both, in that order.

What arrives when a build expires?

EXPIRED comes through as an ordinary transition on this event, rendered with an hourglass at warning level — the same severity Yeethook gives BETA_REJECTED. The payload does not say how many testers had installed the build before it lapsed.

Get this event in Slack or Discord

Connect Yeethook to receive build_beta_detail_external_build_state_updated notifications in your team's Slack or Discord channels.

Get Started Free