Push Notifications (APNs)
This guide covers how iOS push notifications are configured for Pivot Mobile across all environments.
Overview
Pivot uses Firebase Cloud Messaging (FCM) to send push notifications. For iOS, FCM requires an APNs Authentication Key (.p8) to communicate with Apple's Push Notification service.
APNs Key Configuration by Environment
Each Firebase project needs the APNs key configured in Firebase Console.
| Environment | Firebase Project | Bundle ID | APNs Key ID |
|---|---|---|---|
| Dev | pivot-dev-59310 | jobs.pivot.dev | GH9LN6PFT7 |
| Dev 2 | pivot-dev-2 | jobs.pivot.dev2 | GH9LN6PFT7 |
| Staging (QA) | pivot-not-production-project | jobs.pivot.qa | T993V6JQN3 |
| Production | pivot-inc | pivot-studio-inc | 5V69C35FSJ |
Team ID (all environments): 2VZTF24GKY
Where Keys Are Stored
APNs keys and configuration are stored in the pivot-devops repository:
pivot-devops/github/secrets/
├── apns-auth-key.p8 # APNs Authentication Key (dev environments)
├── env.dev # Dev environment variables (includes APNs config)
├── env.dev2 # Dev2 environment variables
├── env.default # Staging environment variables
└── env.production # Production environment variables
Environment Variables
Each env file includes:
# APNs Push Notifications (Firebase Cloud Messaging)
APNS_KEY_ID=GH9LN6PFT7 # 10-character key identifier
APNS_TEAM_ID=2VZTF24GKY # Apple Developer Team ID
APNS_BUNDLE_ID=jobs.pivot.dev # iOS Bundle ID
Setting Up APNs for a New Environment
Step 1: Generate APNs Key (if needed)
If you need a new APNs key:
- Go to Apple Developer Portal - Keys
- Click + to create a new key
- Name it (e.g., "Pivot Push Notifications Dev")
- Enable Apple Push Notifications service (APNs)
- Click Continue, then Register
- Download the .p8 file immediately (you can only download it once!)
- Note the Key ID (10 characters)
You can only download the .p8 file once. Store it securely in pivot-devops/github/secrets/.
Step 2: Upload to Firebase Console
-
Go to Firebase Console for your project:
- Dev: https://console.firebase.google.com/project/pivot-dev-59310/settings/cloudmessaging
- Dev2: https://console.firebase.google.com/project/pivot-dev-2/settings/cloudmessaging
- Staging: https://console.firebase.google.com/project/pivot-not-production-project/settings/cloudmessaging
- Production: https://console.firebase.google.com/project/pivot-inc/settings/cloudmessaging
-
Scroll to Apple app configuration
-
Select your iOS app
-
Under APNs Authentication Key, upload to BOTH slots:
- Development APNs auth key - for Xcode/TestFlight builds
- Production APNs auth key - for App Store builds
-
For each upload, provide:
- The
.p8file - Key ID (10 characters)
- Team ID:
2VZTF24GKY
- The
Step 3: Update Environment Variables
Add the APNs configuration to the appropriate env file in pivot-devops/github/secrets/:
# APNs Push Notifications (Firebase Cloud Messaging)
APNS_KEY_ID=YOUR_KEY_ID
APNS_TEAM_ID=2VZTF24GKY
APNS_BUNDLE_ID=your.bundle.id
Troubleshooting
Push notifications not working on iOS
- Check Firebase Console - Verify APNs key is uploaded for the correct environment
- Check Key ID - Ensure the Key ID matches the .p8 file
- Check Team ID - Should be
2VZTF24GKYfor all environments - Check Bundle ID - Must match the iOS app's bundle identifier
"InvalidProviderToken" error
This usually means:
- Wrong Key ID configured
- Wrong Team ID configured
- .p8 file doesn't match the Key ID
Push works in development but not production
Firebase has separate APNs slots for development and production. Ensure BOTH are configured:
- Development APNs auth key (for Xcode, TestFlight)
- Production APNs auth key (for App Store)
Important Notes
-
One .p8 key works for both sandbox and production - The same key file can be uploaded to both APNs slots in Firebase
-
Keys don't expire - Unlike APNs certificates (.p12), authentication keys (.p8) don't expire
-
Maximum 2 keys per account - Apple allows up to 2 APNs keys per developer account
-
Keys are account-wide - One key can be used across multiple apps/bundle IDs
-
Never commit .p8 files to public repos - Store them only in
pivot-devops/github/secrets/(which is gitignored)