> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pushnotif.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Push tokens, taps and dismissals

> What the SDK wires up automatically, and how to do it by hand instead.

## Automatic (the default)

Like the OneSignal, Firebase and Braze SDKs, ours hooks the system callbacks
when you call `configure`, so none of this needs app code:

* **Device tokens.** Your app delegate's token callback is hooked, and the token
  is registered with your bundle id and the right APNs environment (read from
  the build's provisioning profile, so Xcode and TestFlight builds are told
  apart correctly). The SDK also re-registers on every launch once permission
  is granted, so tokens never go stale.
* **Taps and dismissals.** Your `UNUserNotificationCenterDelegate`'s
  `didReceive` is hooked (or one is provided if you never set a delegate). Your
  own implementation is **always** called, so your deep-link routing keeps
  working. Our notifications are reported as `$notification_tapped` or
  `$notification_dismissed`.
* **The dismiss category.** iOS only reports swipe-to-dismiss for notification
  categories registered with `.customDismissAction`. The SDK adds its category
  to the ones you already registered, and never replaces them.

Asking the user for permission is still up to you:

```swift theme={null}
let granted = try await UNUserNotificationCenter.current()
    .requestAuthorization(options: [.alert, .sound, .badge])
if granted {
    await MainActor.run { UIApplication.shared.registerForRemoteNotifications() }
}
```

## Tap destinations

A flow's message can carry a deep link. When the user taps, iOS hands the
notification to your delegate as usual, with the link under the `deep_link`
key for your router to open:

```swift theme={null}
if let link = response.notification.request.content.userInfo["deep_link"] as? String,
   let url = URL(string: link) {
    router.open(url)
}
```

If a message has no deep link, a tap simply opens the app.

## Custom data

A message's [custom data](https://docs.pushnotif.ai/strategy/flows.md#custom-data) arrives as top-level
keys in the notification's `userInfo`, next to `deep_link`. Values set in a
flow are always strings:

```swift theme={null}
let info = response.notification.request.content.userInfo
if info["screen"] as? String == "lesson",
   let lessonId = info["lesson_id"] as? String {
    router.showLesson(id: lessonId)
}
```

To act on it while the app is open, read the same keys in your delegate's
`willPresent`.

## Manual integration

Turn the hooks off if another SDK's swizzling conflicts with ours, or your
delegate setup needs to be explicit:

```swift theme={null}
PushConfiguration(
    apiKey: "pna_...",
    baseURL: URL(string: "https://api.pushnotif.ai")!,
    swizzlingEnabled: false
)
```

Then forward the two callbacks yourself:

```swift theme={null}
// UIApplicationDelegate
func application(_ application: UIApplication,
                 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    Task {
        await Push.client?.registerPushToken(
            deviceToken,
            topic: Bundle.main.bundleIdentifier!,
            environment: .production   // .sandbox for development-signed builds
        )
    }
}

// UNUserNotificationCenterDelegate
func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse) async {
    Push.handleNotificationResponse(response)   // true if it was one of ours
    // ... your own routing
}
```

`handleNotificationResponse` never calls the completion handler for you, and
returns whether the notification came from PushNotifAI.

If your app sets its whole category list with `setNotificationCategories`
(which replaces whatever was there), also set
`automaticallyRegistersNotificationCategory: false` and include ours:

```swift theme={null}
center.setNotificationCategories([myCategory, Push.notificationCategory])
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.