Skip to main content

Apple Push Notification Service Setup

APNS

Configure APNS to send push notifications to iOS and macOS devices.

Native iOS

Direct Apple integration

P8 Keys

Token-based authentication

Secure

End-to-end encryption

Real-time

Instant delivery

Apple Developer Account Requirements

Before configuring APNS, ensure you have:

Apple Developer Account

Paid membership ($99/year)

App ID with Push

Push Notifications capability enabled

Bundle Identifier

Unique app identifier (e.g., com.myapp.ios)

Team ID

Found in Membership details

Developer Account

You need a paid Apple Developer Program membership to send push notifications. The free tier does not support APNS.

Creating Push Certificates

Configure your App ID for push notifications:

1

Access Certificates

Go to Apple Developer Portal Certificates, Identifiers & Profiles.

2

Select or Create App ID

Under Identifiers, select your existing App ID or create a new one. Enable the Push Notifications capability.

3

Configure Push

Click Configure next to Push Notifications. You can create either Development or Production certificates, but we recommend using P8 keys instead.

Recommendation: Use P8 Keys

While push certificates work, Apple recommends using P8 authentication keys. They never expire and work for all your apps.

P8 Key Configuration

Create an APNS authentication key (recommended approach):

1

Create Key

In Apple Developer Portal, go to Keys and click the + button to create a new key.

2

Enable APNS

Name your key (e.g., "APNS Push Key") and check Apple Push Notifications service (APNs). Click Continue.

3

Download Key

Click Register, then Download. Save the .p8 file securely. You can only download this file once!

4

Note Key ID

Record the Key ID shown on the key details page. You'll need this along with your Team ID.

Required Credentials
# P8 Key File
# File: AuthKey_XXXXXXXXXX.p8
# Contains your private key (keep secure!)

# Key ID (10 characters)
APNS_KEY_ID=XXXXXXXXXX

# Team ID (from Membership page)
APNS_TEAM_ID=YYYYYYYYYY

# Bundle ID (your app's identifier)
APNS_BUNDLE_ID=com.yourcompany.yourapp

Key Security

Store your P8 key securely. If compromised, anyone can send push notifications to your app. Revoke and regenerate if you suspect exposure.

Adding APNS to Console

Configure APNS credentials in the Sylphx dashboard:

1

Navigate to Settings

Go to App Settings → Notifications → Push Providers.

2

Add APNS Provider

Click Add Provider and select Apple Push Notification Service.

3

Upload P8 Key

Upload your .p8 file and enter your Key ID, Team ID, and Bundle ID.

4

Select Environment

Choose Development for testing or Production for App Store builds.

5

Test Connection

Click Test Connection to verify your credentials.

SDK Configuration
import { platform } from '@/lib/platform'

// APNS is automatically configured once added in the dashboard
// No additional SDK configuration needed

// Verify APNS is configured
const providers = await platform.notifications.getProviders()
console.log(providers.apns)
// {
//   enabled: true,
//   environment: 'production',
//   bundleId: 'com.yourcompany.yourapp',
// }

Sending to iOS Devices

Send push notifications to iOS devices:

Server-side
import { platform } from '@/lib/platform'

// Send to a specific user (uses their registered device token)
await platform.notifications.send({
  userId: user.id,
  title: 'New Message',
  body: 'Sarah sent you a message',
  data: {
    messageId: '123',
  },
})

// Send with iOS-specific options
await platform.notifications.send({
  userId: user.id,
  title: 'Order Update',
  body: 'Your order has shipped!',

  // APNS-specific configuration
  apns: {
    // Alert customization
    alert: {
      title: 'Order Update',
      subtitle: 'Order #12345',
      body: 'Your order has shipped!',
    },

    // Badge count
    badge: 5,

    // Sound
    sound: 'default', // or custom sound file name

    // Content available (for background updates)
    contentAvailable: true,

    // Mutable content (for notification extensions)
    mutableContent: true,

    // Category for actionable notifications
    category: 'ORDER_UPDATE',

    // Thread ID for grouping
    threadId: 'order-12345',

    // Target content ID (for replacing notifications)
    targetContentId: 'order-12345',

    // Interruption level (iOS 15+)
    interruptionLevel: 'active', // 'passive' | 'active' | 'time-sensitive' | 'critical'

    // Relevance score (0-1, for notification summary)
    relevanceScore: 0.8,
  },

  data: {
    orderId: '12345',
    trackingUrl: 'https://tracking.example.com',
  },
})
Send to Device Token
// Send directly to a device token
await platform.notifications.sendToToken({
  token: 'apns-device-token...',
  title: 'Welcome!',
  body: 'Thanks for enabling notifications',
  apns: {
    badge: 1,
    sound: 'default',
  },
})

// Batch send to multiple tokens
const result = await platform.notifications.sendToTokens({
  tokens: ['token1...', 'token2...', 'token3...'],
  title: 'New Feature',
  body: 'Check out our latest update!',
})

console.log(result)
// {
//   success: 2,
//   failure: 1,
//   failedTokens: ['token3...'],
// }

APNS Options

PropertyTypeDescription
alertobjectAlert content (title, subtitle, body)
badgenumberApp badge number
soundstringSound file name or "default"
contentAvailableboolean= falseEnable background fetch
mutableContentboolean= falseAllow notification extension
categorystringAction category identifier
threadIdstringThread for grouping notifications
interruptionLevelstringiOS 15+ interruption level
relevanceScorenumberScore for notification summary (0-1)

Testing on Simulator vs Device

Understanding the differences when testing push notifications:

Physical Device

  • Full APNS support
  • Real device tokens
  • Background notifications
  • Notification extensions
  • Production environment

Simulator

  • Xcode 14+ supports push
  • Drag .apns files to test
  • Simulated tokens only
  • No real APNS connection
  • Limited extension support
Test on Simulator (Xcode 14+)
// Create a test payload file: test.apns
{
  "Simulator Target Bundle": "com.yourcompany.yourapp",
  "aps": {
    "alert": {
      "title": "Test Notification",
      "body": "This is a test push notification"
    },
    "badge": 1,
    "sound": "default"
  },
  "customData": {
    "key": "value"
  }
}

// Drag the .apns file onto the simulator to trigger the notification
// Or use xcrun from command line:
// xcrun simctl push booted com.yourcompany.yourapp test.apns
Test with Sylphx Dashboard
// You can also test from the dashboard:
// 1. Go to App Settings → Notifications → Push Providers → APNS
// 2. Click "Send Test Notification"
// 3. Enter a device token (from your app logs)
// 4. Customize the payload and send

// Or use the SDK for testing
await platform.notifications.sendTest({
  provider: 'apns',
  token: 'device-token-from-logs...',
  title: 'Test Notification',
  body: 'This is a test!',
})

Development vs Production

Development builds use the APNS sandbox (gateway.sandbox.push.apple.com). Production/ TestFlight builds use production APNS (gateway.push.apple.com). Tokens from one environment won't work in the other.

Troubleshooting APNS

Common issues and solutions:

BadDeviceToken

Cause: Token format is invalid or malformed

Solution: Ensure you're using the correct hex string format. Token should be 64 characters.

DeviceTokenNotForTopic

Cause: Token was generated for a different app bundle

Solution: Verify the bundle ID matches the one used to generate the token

Unregistered

Cause: App was uninstalled or token invalidated

Solution: Remove the token from your database and wait for a new registration

ExpiredProviderToken

Cause: Your P8 key authentication token expired

Solution: Tokens expire after 1 hour. The SDK handles this automatically.

InvalidProviderToken

Cause: P8 key, Key ID, or Team ID is incorrect

Solution: Verify all credentials match your Apple Developer account

TopicDisallowed

Cause: Push not enabled for this App ID

Solution: Enable Push Notifications capability in Apple Developer Portal

Debug APNS Responses
// Enable debug mode for detailed logging
const result = await platform.notifications.send({
  userId: user.id,
  title: 'Test',
  body: 'Debug test',
  debug: true, // Returns detailed response
})

console.log(result)
// {
//   success: false,
//   provider: 'apns',
//   error: {
//     code: 'BadDeviceToken',
//     message: 'The specified device token is invalid.',
//     timestamp: '2024-01-15T10:30:00Z',
//   },
//   apnsResponse: {
//     statusCode: 400,
//     headers: { ... },
//   },
// }

Token Lifecycle

APNS tokens can change when users update iOS, restore from backup, or reinstall your app. Always listen for token refresh events and update your database accordingly.