Skip to main content
Courier integrates with many different push providers. Each provider may have specific requirements for delivering a message to a recipient, such as device tokens or provider-specific profile fields.

Available Push Providers

ProviderDescription
Apple Push Notifications (APNS)iOS/macOS push via APNS with P8/P12 auth and Courier Mobile SDK support
Firebase Cloud Messaging (FCM)Android/iOS/Web push via Google FCM with Courier Mobile SDK support
ExpoCross-platform push for Expo/React Native apps
OneSignalMulti-platform push via OneSignal’s notification platform
AirshipEnterprise push via Airship (formerly Urban Airship)
Pusher BeamsPush via Pusher Beams to users or interest groups
PusherReal-time messaging via Pusher Channels
MagicBellIn-app notifications via MagicBell
PushbulletCross-device push via Pushbullet
BeamerIn-app changelog and push notifications via Beamer
NowPushCross-platform push via NowPush
Can’t find a provider? Open up a chat on the Courier site, or email support@courier.com

Push Channel Override

Push channel overrides allow you to set the body, clickAction, data, icon, and title of a push notification. Data structure for the push channel override:
{
  "message": {
    "channels": {
      "push": {
        "override": {
          "body": "",
          "clickAction": "",
          "data": "",
          "icon": "",
          "title": ""
        }
      }
    }
    //... rest of message
  }
}

Data Mapping

All push channels have the ability to explicitly turn on data mapping. Data mapping can be useful to help limit how much data is passed to the push provider. For example, you can either pass the entire data payload as
data: request("data")
or explicitly choose which values to pass down:
data: {
  "firstName": data("firstName"), // accesses the data object
  "email": profile("email"), // accesses the profile object
  "template": request("template") // accesses the entire request received.
}

Tracking

Courier will attach a trackingUrl for all push requests that allow the state of the push notification to be updated. This is automatically done via the Courier Mobile SDKs, but you can control it manually like this:

Example Message

{
  "message": {
    "data": {
      "trackingUrl": "https://api.courier.com/e/123_channelTrackingId"
      // other data attributes
    }
    // other messages attributes
  }
}

Example Request

fetch("https://api.courier.com/e/123_channelTrackingId", {
  method: "POST",
  headers: {
    "X-Courier-Client-Key": "YOUR_COURIER_CLIENT_KEY",
  },
  body: JSON.stringify({
    event: "DELIVERED", // CLICKED or DELIVERED
  }),
});

Provider-Specific Tracking

Different push providers include the trackingUrl in different parts of their payload:

Airship

Courier will send trackingUrl in global_attributes data bag when you receive push notification in your client application.

APN (Apple Push Notifications)

trackingUrl will be part of data attribute in incoming payload when you receive push notification in your client application.

Firebase

trackingUrl will be part of data attribute in incoming message payload when you receive push notification in your client application.

Expo

trackingUrl will be part of data attribute in incoming payload when you receive push notification in your client application.

Pusher

trackingUrl will be part of data attribute in the incoming payload when you receive push notification in your client application.

Targeting Specific Devices

If a user has multiple push tokens registered (e.g., a desktop app and a mobile app), you can target a subset of their tokens at send time. This is useful when you want to send different notifications to different platforms, or when multiple apps share the same push provider project. This requires two steps: tagging tokens with an app identifier when you register them, and filtering by that identifier when you send.

Tag tokens at registration

When you store a token via the Token Management API, set device.app_id to identify which app or platform the token belongs to:
curl --request PUT \
  --url https://api.courier.com/users/YOUR_USER_ID/tokens/YOUR_DESKTOP_TOKEN \
  --header 'Authorization: Bearer YOUR_AUTH_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
  "provider_key": "firebase-fcm",
  "device": {
    "app_id": "my-app-desktop"
  }
}'
Replace firebase-fcm with your provider key (apn, expo, or onesignal) as needed. The app_id value is an arbitrary string you define.

Filter tokens at send time

Pass filterByBundleId and bundleId in the provider override to send only to tokens whose device.app_id matches:
curl --request POST \
  --url https://api.courier.com/send \
  --header 'Authorization: Bearer YOUR_AUTH_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
  "message": {
    "to": {
      "user_id": "YOUR_USER_ID"
    },
    "content": {
      "title": "Desktop notification",
      "body": "This only goes to desktop tokens"
    },
    "routing": {
      "method": "all",
      "channels": ["firebase-fcm"]
    },
    "providers": {
      "firebase-fcm": {
        "override": {
          "config": {
            "filterByBundleId": true,
            "bundleId": "my-app-desktop"
          }
        }
      }
    }
  }
}'
To target mobile tokens instead, change bundleId to "my-app-mobile". If bundleId doesn’t match any of the user’s tokens, the message won’t be delivered to that provider. The same override structure works for any push provider:
ProviderOverride path
Firebase FCMproviders.firebase-fcm.override.config
Apple Push (APNS)providers.apn.override.config
Expoproviders.expo.override.config
OneSignalproviders.onesignal.override.config
Token filtering only works with tokens stored via the Token Management API (PUT /users/{user_id}/tokens/{token}). Tokens set directly on the user profile (e.g., firebaseToken or apn.token in the to object) bypass this filter.