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

# expo-notifications

> Fetch push tokens, present notifications, schedule local notifications, and handle responses

# expo-notifications

**Version:** 55.0.7

Provides an API to fetch push notification tokens and to present, schedule, receive, and respond to notifications. Supports both local and remote push notifications.

## Installation

```bash theme={null}
npx expo install expo-notifications
```

## Usage

```typescript theme={null}
import * as Notifications from 'expo-notifications';

// Configure notification behavior
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: true,
    shouldSetBadge: false,
  }),
});

// Request permissions
const { status } = await Notifications.requestPermissionsAsync();

// Get push token
const token = (await Notifications.getExpoPushTokenAsync()).data;

// Schedule local notification
await Notifications.scheduleNotificationAsync({
  content: {
    title: 'Hello!',
    body: 'This is a notification',
  },
  trigger: {
    seconds: 5,
  },
});

// Listen for notifications
Notifications.addNotificationReceivedListener((notification) => {
  console.log('Notification received:', notification);
});

Notifications.addNotificationResponseReceivedListener((response) => {
  console.log('Notification tapped:', response);
});
```

## API Reference

### Permissions

<ParamField path="requestPermissionsAsync(request)" type="(request?: NotificationPermissionsRequest) => Promise<NotificationPermissionsStatus>">
  Requests notification permissions

  ```typescript theme={null}
  const { status } = await Notifications.requestPermissionsAsync({
    ios: {
      allowAlert: true,
      allowBadge: true,
      allowSound: true,
    },
  });
  ```
</ParamField>

<ParamField path="getPermissionsAsync()" type="() => Promise<NotificationPermissionsStatus>">
  Gets current permission status
</ParamField>

### Push Tokens

<ParamField path="getExpoPushTokenAsync(options)" type="(options?: ExpoPushTokenOptions) => Promise<ExpoPushToken>">
  Gets Expo push token

  ```typescript theme={null}
  const token = await Notifications.getExpoPushTokenAsync({
    projectId: 'your-project-id',
  });
  console.log('Token:', token.data);
  ```
</ParamField>

<ParamField path="getDevicePushTokenAsync()" type="() => Promise<DevicePushToken>">
  Gets native device push token (FCM/APNs)
</ParamField>

### Local Notifications

<ParamField path="scheduleNotificationAsync(request)" type="(request: NotificationRequestInput) => Promise<string>">
  Schedules a local notification

  ```typescript theme={null}
  const id = await Notifications.scheduleNotificationAsync({
    content: {
      title: 'Reminder',
      body: 'Don\'t forget!',
      data: { customData: 'value' },
    },
    trigger: {
      seconds: 10,
    },
  });
  ```
</ParamField>

<ParamField path="presentNotificationAsync(content)" type="(content: NotificationContentInput) => Promise<string>">
  Shows notification immediately

  ```typescript theme={null}
  await Notifications.presentNotificationAsync({
    title: 'Now',
    body: 'Immediate notification',
  });
  ```
</ParamField>

<ParamField path="cancelScheduledNotificationAsync(identifier)" type="(identifier: string) => Promise<void>">
  Cancels scheduled notification
</ParamField>

<ParamField path="cancelAllScheduledNotificationsAsync()" type="() => Promise<void>">
  Cancels all scheduled notifications
</ParamField>

<ParamField path="getAllScheduledNotificationsAsync()" type="() => Promise<Notification[]>">
  Gets all scheduled notifications
</ParamField>

### Notification Management

<ParamField path="dismissNotificationAsync(identifier)" type="(identifier: string) => Promise<void>">
  Dismisses displayed notification
</ParamField>

<ParamField path="dismissAllNotificationsAsync()" type="() => Promise<void>">
  Dismisses all displayed notifications
</ParamField>

<ParamField path="getPresentedNotificationsAsync()" type="() => Promise<Notification[]>">
  Gets currently displayed notifications
</ParamField>

### Badge Count

<ParamField path="setBadgeCountAsync(count)" type="(count: number) => Promise<boolean>">
  Sets app badge count

  ```typescript theme={null}
  await Notifications.setBadgeCountAsync(5);
  ```
</ParamField>

<ParamField path="getBadgeCountAsync()" type="() => Promise<number>">
  Gets current badge count
</ParamField>

### Event Listeners

<ParamField path="addNotificationReceivedListener(listener)" type="(listener: (notification: Notification) => void) => Subscription">
  Listens for received notifications

  ```typescript theme={null}
  const subscription = Notifications.addNotificationReceivedListener(
    (notification) => {
      console.log('Received:', notification.request.content.title);
    }
  );
  ```
</ParamField>

<ParamField path="addNotificationResponseReceivedListener(listener)" type="(listener: (response: NotificationResponse) => void) => Subscription">
  Listens for notification taps

  ```typescript theme={null}
  Notifications.addNotificationResponseReceivedListener((response) => {
    const data = response.notification.request.content.data;
    // Navigate based on data
  });
  ```
</ParamField>

### Configuration

<ParamField path="setNotificationHandler(handler)" type="(handler: NotificationHandler | null) => void">
  Configures notification behavior

  ```typescript theme={null}
  Notifications.setNotificationHandler({
    handleNotification: async () => ({
      shouldShowAlert: true,
      shouldPlaySound: true,
      shouldSetBadge: true,
      priority: Notifications.AndroidNotificationPriority.HIGH,
    }),
  });
  ```
</ParamField>

<ParamField path="setNotificationChannelAsync(identifier, channel)" type="(identifier: string, channel: NotificationChannel) => Promise<NotificationChannel | null>">
  Creates/updates Android notification channel

  ```typescript theme={null}
  await Notifications.setNotificationChannelAsync('default', {
    name: 'Default',
    importance: Notifications.AndroidImportance.HIGH,
    vibrationPattern: [0, 250, 250, 250],
    sound: 'notification.wav',
  });
  ```
</ParamField>

## Examples

### Complete Setup

```tsx theme={null}
import * as Notifications from 'expo-notifications';
import { useState, useEffect, useRef } from 'react';
import { Platform } from 'react-native';

// Configure handler
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: true,
    shouldSetBadge: false,
  }),
});

export default function App() {
  const [pushToken, setPushToken] = useState('');
  const notificationListener = useRef<Notifications.Subscription>();
  const responseListener = useRef<Notifications.Subscription>();

  useEffect(() => {
    registerForPushNotifications();

    // Add listeners
    notificationListener.current = Notifications.addNotificationReceivedListener(
      (notification) => {
        console.log('Notification received:', notification);
      }
    );

    responseListener.current = Notifications.addNotificationResponseReceivedListener(
      (response) => {
        console.log('Notification tapped:', response);
      }
    );

    return () => {
      notificationListener.current?.remove();
      responseListener.current?.remove();
    };
  }, []);

  async function registerForPushNotifications() {
    const { status: existingStatus } = await Notifications.getPermissionsAsync();
    let finalStatus = existingStatus;

    if (existingStatus !== 'granted') {
      const { status } = await Notifications.requestPermissionsAsync();
      finalStatus = status;
    }

    if (finalStatus !== 'granted') {
      alert('Failed to get push token');
      return;
    }

    const token = (await Notifications.getExpoPushTokenAsync()).data;
    setPushToken(token);

    // Send token to your server
    await sendTokenToServer(token);

    // Android channel
    if (Platform.OS === 'android') {
      Notifications.setNotificationChannelAsync('default', {
        name: 'default',
        importance: Notifications.AndroidImportance.MAX,
      });
    }
  }

  // Rest of component...
}
```

### Schedule Notification

```typescript theme={null}
import * as Notifications from 'expo-notifications';

async function scheduleReminder() {
  await Notifications.scheduleNotificationAsync({
    content: {
      title: 'Reminder',
      body: 'Time to check your tasks',
      data: { screen: 'tasks' },
    },
    trigger: {
      hour: 9,
      minute: 0,
      repeats: true,
    },
  });
}
```

### Handle Notification Tap

```typescript theme={null}
import * as Notifications from 'expo-notifications';
import { useNavigation } from '@react-navigation/native';

function useNotifications() {
  const navigation = useNavigation();

  useEffect(() => {
    const subscription = Notifications.addNotificationResponseReceivedListener(
      (response) => {
        const { screen } = response.notification.request.content.data;
        
        if (screen) {
          navigation.navigate(screen as never);
        }
      }
    );

    return () => subscription.remove();
  }, []);
}
```

## Platform Support

| Platform | Supported   |
| -------- | ----------- |
| iOS      | ✅           |
| Android  | ✅           |
| Web      | ✅ (Limited) |

## Configuration

### app.json

```json theme={null}
{
  "expo": {
    "plugins": [
      [
        "expo-notifications",
        {
          "icon": "./assets/notification-icon.png",
          "color": "#ffffff",
          "sounds": ["./assets/notification.wav"]
        }
      ]
    ],
    "notification": {
      "icon": "./assets/notification-icon.png",
      "color": "#ffffff"
    }
  }
}
```

### Permissions

**iOS:** Add to `app.json`:

```json theme={null}
{
  "ios": {
    "infoPlist": {
      "UIBackgroundModes": ["remote-notification"]
    }
  }
}
```

**Android:** Permissions automatically added.

## Best Practices

1. **Request Permissions**: Always request before sending notifications
2. **Configure Handler**: Set notification handler before listeners
3. **Clean Up**: Remove listeners in component cleanup
4. **Android Channels**: Create channels for Android 8+
5. **Error Handling**: Handle permission denials gracefully

<Warning>
  On iOS, notifications may not appear when app is in foreground unless configured in notification handler.
</Warning>

## Resources

* [Official Documentation](https://docs.expo.dev/versions/latest/sdk/notifications/)
* [GitHub Repository](https://github.com/expo/expo/tree/main/packages/expo-notifications)
* [Push Notification Tool](https://expo.dev/notifications)
