Home > Uncategorized > #APNS using HTTP/2 in C# using #AWS Lambda

#APNS using HTTP/2 in C# using #AWS Lambda

By March 31st 2021, all users using the Apple Push Notification Service (APNS) must update to Apple’s new API, which is based on HTTP/2. If you don’t update, then it’s likely that your push notifications won’t get through.

If you are using C#, then you can use the dotAPNS NUGet package, which, from the client perspective is a tiny change, however, it does require .NET Core to run, which if your project is in .NET standard, then this could cause problems.

So, in this case, I decided to create a stand-alone .NET Core app using AWS Lambda and AWS API Gateway, which would be a middleware API between my main app and the APNS API.


So, I created an AWS Lambda App in Visual Studio, and made sure I could publish to AWS Lambda. Which also gives you an API Gateway URL, in the format;


I also needed to update the serverless.template file as follows

         "Events": {
           "RootGet": {
             "Type": "Api",
             "Properties": {
               "Path": "/",
               "Method": "GET"
           "RootPost": {
             "Type": "Api",
             "Properties": {
               "Path": "/",
               "Method": "POST"

And changed the Handler to


(Where ApnsHttp2Serverless was the name of my project)

Now, my code to send the push notification is as follows;

private ApnsResponse Send(
             byte[] certificate, 
             string certPassword, 
             string message, 
             string destination)
     var x509 = new X509Certificate2(certificate, certPassword);
     var applePushNotificationService = ApnsClient.CreateUsingCert(x509);
     var push = new ApplePush(ApplePushType.Alert)
     return applePushNotificationService.Send(push).Result;

Which is called from the lambda as follows;

public APIGatewayProxyResponse HttpRequest(APIGatewayProxyRequest request, ILambdaContext context)
     var jRequest = JObject.Parse(request.Body);
     var certificate = jRequest["certificate"].ToObject();
     var certPassword = jRequest["certPassword"].ToObject();
     var message = jRequest["message"].ToObject();
     var destination = jRequest["destination"].ToObject();
     var sendResult = Send(certificate, certPassword, message, destination);
     var response = new APIGatewayProxyResponse
     StatusCode = (int)HttpStatusCode.OK,
     Body = JsonConvert.SerializeObject(sendResult,Formatting.Indented),
     Headers = new Dictionary { { "Content-Type", "application/json" } }
     return response;

So, I pushed this code to AWS Lambda, and wrote the client as follows:

public static string Push(string destination, string message, string certFile, string certPassword)
     var certificate = File.ReadAllBytes(certFile);
     var oPayload = new
     var strPayload = JsonConvert.SerializeObject(oPayload, Formatting.Indented);
     var wc = new WebClient();
     var response = wc.UploadString("https://....execute-api.eu-west-1.amazonaws.com/Prod", strPayload);
     return response;

So, Assuming you have the destination ID, and your certs set up correctly, this just works!

For anyone who is interested, here is the GitHub Repo of the AWS Lambda function:


And for those who happen to use PHP as the trigger to send push notifications, here is the client code in PHP:

$data        = file_get_contents('cert.p12');
$cert64      = base64_encode($data);
$destination = "-apns-token-";
$password    = "-cert-password-";
$url         = "https://xxxxxx.execute-api.eu-west-1.amazonaws.com/Prod";
$ch          = curl_init($url);
$oPayload    = array(
    'destination' => $destination,
    'message' => 'hello there!',
    'certificate' => $cert64,
    'certPassword' => $password
$payload     = json_encode($oPayload);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$content = curl_exec($ch);
if ($content === false) {
    echo 'Curl error: ' . curl_error($ch);
echo $content;

Categories: Uncategorized
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: