Skip to content

Store releases ​

A store submission is the release of that build for that browser. Submitting a build creates the release row for that store and version, and every store act after it (publish, the store's review, a withdrawal, a newer version) advances the same row. Reach for this page when you need to know what is live in each store, which record says so, and what extension_submit writes.

Channels stay the way testers get a build: promoting a build pins a channel to it, and that is a separate record. Nothing has to be promoted before a store submission, and a store submission never moves a channel.

Quick start ​

GET /api/projects/{id}/releases

The answer carries storeReleases, one row per store and version, beside the channel rows it always carried. summary.activeReleases counts the rows at live; summary.liveChannels counts the channels every browser's promote run proved live.

From an agent, extension_release_status {include: ["history"]} answers value.storeReleases with the same rows, and {include: ["stores"]} carries each store's newest row as release.

How it works ​

The row ​

One row per store and version. Several submissions of one version (a Chrome draft uploaded twice, two TestFlight builds of one App Store version) advance one row; the newest record wins.

FieldMeaning
id<store>:<version>
storechrome, firefox, edge or safari
browserThe browser the store serves, the same word
versionThe version the store names: storeVersion.packaged when the platform stamped one, else the submission's version
buildShaThe seven character sha of the build the row stands on
stateuploaded, in-review, live, rejected, withdrawn or superseded
storeWordThe store's own word for that version as last read (PUBLISHED, InReview, WAITING_FOR_REVIEW), empty when the platform holds none
readAtWhen that word was read
sourceWhere it was read: publish-answer (the store's answer to a publish, cancel or review send), poll (the platform's store poller), run (the store's answer to the upload, read by the store run), or inferred (no store word; the state was inferred from the recorded submission)
visibilitypublic or unlisted, only when the store said so (Chrome's publish answer or poll); absent otherwise. A live row with no visibility is live for an audience the platform has not read
storeVersion{packaged, displayed, source, buildNumber?} when the platform stamped the package
submissionId, submittedAt, updatedAtThe submission that advanced the row, and when
storeUrl, failureReasonThe listing, and the store's refusal when it refused the last act
channelThe channel the build was promoted to, when one pins it

A row whose source is inferred says what the platform recorded, not what the store said. It is shown as such and never grounds a next step: an agent reads the store again before acting on it.

Visibility is read, never inferred. A Chrome item Chrome calls PUBLISHED with visibility unlisted, or a Firefox version AMO signed for self distribution, is live for its audience only, and a row never reads it as public. Where no store said who can find the version, visibility is absent and the row says nothing about it.

What a submit does to the row ​

A submit uploads the build. The row appears at uploaded once the platform's record says the store took the package. A run that failed before any store step, and a submission the platform dispatched and has no answer for yet, create no row: the submissions page shows them, the Releases page does not.

What each store's acts do to the row ​

StoreActRow
ChromeUpload a draftuploaded
ChromePublish (send to review)in-review with Chrome's word
ChromeChrome approves and publisheslive (PUBLISHED)
ChromeChrome rejectsrejected
ChromeCancel reviewwithdrawn; the draft stays on the dashboard
EdgeUpload a draftuploaded
EdgePublish (certification)in-review (InReview); Edge locks the product until certification ends
EdgeCertification passes and the product serves the versionlive
EdgePartner Center refuses the publishstays uploaded with failureReason in Microsoft's words
FirefoxUnlisted upload, signedlive for self distribution once AMO signed it
FirefoxListed uploadin-review (awaiting review)
FirefoxAMO approveslive; AMO rejects: rejected
FirefoxA newer version arrives before reviewthe older row superseded, AMO's own word
SafariTestFlight uploaduploaded with the build number
SafariSend to App Reviewin-review (WAITING_FOR_REVIEW, IN_REVIEW)
SafariApple approveslive; Apple rejects: rejected
SafariRemove from reviewwithdrawn (DEVELOPER_REJECTED); the build stays on TestFlight

Across stores, the last rule is the same: when a newer version of one store reaches live, the older live row of that store reads superseded. That transition is inferred, since no store says it in one word, and the row says so in source.

How the state is read from the record ​

The platform's submission record carries status, the store's answers (storeUpload, storeReview, publish, cancel) and the version it stamped. The row is read from them in this order:

RecordState
draft, uploadeduploaded
submittedin-review
approved, publishedlive
rejectedrejected
supersededsuperseded
a cancel the store accepted, on a record that is no longer in reviewwithdrawn
failed while the store holds the package (storeUpload or storeSubmissionId)uploaded with failureReason
failed before the store, pending, dry_run, unknownno row

storeWord, readAt and source come from the newest of storeReview and storeUpload; with neither, source is inferred.

What counts as active ​

summary.activeReleases is the number of rows at live. One store has at most one live row, the newest version it serves. summary.liveChannels is what activeReleases counted before: channels whose every browser's promote run concluded success. The two are different facts and are shown apart.

What the Releases page shows ​

The console Releases page lists the store rows in a Stores section: store, version, build, state, the store's word with when and where it was read, and a link to the submission. The overview cards read Live in stores from activeReleases and Live channels from liveChannels. While every reading is zero and the history is empty, the cards step aside.

What the MCP answers ​

extension_release_status {include: ["history"]} answers value.storeReleases and value.summary (activeReleases, liveChannels, channels), and its hint leads with what is live where. {include: ["stores"]} carries each store's newest row as release on that store, so "is it live on Chrome" reads the same answer on both.

extension_submit sends no channel. Its answer's value.channel is the channel the platform found the build promoted to, when one pins it; a submit of a build no channel pins answers no channel.

The submission's channel ​

A store submission used to carry channel: "stable", a label that named no channel and changed nothing uploaded. A submission's channel is now the channel whose pin for that browser is the build submitted, read from the project's channel pins, else absent. POST /api/cli/stores/submit and POST /api/projects/{id}/stores/{store}/submissions accept channel in the body and ignore it, and the store run receives channel only when such a pin exists. The approval of a submit binds browsers and buildSha.

Reference ​

Store release row ​

FieldType
id<store>:<version>
store, browserchrome, firefox, edge, safari
version, buildShastring
stateuploaded, in-review, live, rejected, withdrawn, superseded
storeWord, readAtstring, empty when the platform holds no store word
sourcepublish-answer, poll, run, inferred
visibilitypublic or unlisted, optional, only from the store's own word
storeVersion{packaged, displayed, source, buildNumber?}, optional
submissionId, submittedAt, updatedAtstring
storeUrl, failureReason, channelstring, optional

Summary ​

FieldCounts
activeReleasesStore rows at live
liveChannelsChannels every browser's promote run proved live
channelsChannels that exist, shipped or not

When it fails ​

  • A store is live and the Releases page reads no live store. The platform's record for that submission has not read the store's word yet. Ask for a store read with extension_release_status {include: ["stores"], refresh: ["<store>"]} or the Refresh control on the submission, then read again.
  • The row reads inferred. The platform recorded the submission and holds no store word for it. Read the store before acting on the row.
  • A submission the record says failed shows no row. The store never received the package. The submissions page carries the failed step and its last log lines.
  • channel is absent on a new submission. No channel pins the build that was submitted. Promote the build to a channel first when the records should match, or leave it: the store release stands on its own.
  • A live row carries no visibility. The store has not said who can find the version. Read it in the store's dashboard before calling it public.

Next ​