Get started

Quickstart

Register a device and send your first push notification.

1. Create an app in Native Notify

In Native Notify, click + New project, then open the project's Keys page to copy the app id and app token. Requests carry both — in the body for POSTs, in the URL for GETs.

2. Add push credentials in Native Notify

Android needs an FCM v1 service-account JSON. iOS needs an APNs .p8 key with its Key ID, your Team ID and the app's bundle id — which takes a paid Apple Developer Program membership and a Bundle ID registered with Apple. In Native Notify, save them under Settings → Push credentials — each save is checked live. Web push needs none, so web-only apps can skip to step 3. See Push credentials for where each one comes from.

3. Register a device from your app

POST https://app.nativenotify.com/api/universal/device/register
{
  "appId": 123,
  "appToken": "yourAppToken",
  "deviceId": "A1B2C3D4-install-key",
  "platform": "ios",
  "tokens": { "apnsToken": "0c9d8e…" }
}

Registration saves the device id you generate once per install and the platform's push token — APNs on iOS, FCM on Android, a PushSubscription on the web. It's an upsert: call it on every launch and whenever the token changes.

Examples

Ask for permission, let APNs hand you the device token, and register it:

AppDelegate.swift
import UIKit
import UserNotifications

@main
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        UNUserNotificationCenter.current().delegate = self
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, _ in
            guard granted else { return }
            DispatchQueue.main.async { application.registerForRemoteNotifications() }
        }
        return true
    }

    // APNs delivers the device token here.
    func application(_ application: UIApplication,
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let apnsToken = deviceToken.map { String(format: "%02x", $0) }.joined()
        Task { await register(apnsToken: apnsToken) }
    }

    func register(apnsToken: String) async {
        var request = URLRequest(url: URL(string: "https://app.nativenotify.com/api/universal/device/register")!)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = try? JSONSerialization.data(withJSONObject: [
            "appId": 123,
            "appToken": "yourAppToken",
            "deviceId": DeviceIdentity.current,   // a stable id you persist (Keychain, UserDefaults)
            "platform": "ios",
            "tokens": ["apnsToken": apnsToken]
        ])
        _ = try? await URLSession.shared.data(for: request)   // 201 = registered
    }
}

Stable deviceId and tap handling: Swift recipe.

4. Send a test push with the API

Send to the device you registered. The response says whether APNs or FCM accepted it.

curl -X POST https://app.nativenotify.com/api/universal/test-send \
  -H "Content-Type: application/json" \
  -d '{
    "appId": 123,
    "appToken": "yourAppToken",
    "title": "Hello from Native Notify",
    "message": "If you can read this, APNs/FCM accepted it.",
    "deviceId": "YOUR_DEVICE_ID"
  }'

5. Send to everyone with the API

Change the audience to reach every registered device.

curl -X POST https://app.nativenotify.com/api/universal/notifications/send \
  -H "Content-Type: application/json" \
  -d '{
    "appId": 123,
    "appToken": "yourAppToken",
    "title": "Hello everyone",
    "message": "Our first push notification.",
    "audience": { "type": "all" }
  }'

Troubleshooting

SymptomLikely cause
401Wrong appToken, or a web key (nnweb_…) used from a native device. The web key only belongs in platform: "web" registrations.
400 invalid_token_formatNot a raw APNs or FCM token. Expo push tokens are rejected — pass the native token (getDevicePushTokenAsync()).
400 token_platform_mismatchapnsToken → ios, fcmToken → android, webPush → web.
Test send refused with a reasonCodeUsually the step 2 credential: bundle id, team id, or sandbox vs production. See Verify delivery.
Accepted, but nothing shows on AndroidFCM sends data messages, so your app shows them. See your platform guide.
Accepted, but nothing shows on iPhone or iPad (web)Safari delivers web push only to sites added to the Home Screen.
403 plan_upgrade_requiredThe plan doesn't include that audience. Premium allows one subscriber or "all", not groups or device lists. See Plans & billing.

Next steps