Skip to main content
Shipping an extension to the Chrome Web Store, Firefox Add-ons, and Edge Add-ons is one journey with the same shape on every store: register a developer account, create the listing once, get API credentials, and automate every submission after that. This page walks the whole journey. The per-store guides cover each credential portal in detail:

The journey

1

Register the store accounts

Each store requires a developer account before anything else works. See account prerequisites below for the fee, agreement, and enrollment each store demands.
2

Create each listing once by hand

The Chrome and Edge APIs cannot create a new listing. Upload the first zip manually in the store dashboard. That first upload is what creates the extension ID (Chrome) and the Product ID (Edge) that automation needs. Firefox can create a new unlisted add-on through the API; a listed add-on still needs a first manual submission.
3

Get API credentials per store

Follow the per-store guides linked above. Each guide names the exact portal page, shows what every value looks like, and lists the expiry rules.
4

Enter the credentials

On the platform track, open your project on extension.dev, go to Settings, then Stores, and use the guided setup dialog. On the direct track, run npx extension-deploy init to write a .env.submit file, or set the environment variables in your own CI.
5

Author STORE.md

Write the STORE.md metadata file before the first submission. Submission tooling reads it and attaches reviewer notes, release notes, and certification notes automatically. Without it, submissions go out noteless.
6

Submit

Submit from the project’s release flow on extension.dev, from your own CI with @extension.dev/deploy, or from an AI agent through the MCP server. Dry-run first: a dry run verifies credentials and zips without uploading anything.
7

Track the review

A successful submission means the store accepted the upload and queued it for review. Review is a third-party decision. The platform polls review status and reports it in the project dashboard; it never claims a listing is live before the store confirms it.
8

Handle a rejection

Read the failure reason the store returned, fix the cause, and record both in the version history section of STORE.md so the next submission does not repeat the mistake. Vague permission justifications are the most common rejection on every store.

Account prerequisites

Where credentials live

Store credentials on the platform track are per project, not per workspace. Each project gets a managed GitHub mirror repository. When you save store credentials in the project’s Settings, under Stores, the platform writes them as GitHub Actions repository secrets on that project’s mirror (names like STORE_CHROME_CLIENT_ID and STORE_FIREFOX_API_KEY). Non-secret identifiers, such as the extension ID and the publisher ID, go into the mirror’s _extension-dev/settings.json. Three consequences follow from that model:
  • Isolation. One project’s credentials can never reach another project’s pipeline. See Agencies and multiple clients for what this means when you manage several store accounts.
  • Write-only storage. Saved secrets cannot be read back, by you or by the platform UI. To re-run a live connection test, re-enter the secret values.
  • Per-project rotation. Rotating a credential for one project touches nothing else.
On the direct track, you hold the credentials yourself. The .env.submit file that npx extension-deploy init writes is the per-project credential file for that track. Keep it out of git.

Platform track and direct track

What a submission needs, per store

Next steps