Safari
Safari extensions ship through the App Store inside a wrapper app, not through an extension store. The submission unit is a signed .pkg installer containing the wrapper app, and Apple's App Store rules apply on top of the extension review. The platform runs the submission with the project's stored credentials; trigger it from the console's Stores tab, from an agent with extension_submit, or with POST /api/cli/stores/submit. See Publishing.
Credentials
The App Store Connect API authenticates with an ES256 JWT signed from a .p8 key. Signing the package needs certificates and profiles on top of the API key, so Safari holds nine secrets per project:
| Secret | Purpose |
|---|---|
| App Store Connect key ID | Identifies the .p8 key |
| Issuer ID | The API issuer from App Store Connect |
| Key, base64 | The .p8 key content |
App certificate .p12 | Signs the wrapper app |
| App certificate password | Unlocks that .p12 |
Installer certificate .p12 | Signs the .pkg |
| Installer certificate password | Unlocks that .p12 |
| Provisioning profile | For the wrapper app |
| Appex provisioning profile | For the extension appex |
The app's numeric Apple id resolves from the bundle id when it is not given. Add them from Stores, New, Safari in the console.
Signing
You do not need a Mac and you never install Xcode: signing happens in the platform's pipeline, inside an ephemeral keychain that exists only for the run. Certificates never land on a persistent machine.
Submitting
Submit from the Stores tab, or over the API:
curl -s -X POST https://www.extension.dev/api/cli/stores/submit \
-H "Authorization: Bearer $EXTENSION_DEV_TOKEN" \
-d '{"browsers":["safari"],"buildSha":"<sha>","channel":"stable"}'Two version values go with the upload, and the platform derives both:
| Value | Meaning |
|---|---|
| Short version | CFBundleShortVersionString, taken from the build's manifest version |
| Bundle version | CFBundleVersion, a build number the platform increments on every run |
Review is opt in
By default a Safari submission stops at TestFlight or draft. It does not enter App Store review until you ask. Promote the TestFlight build into review from App Store Connect when it is ready. The default is a safe mode; submitting for review is broad.
When it fails
- An unsigned or badly signed
.pkgis rejected at upload, not at review. Check the certificate and profile secrets first. - A
CFBundleVersionthat does not increase is rejected at upload. Bump the bundle version, not only the short version. - ES256 authentication failures are the key trio: key ID, issuer ID, and the base64 key must all come from the same App Store Connect key.
- The preflight,
dryRunon the submit call, reports credential health and the console page that fixes a blocked store.
Last verified against the App Store Connect API on 2026-07-27. Submission outcomes are subject to App Store review and policy.
Next
- Executables to ship a launcher outside the App Store
- Publishing overview for the three ways in
