PushMesh
Sign in Request access
Open section navigation

Index

Delivery credentials

What you need in hand before the first push goes out — the Firebase service account for Android and the APNs .p8 key for iOS, field by field, including Apple's environment trap.

Delivery credentials

PushMesh does not deliver a push on its own: the notification is put on the device by Google (FCM) on Android and by Apple (APNs) on iOS. To speak to them on behalf of your application, the service needs a credential of yours.

This is the step that stalls most integrations on day one, and it has a distinctive symptom: the send returns 200, recipients looks right, and the result reads successful: 0 with remaining: 0. The audience existed; the message had no way out.

Credentials are registered in the dashboard, at https://app.pushmesh.io. No public route accepts a delivery credential — neither to store one nor to read one back. A push signing key is the kind of secret that should not travel through an automated integration, so it only goes in through the screen.

This page exists so you know what to have in hand before creating an account, and so you recognise the right credential when you see it.


What each platform requires, in one table

PlatformWhat you provideWhere it comes from
Android (and WebPush)the Firebase service account .json fileFirebase Console
Android (optional)the Android app’s google-services.jsonFirebase Console
iOSthe APNs .p8 key + Key ID + Team ID + Bundle ID + environmentApple Developer

You only need the platform you actually serve. An Android-only application never has to touch APNs.


1. Android — the Firebase service account

What it is (and what does not work)

What the service accepts is the service account JSON file from your Firebase project. It is the file the console generates under:

Firebase Console → Project settings → Service accounts → “Generate new private key”

The legacy server key does not work. That long string older applications kept in an environment variable belongs to a retired protocol. If what you have is a single line of text rather than a JSON file with keys and values, it is the wrong credential — generate a new one through the path above.

The fields that are checked

The file is validated at registration time, field by field, and every problem comes back named instead of turning into a delivery failure weeks later:

FieldWhat it must beTypical failure
project_ida non-empty stringmissing ⇒ the file is not a service account
client_emailan e-mail address (contains @; ends in .iam.gserviceaccount.com)missing or hand-edited
private_keya PEM containing the BEGIN PRIVATE KEY blockline breaks (\n) stripped while copying

Do not edit the file. The most common failure here is pasting the private_key without its line breaks, or running it through an editor that “tidies up” the text. Paste the whole content exactly as Google delivered it.

After registering

  • The credential is encrypted on the server. It never comes back through any screen or any route.
  • The dashboard offers a connection test: it requests an access token from Google using your credential and shows which project answered. Run it before your first send — it is the difference between finding the problem now and finding it mid-campaign.
  • Revoking stops delivery immediately. Deleting the credential from PushMesh halts this application’s sends until you configure another one; it does not delete anything in Firebase. If the key leaked, revoke it in both places.

Optional: the google-services.json

Besides the service account (which sends), there is a second file that only identifies the project to the Android application. Pasting the google-services.json into the dashboard once means your app no longer has to ship the file: the SDK fetches those values from the server at boot.

Firebase Console → Project settings → Your apps → download the google-services.json for the Android app

There are five values, and they are public by design — they already ship inside every published APK. They are not a credential, which is why the route that serves them asks for none:

curl https://api.pushmesh.io/api/v1/apps/APP_ID/firebase_params
{
  "android": {
    "project_id": "my-firebase-project",
    "sender_id": "123456789012",
    "app_id": "1:123456789012:android:abcdef0123456789",
    "api_key": "AIza…",
    "package_name": "com.example.myapp"
  },
  "ios": null
}

Until they are configured, the same route answers 200 with "android": null.

Mind the name. The api_key inside the android block is the Firebase key, public, taken from Google’s file. It is not your application’s PushMesh key (pm_live_…), which must never leave your server. They are different things with similar names, and mixing them up is the most expensive mistake on this page.

If your Firebase project has more than one Android app, the dashboard asks for the package_name to pick which one to use — without it, storing the wrong app would make the SDK initialise against a different project. The Android app identifier always has the form 1:<number>:android:<hash>.

Route details in Applications and keys.


2. iOS — the APNs .p8 key

iOS requires five pieces of information, and all of them are shape-checked before being stored.

FieldRequired formatWhere to get it
.p8the file contents, with the BEGIN PRIVATE KEY blockApple Developer → Certificates, IDs & Profiles → Keys (check “Apple Push Notifications service”)
Key IDexactly 10 alphanumeric charactersthe same Keys screen
Team IDexactly 10 alphanumeric charactersApple Developer → Membership
Bundle IDreverse-dns (com.yourcompany.app)Xcode / App Store Connect
Environmentsandbox or productionyour choice — read the next section

The .p8 can only be downloaded once. Apple hands the file over when the key is created and never again. If you do not have it, there is no way to recover it: generate another key.

On save, the credential is encrypted on the server. The dashboard offers a connection test that validates the key against Apple itself and shows the accepted bundle and environment.

Revoking deletes the credential from PushMesh and stops iOS deliveries immediately, without touching anything in Apple Developer.

The environment trap — read this before blaming the platform

Apple keeps two separate worlds, and a push token from one is worthless in the other.

The build decides, not the server:

How the app reached the deviceToken environment
run straight from Xcodesandbox
published to the App Storeproduction
distributed through TestFlightproduction

TestFlight being production is the most common mistake of all: the person is testing, therefore assumes sandbox, and no push ever arrives.

The same .p8 key works in both worlds — all that changes is where the service sends. That is why the environment is an application setting you can switch at any time in the dashboard, without re-uploading the key, and the switch takes effect immediately.

When the key is not valid in the chosen environment, Apple answers BadEnvironmentKeyIdInToken, and the error that reaches you says exactly that: check whether the application’s environment matches the environment the APNs key was created for.


3. How to know it worked

Once registered, send to one real device and read the result. The reading table is short:

What you seeWhat it means
good recipients, successful: 0, remaining: 0the delivery credential is missing or wrong
good successful, high failedthe tokens are dead, or (on iOS) they were issued in the other environment
good successful, recebidos: 0the push went out; what did not come back is the proof — notification permission, device offline, or a custom client that never calls the receipts route
good successful, good recebidosyou are done.

The full walkthrough, with commands, is in Getting started.


Checklist before creating an account

Android

  • Access to the Firebase Console of the project that already issues your app’s tokens
  • Permission to generate a service account private key
  • (Optional) The Android app’s google-services.json

iOS

  • An Apple Developer account with access to Keys
  • The APNs .p8 file — or permission to generate a new one
  • Key ID, Team ID and Bundle ID at hand
  • The answer to “does this build come from Xcode, the App Store or TestFlight?”

See also

TopicPage
from zero to your first push with a receiptGetting started
the public route for Firebase parametersApplications and keys
what changes when you switch providersMigrating from another provider
retention and personal dataData and privacy