Skip to content

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:

SecretPurpose
App Store Connect key IDIdentifies the .p8 key
Issuer IDThe API issuer from App Store Connect
Key, base64The .p8 key content
App certificate .p12Signs the wrapper app
App certificate passwordUnlocks that .p12
Installer certificate .p12Signs the .pkg
Installer certificate passwordUnlocks that .p12
Provisioning profileFor the wrapper app
Appex provisioning profileFor 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:

bash
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:

ValueMeaning
Short versionCFBundleShortVersionString, taken from the build's manifest version
Bundle versionCFBundleVersion, 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 .pkg is rejected at upload, not at review. Check the certificate and profile secrets first.
  • A CFBundleVersion that 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, dryRun on 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