Create AWS SNS Platform Applications

The aws:sns/platformApplication:PlatformApplication resource, part of the Pulumi AWS provider, registers mobile applications with SNS for push notification delivery to iOS and Android devices. This guide focuses on two capabilities: iOS push notifications (certificate and token authentication) and Android push notifications via GCM.

Platform applications require credentials from Apple Developer or Google Cloud Console before registration. The examples are intentionally small. Combine them with your own endpoint management and delivery monitoring.

Register iOS apps with certificate-based authentication

iOS applications using certificate-based push notifications require an APNS certificate and private key from Apple Developer.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const apnsApplication = new aws.sns.PlatformApplication("apns_application", {
    name: "apns_application",
    platform: "APNS",
    platformCredential: "<APNS PRIVATE KEY>",
    platformPrincipal: "<APNS CERTIFICATE>",
});
import pulumi
import pulumi_aws as aws

apns_application = aws.sns.PlatformApplication("apns_application",
    name="apns_application",
    platform="APNS",
    platform_credential="<APNS PRIVATE KEY>",
    platform_principal="<APNS CERTIFICATE>")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/sns"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sns.NewPlatformApplication(ctx, "apns_application", &sns.PlatformApplicationArgs{
			Name:               pulumi.String("apns_application"),
			Platform:           pulumi.String("APNS"),
			PlatformCredential: pulumi.String("<APNS PRIVATE KEY>"),
			PlatformPrincipal:  pulumi.String("<APNS CERTIFICATE>"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var apnsApplication = new Aws.Sns.PlatformApplication("apns_application", new()
    {
        Name = "apns_application",
        Platform = "APNS",
        PlatformCredential = "<APNS PRIVATE KEY>",
        PlatformPrincipal = "<APNS CERTIFICATE>",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.sns.PlatformApplication;
import com.pulumi.aws.sns.PlatformApplicationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var apnsApplication = new PlatformApplication("apnsApplication", PlatformApplicationArgs.builder()
            .name("apns_application")
            .platform("APNS")
            .platformCredential("<APNS PRIVATE KEY>")
            .platformPrincipal("<APNS CERTIFICATE>")
            .build());

    }
}
resources:
  apnsApplication:
    type: aws:sns:PlatformApplication
    name: apns_application
    properties:
      name: apns_application
      platform: APNS
      platformCredential: <APNS PRIVATE KEY>
      platformPrincipal: <APNS CERTIFICATE>

The platform property specifies “APNS” for iOS. The platformCredential holds your APNS private key, while platformPrincipal contains the APNS certificate. SNS uses these credentials to authenticate with Apple’s push notification service when delivering messages to iOS devices.

Register iOS apps with token-based authentication

Token-based authentication simplifies credential management by using a signing key instead of certificates, enabling a single key across multiple apps.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const apnsApplication = new aws.sns.PlatformApplication("apns_application", {
    name: "apns_application",
    platform: "APNS",
    platformCredential: "<APNS SIGNING KEY>",
    platformPrincipal: "<APNS SIGNING KEY ID>",
    applePlatformTeamId: "<APPLE TEAM ID>",
    applePlatformBundleId: "<APPLE BUNDLE ID>",
});
import pulumi
import pulumi_aws as aws

apns_application = aws.sns.PlatformApplication("apns_application",
    name="apns_application",
    platform="APNS",
    platform_credential="<APNS SIGNING KEY>",
    platform_principal="<APNS SIGNING KEY ID>",
    apple_platform_team_id="<APPLE TEAM ID>",
    apple_platform_bundle_id="<APPLE BUNDLE ID>")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/sns"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sns.NewPlatformApplication(ctx, "apns_application", &sns.PlatformApplicationArgs{
			Name:                  pulumi.String("apns_application"),
			Platform:              pulumi.String("APNS"),
			PlatformCredential:    pulumi.String("<APNS SIGNING KEY>"),
			PlatformPrincipal:     pulumi.String("<APNS SIGNING KEY ID>"),
			ApplePlatformTeamId:   pulumi.String("<APPLE TEAM ID>"),
			ApplePlatformBundleId: pulumi.String("<APPLE BUNDLE ID>"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var apnsApplication = new Aws.Sns.PlatformApplication("apns_application", new()
    {
        Name = "apns_application",
        Platform = "APNS",
        PlatformCredential = "<APNS SIGNING KEY>",
        PlatformPrincipal = "<APNS SIGNING KEY ID>",
        ApplePlatformTeamId = "<APPLE TEAM ID>",
        ApplePlatformBundleId = "<APPLE BUNDLE ID>",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.sns.PlatformApplication;
import com.pulumi.aws.sns.PlatformApplicationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var apnsApplication = new PlatformApplication("apnsApplication", PlatformApplicationArgs.builder()
            .name("apns_application")
            .platform("APNS")
            .platformCredential("<APNS SIGNING KEY>")
            .platformPrincipal("<APNS SIGNING KEY ID>")
            .applePlatformTeamId("<APPLE TEAM ID>")
            .applePlatformBundleId("<APPLE BUNDLE ID>")
            .build());

    }
}
resources:
  apnsApplication:
    type: aws:sns:PlatformApplication
    name: apns_application
    properties:
      name: apns_application
      platform: APNS
      platformCredential: <APNS SIGNING KEY>
      platformPrincipal: <APNS SIGNING KEY ID>
      applePlatformTeamId: <APPLE TEAM ID>
      applePlatformBundleId: <APPLE BUNDLE ID>

Token-based authentication requires four properties: platformCredential (signing key), platformPrincipal (signing key ID), applePlatformTeamId (your Apple developer team ID), and applePlatformBundleId (your app’s bundle identifier). This approach eliminates certificate expiration concerns and supports multiple apps with one key.

Register Android apps with GCM credentials

Android applications using Google Cloud Messaging require a GCM API key from the Google Cloud Console.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const gcmApplication = new aws.sns.PlatformApplication("gcm_application", {
    name: "gcm_application",
    platform: "GCM",
    platformCredential: "<GCM API KEY>",
});
import pulumi
import pulumi_aws as aws

gcm_application = aws.sns.PlatformApplication("gcm_application",
    name="gcm_application",
    platform="GCM",
    platform_credential="<GCM API KEY>")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/sns"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sns.NewPlatformApplication(ctx, "gcm_application", &sns.PlatformApplicationArgs{
			Name:               pulumi.String("gcm_application"),
			Platform:           pulumi.String("GCM"),
			PlatformCredential: pulumi.String("<GCM API KEY>"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var gcmApplication = new Aws.Sns.PlatformApplication("gcm_application", new()
    {
        Name = "gcm_application",
        Platform = "GCM",
        PlatformCredential = "<GCM API KEY>",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.sns.PlatformApplication;
import com.pulumi.aws.sns.PlatformApplicationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var gcmApplication = new PlatformApplication("gcmApplication", PlatformApplicationArgs.builder()
            .name("gcm_application")
            .platform("GCM")
            .platformCredential("<GCM API KEY>")
            .build());

    }
}
resources:
  gcmApplication:
    type: aws:sns:PlatformApplication
    name: gcm_application
    properties:
      name: gcm_application
      platform: GCM
      platformCredential: <GCM API KEY>

The platform property specifies “GCM” for Android. The platformCredential contains your GCM API key. Unlike iOS, Android push notifications don’t require a platformPrincipal property.

Beyond these examples

These snippets focus on specific platform application features: iOS push notifications (certificate and token authentication) and Android push notifications via GCM. They’re intentionally minimal rather than full notification systems.

The examples require pre-existing infrastructure such as APNS certificates, signing keys, or GCM API keys from platform providers. They focus on registering the application rather than managing endpoints or monitoring delivery.

To keep things focused, common platform application patterns are omitted, including:

  • Delivery failure monitoring (eventDeliveryFailureTopicArn)
  • Endpoint lifecycle events (eventEndpointCreated/Updated/DeletedTopicArn)
  • CloudWatch logging with IAM roles (failureFeedbackRoleArn, successFeedbackRoleArn)
  • Success sampling configuration (successFeedbackSampleRate)

These omissions are intentional: the goal is to illustrate how each platform application is wired, not provide drop-in notification modules. See the SNS Platform Application resource reference for all available configuration options.

Let's create AWS SNS Platform Applications

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Platform Configuration & Authentication
What's the difference between APNS certificate-based and token-based authentication?
Certificate-based authentication uses platformCredential (private key) and platformPrincipal (certificate). Token-based authentication uses platformCredential (signing key), platformPrincipal (signing key ID), plus applePlatformTeamId and applePlatformBundleId.
What credentials do I need for Google Cloud Messaging?
GCM only requires platformCredential (API key). You don’t need to provide platformPrincipal.
What are the requirements for APNS token authentication fields?
applePlatformTeamId must be exactly 10 alphanumeric characters. applePlatformBundleId may only include alphanumeric characters, hyphens (-), and periods (.).
Which platforms are supported?
Set the platform property to the platform your app is registered with. See the AWS SNS documentation for the full list of supported platforms including APNS and GCM.
State Management & Immutability
Why can't I reference platformCredential or platformPrincipal in other resources?
These values are stored as hashes in the Pulumi state, making them impractical to use as attributes for other resources. Store credentials in a secure location like AWS Secrets Manager and reference them directly instead.
What properties are immutable after creation?
Both name and platform are immutable. Changing either property will force resource replacement (destroy and recreate).
Event Notifications & Monitoring
What events can I monitor for my platform application?
You can configure SNS topics for four event types: delivery failures (eventDeliveryFailureTopicArn), endpoint creation (eventEndpointCreatedTopicArn), endpoint deletion (eventEndpointDeletedTopicArn), and endpoint updates (eventEndpointUpdatedTopicArn).
How do I enable CloudWatch logging for message delivery?
Configure successFeedbackRoleArn and/or failureFeedbackRoleArn with IAM roles that have permissions to write to CloudWatch logs. For success feedback, also set successFeedbackSampleRate (0-100 percentage).
What does successFeedbackSampleRate control?
It sets the percentage (0-100) of successfully delivered messages that will generate feedback logs in CloudWatch.

Using a different cloud?

Explore messaging guides for other cloud providers: