When your app sends a push notification, it doesn’t travel straight from your WordPress site to a phone — it goes through Apple or Google first. Apple runs the Apple Push Notification service (APNs) for iOS devices; Google runs Firebase Cloud Messaging (FCM) for Android devices. Think of them as gatekeepers: they’re the only ones allowed to wake a phone with a notification, and they won’t do it for just anyone.
That’s why push notifications need credentials. A credential is how MAM Suite proves to Apple and Google that it’s allowed to send notifications on behalf of your specific app — without the right one, the gatekeeper rejects the message and nothing reaches the device. Knowing what these credentials are, and how they differ from a device token, is the single most useful thing to understand here, whether you’re an admin pasting keys into a settings screen or a developer reading delivery errors.
Here’s what’s ahead: the three pieces involved — the APNs key, the FCM service account, and the device token — and then how a notification actually finds its way to one phone.
The two gatekeepers, and why there are two
Your MAM Suite app is a real native app on both platforms, so it has to satisfy both gatekeepers separately — there’s no shared “send a push” mechanism that works across Apple and Google. Each platform has its own credential format, its own authentication flow, and its own delivery endpoint. MAM Suite keeps the iOS path and the Android path completely separate in code for exactly this reason, and the credentials you provide reflect that same split:
- iOS notifications authenticate to Apple using an APNs key.
- Android notifications authenticate to Google using a Firebase service account.
You’ll set up both because your app ships to both stores. Configure only one, and only that platform’s users receive notifications — the other one just fails quietly at send time.
The APNs key (iOS)
Apple’s modern way to authenticate is a token-based key — a small file with a .p8 extension. You generate it once in your Apple Developer account, and unlike the older push certificates, it doesn’t expire. In MAM Suite, the iOS push credential is actually four pieces of information traveling together:
| Piece | What it is |
|---|---|
The .p8 key file |
The private key that signs Apple’s authentication tokens. This is the secret. |
| Key ID | A short identifier Apple assigns to that key, so Apple knows which key signed the request. |
| Team ID | Identifies your Apple Developer team / account. |
| Bundle ID | Identifies your specific app (for example, com.yourcompany.yourapp). |
In the code, these map to the WordPress options ios_pn_key_id, ios_pn_team_id, and ios_pn_app_bundle_id, plus the .p8 file itself, which MAM Suite stores under its pemcerts directory and references by the ios_pn_pem_certs option. The class MAM_IosCredentials loads all four and will refuse to send if any one of them is missing.
Behind the scenes, MAM Suite uses these four pieces to build a short-lived signed token for each batch of notifications — you’ll never have to think about that token yourself; it’s generated automatically from the key. From where you sit, the .p8 file plus those three IDs are your iOS credential.
One subtlety worth knowing: standard alert pushes and VoIP pushes (the kind that power incoming-call screens) use separate credentials and separate device tokens on iOS. A device registered for one will not receive the other. Most apps only need the standard path.
The FCM service account (Android)
Google’s equivalent is a service account — think of it as a robot user that belongs to your Firebase project and is allowed to send messages on its behalf. You’ll download it from the Firebase console as a single JSON file, which contains (among other things) a client_email (the robot’s address) and a private_key (its secret). MAM Suite also needs your Firebase project ID, so it knows which project those messages belong to.
MAM Suite uses the modern FCM v1 API, not the old “server key” approach Google has deprecated — and the practical difference shows up in how authentication works. With v1, there’s no static key to simply present. Instead, each time MAM Suite needs to send, the class MAM_FirebaseJwtSigner does the following:
- Reads the service-account JSON and pulls out the private key.
- Builds a small signed token (a JWT) claiming the right to send Firebase messages, scoped to
firebase.messaging. - Exchanges that signed token with Google for a short-lived access token that lasts about an hour.
- Sends the actual notification with that access token attached.
All of that happens automatically, behind the scenes. You only ever supply the JSON file and the project ID — MAM Suite handles the signing and token exchange on every single send. The takeaway: your Android credential is one JSON file plus your project ID, and MAM Suite keeps the working token renewed for you.
Device tokens are not credentials
This is the distinction that trips people up most, so let’s be explicit about it.
A credential (the APNs key, the FCM service account) belongs to you — it proves your app’s identity to the gatekeeper. There’s one set per platform, and it rarely changes.
A device token belongs to one installation of your app on one phone. It’s a long string that Apple or Google hands to your app the first time it launches and the user agrees to notifications — the gatekeeper’s home address for that specific device. It answers “which phone?”, not “are you allowed to send?”
In MAM Suite, your app reports its token back to your WordPress site on launch, and the site stores it as user meta on that person’s account:
| What is stored | Meta key |
|---|---|
| iOS APNs token | mam_app_ios_pn_token |
| Android FCM token | mam_app_android_pn_token |
| iOS VoIP token (separate path) | mam_ios_voip_token |
| Opt-in flag | push_enabled |
| Last delivery status | push_status |
There’s no separate table for this — tokens just live alongside the rest of the user’s profile data. At send time, MAM Suite reads the tokens for whoever you’re notifying and hands them off to the right platform sender.
Two things follow from this, and together they explain most of the real-world behavior you’ll run into:
- Tokens go stale. When a user reinstalls the app, restores from a backup, or switches phones, the old token stops working. The gatekeeper rejects it — Apple replies
BadDeviceToken, Google repliesUNREGISTEREDorNOT_FOUND— and MAM Suite flags that token as invalid so it can be cleaned up. A failed send to one device is normal, and it doesn’t mean your credentials are broken. - No token means no notification. If someone never opened the app, never granted notification permission, or is signed out, there’s simply no token on file — and nothing can reach them, no matter how perfect your credentials are.
How one notification reaches one phone
Now let’s put the pieces together and follow a single push on its journey from your site to one device:
- A notification gets triggered. Something in your app or your admin — a new order, a special offer, an admin “send a test” — fires off a notification with a title, body, and optional data.
- MAM Suite looks up the recipients’ tokens. For each targeted user, it reads their stored iOS and Android tokens from user meta — naturally splitting everyone into an iOS group and an Android group based on which token they have.
- The right sender authenticates with the gatekeeper. For iOS, MAM Suite signs a token using your
.p8key and the three IDs. For Android, it signs a JWT from your service-account JSON and exchanges it for a Google access token. - The notification is handed to the gatekeeper, addressed by device token. iOS messages go to Apple’s APNs over HTTP/2; Android messages go to Google’s FCM v1 endpoint, one request per token.
- The gatekeeper delivers — or reports a problem. A success means Apple or Google has taken responsibility for waking the device. A rejection for a specific token (stale, unregistered) gets recorded so that token can be retired. A rejection of the whole request usually points to a credential problem, not a device problem.
One detail from step 4 is worth calling out, because it explains a common iOS gotcha: Apple runs two environments, production and sandbox, and any given device token belongs to exactly one of them, depending on how the app was built. MAM Suite tries production first and automatically retries against sandbox if production rejects the token — so both test builds and store builds work without you ever having to choose an environment by hand.
Why this matters when something goes wrong
Credentials and tokens answer different questions — “are you allowed?” versus “which phone?” — so a problem with one looks nothing like a problem with the other. Knowing which is which saves you a lot of troubleshooting time:
- Nobody on a platform receives anything. That points at the credential — the APNs key or service account is missing, wrong, or expired, and MAM Suite can’t authenticate at all.
- Most people get it but a few don’t. That points at tokens — those few have stale or missing ones, whether from reinstalling, signing out, or never opting in.
- iOS works in testing but not in the store (or vice versa). That’s the production/sandbox split — generally handled automatically, but the first place to check if only one kind of build is affected.
Where to go next
- For the step-by-step of generating an APNs key and a Firebase service account and entering them into MAM Suite, see the push credential setup recipe (iOS APNs and Android FCM).
- For what a notification can contain (titles, deep-link targets, silent/data pushes) and how it is composed, see the push notification payload reference.
- For the admin experience of composing and sending a notification to your users, see the notifications manager overview.
