Fetch a subscriber's notifications with getIndieNotificationInbox to build your own inbox screen.
Premium has no inbox
On Premium, every inbox call answers 201 with an explanation, so the SDK shows an empty inbox and an unread count of 0. See what each plan includes.
Get notifications
getIndieNotificationInbox returns a subscriber's notifications, newest first: the pushes sent to that subId plus your mass pushes sent after it registered. They're kept for 365 days.
import React, { useState, useEffect } from 'react';
import { getIndieNotificationInbox } from 'native-notify';
export default function NotificationInbox() {
const [data, setData] = useState([]);
const [takeNumber, setTakeNumber] = useState(10);
const [skipNumber, setSkipNumber] = useState(0);
const fetchNotifications = async () => {
try {
const notifications = await getIndieNotificationInbox(
"unique-user-id",
yourAppId,
'yourAppToken',
takeNumber,
skipNumber
);
console.log("notifications: ", notifications);
setData(notifications);
} catch (error) {
console.error("Error fetching notifications: ", error);
}
};
useEffect(() => {
fetchNotifications();
}, []);
return (
... // create an Indie Notification Inbox using getIndieNotificationInbox data
)
}
| Argument | Required | Notes |
|---|---|---|
subId | yes | The id you registered with registerIndieID. |
appId, appToken | no | Your app's id and token from your Native Notify dashboard. Default to NativeNotify.init(). |
take | no | Rows per page. Defaults to 20 in v5 and later. v4 and raw REST calls default to 10. |
skip | no | Rows to skip. Defaults to 0. |
It resolves with an array of rows:
[
{
"notification_id": 12345678,
"date": "9-17-2026 7:24PM",
"title": "New comment",
"message": "Someone commented on your post",
"pushData": "{\"postId\":\"a1b2c3\"}",
"read": true
}
]
pushData is the JSON string you sent: JSON.parse(row.pushData). A plain fetch marks every notification of the subscriber read before it lists them, so each row comes back read: true. For the real state, use per-notification read state. A failed request (a 401, a network error) rejects, so keep the try / catch.
Exact pagination
getIndieNotificationInboxPage also returns the subscriber's own row total, from the X-Total-Count response header, so "load more" is exact. getIndieNotificationInbox returns the rows alone.
import { getIndieNotificationInboxPage } from 'native-notify';
const { rows, total } = await getIndieNotificationInboxPage(
"unique-user-id",
yourAppId,
'yourAppToken',
20, // take
0 // skip
);
console.log(rows.length, "of", total); // total is null when the server doesn't send the header
Per-notification read state
Needs native-notify v5.2 or later. Pass { perNotification: true } as the sixth argument of the page function. Each row keeps its own read flag, and the server stops marking the inbox read on fetch. Mark a row read when the user opens it:
import { getIndieNotificationInboxPage, markIndieNotificationRead } from 'native-notify';
const { rows, total } = await getIndieNotificationInboxPage(
"unique-user-id",
yourAppId,
'yourAppToken',
20, // take
0, // skip
{ perNotification: true }
);
rows[0].read; // this subscriber's own read state
// Mark ONE row read when it is opened (best-effort — resolves false, never throws).
// Pass the ids unless you set them once with NativeNotify.init():
await markIndieNotificationRead(rows[0].notification_id, "unique-user-id", yourAppId, 'yourAppToken');
markIndieNotificationRead(notificationId, subId, appId?, appToken?) resolves true when the server accepted the mark and false on any failure. Without a notificationId it resolves false and sends nothing, because the id-less endpoint form marks the whole inbox read.
Unlike mass, read state here is per subId, so it works on simulators, in Expo Go and on the web. The prebuilt components and useNotificationInbox() take the same option as perNotificationRead.
Call the endpoint directly
GET https://app.nativenotify.com/api/indie/notification/inbox/{subId}/{appId}/{appToken}?take=10&skip=0
| Query | Default | Notes |
|---|---|---|
take | 10 | Rows per page. |
skip | 0 | Rows to skip. |
perNotification | — | true lists each row's real read state and marks nothing. Without it, the call marks every notification of the subscriber read first. |
Mark read:
POST https://app.nativenotify.com/api/indie/notification/inbox/read
{ "appId": 12345, "appToken": "yourAppToken", "subId": "unique-user-id", "notificationId": 12345678 }
notificationId is optional. Without it, everything for the subscriber is marked read.
| Status | Meaning |
|---|---|
201 | The array of rows above. [] means nothing has reached that subId: compare it with the id you registered and send to. A mark-read call answers 201 with Notifications Read Updated. |
201 with text | Premium: nothing is listed or marked, so the SDK returns []. Check that the body is an array before you use it. |
400 | A mark-read call without a subId. |
401 | The appId and appToken pair doesn't match an app. |
Premium accounts get this text instead of a list:
Your current Native Notify membership cannot access notification inbox features. You must upgrade to a higher membership to access notification inbox features.
Responses are never cached.