FunnelHound / Guides / The .p8 file

The App Store Connect .p8 file: what it is and where it goes

The .p8 file is the private half of an App Store Connect API key: a small PEM text file named AuthKey_<KEYID>.p8, handed to you exactly once when the key is created. Every tool that talks to Apple on your behalf, from fastlane to a Python script to FunnelHound, signs a short-lived token with it. Lose it and there is no second download, only a new key.

AuthKey_2X9R4HXF34.p8 -----BEGIN PRIVATE KEY----- MIGTAgEAMBMGByqGSM49AgEGCCqGSM49 AwEHBHkwdwIBAQQg... ...4 lines, about 250 characters -----END PRIVATE KEY----- PKCS#8 · EC P-256 · plain text Key ID 2X9R4HXF34 public, also in the filename Issuer ID 57246542-96fe-1a63-… public, one per team
One secret file and two public IDs. The file signs, the Key ID says which key, the Issuer ID says which team.

What is inside

Open it in any text editor: a BEGIN PRIVATE KEY line, four lines of base64, an END PRIVATE KEY line. That is a PKCS#8 container holding an elliptic-curve private key on the P-256 curve, the curve the ES256 signature algorithm uses. There is no password on it, which is why the file itself is the secret. The matching public key stays with Apple; when a tool signs a token with your .p8, Apple checks the signature against that public key and trusts the request up to the key's role.

The number in the filename is the Key ID. Tools that take a folder instead of a path find the right key by that name, so renaming the file is the fastest way to break altool and notarytool. The Issuer ID is not in the file anywhere; it is read off the API page and passed alongside.

One download, ever

App Store Connect shows a Download API Key link once, in the row of the freshly created key, with a warning that it will not be offered again. Click it, store it, and only then leave the page. Losing the file means revoking the key and creating another, then rotating the Key ID in every tool. Apple does this on purpose: a private key that can be re-downloaded is a private key that Apple holds, and the point of the scheme is that it does not. The step-by-step for creating the key, including which role to pick, is in the API key setup guide.

Where each tool expects it

the secret AuthKey_….p8 fastlane app_store_connect_api_key xcodebuild -authenticationKeyPath altool · notarytool ~/.appstoreconnect/private_keys CI secret base64, decoded per job FunnelHound imported once, iOS Keychain
Five consumers, one file. Each wants the Key ID and Issuer ID next to it, each in its own spelling.
ToolHow it takes the .p8Notes
fastlaneapp_store_connect_api_key(key_id:, issuer_id:, key_filepath:), or key_content: with is_key_content_base64: true; env vars APP_STORE_CONNECT_API_KEY_KEY_ID, _ISSUER_ID, _KEYThe returned hash feeds pilot, deliver, match and sigh. Prefer the base64 content form on CI.
xcodebuild-allowProvisioningUpdates -authenticationKeyPath ./AuthKey.p8 -authenticationKeyID KEYID -authenticationKeyIssuerID UUIDLets archive and export talk to Apple without a logged-in Xcode account.
altool, notarytool--apiKey KEYID --apiIssuer UUID, file looked up in ./private_keys, ~/private_keys, ~/.private_keys or ~/.appstoreconnect/private_keys; notarytool also accepts --key path --key-id --issuerFilename must stay AuthKey_KEYID.p8 for the folder lookup to work.
Transporter appSign in with API key: paste Issuer ID, Key ID, select the fileOnce per Mac.
Xcode CloudNothingApple's own service signs internally; no .p8 to manage.
Scripts (Python, Node, Swift)Read the file, sign an ES256 JWT with kid = Key ID, iss = Issuer ID, aud = appstoreconnect-v1, expiry under 20 minutesWorked example in the Python guide.
FunnelHoundImport once from Files or the clipboard; stored in the iOS KeychainSigns on the device, never uploads the key anywhere.

Storing it without regretting it

The other .p8: push keys

developer.apple.com → Certificates, Identifiers & Profiles → Keys also produces a file called AuthKey_KEYID.p8, in the same PEM format, for Apple Push Notification service and for Sign in with Apple. Same shape, different key, different companion: the push key travels with your ten-character Team ID, the App Store Connect key with a UUID Issuer ID. A push provider asking for a Team ID will reject an API key, and fastlane will reject a push key, each with an error that mentions neither fact. When two .p8 files sit in the same Downloads folder, the companion ID is how you tell them apart.

Did it work? Thirty seconds

Sign a token and call GET https://api.appstoreconnect.apple.com/v1/apps. A JSON list of your apps means the file, Key ID and Issuer ID agree. A 401 means one of the three is wrong or the token expired; a 403 means the key's role is too low for that endpoint. The setup guide has the curl one-liner.

Import the key once, read the funnel forever

FunnelHound takes the .p8, Key ID and Issuer ID, keeps them in the iOS Keychain, and signs every request on your iPhone. Impressions, page views, installs, deletions and proceeds for all your apps, with no server holding your key.

Get FunnelHound

Share this on X

Data notes: tool flags per fastlane, Xcode and notarytool documentation as of 2026; folder lookup paths per Apple's altool and notarytool manuals. 2X9R4HXF34 and the Issuer ID fragment are placeholders. Token lifetime must stay under 20 minutes or Apple rejects it. Verify flag spellings against the tool version you run; fastlane in particular renames options between majors.