An in-app notification center list you can use to notify your users. Allows you to build high quality, flexible notification feeds very quickly.
Requirement | Reason |
---|---|
Courier Inbox Provider
|
Needed to link your Courier Inbox to the SDK |
Authentication
|
Needed to view inbox messages that belong to a user. |
If you are using JWT authentication, be sure to enable JWT support on the Courier Inbox Provider here
.

CourierInbox
works with all native iOS UI frameworks.
UI Framework | Support |
---|---|
UIKit |
✅ |
XIB |
|
SwiftUI |
✅ |
The default CourierInbox
styles.
import Courier_iOS
CourierInboxView(
didClickInboxMessageAtIndex: { message, index in
message.isRead ? message.markAsUnread() : message.markAsRead()
print(index, message)
},
didLongPressInboxMessageAtIndex: { message, index in
message.markAsArchived()
print(index, message)
},
didClickInboxActionForMessageAtIndex: { action, message, index in
print(action, message, index)
},
didScrollInbox: { scrollView in
print(scrollView.contentOffset.y)
}
)
let courierInbox = CourierInbox(
didClickInboxMessageAtIndex: { message, index in
message.isRead ? message.markAsUnread() : message.markAsRead()
print(index, message)
},
didLongPressInboxMessageAtIndex: { message, index in
message.markAsArchived()
print(index, message)
},
didClickInboxActionForMessageAtIndex: { action, message, index in
print(action, message, index)
},
didScrollInbox: { scrollView in
print(scrollView.contentOffset.y)
}
)
The styles you can use to quickly customize the CourierInbox
.
func getTheme() -> CourierInboxTheme {
let whiteColor = UIColor.white
let blackColor = UIColor.black
let blackLightColor = UIColor.black.withAlphaComponent(0.5)
let primaryColor = UIColor(red: 102/255, green: 80/255, blue: 164/255, alpha: 1)
let primaryLightColor = UIColor(red: 98/255, green: 91/255, blue: 113/255, alpha: 1)
let font = UIFont(name: "Avenir-Medium", size: 18)
return CourierInboxTheme(
tabIndicatorColor: primaryColor,
tabStyle: CourierStyles.Inbox.TabStyle(
selected: CourierStyles.Inbox.TabItemStyle(
font: CourierStyles.Font(
font: font!,
color: primaryColor
),
indicator: CourierStyles.Inbox.TabIndicatorStyle(
font: CourierStyles.Font(
font: font!,
color: whiteColor
),
color: primaryColor
)
),
unselected: CourierStyles.Inbox.TabItemStyle(
font: CourierStyles.Font(
font: font!,
color: blackLightColor
),
indicator: CourierStyles.Inbox.TabIndicatorStyle(
font: CourierStyles.Font(
font: font!,
color: whiteColor
),
color: blackLightColor
)
)
),
readingSwipeActionStyle: CourierStyles.Inbox.ReadingSwipeActionStyle(
read: CourierStyles.Inbox.SwipeActionStyle(
icon: UIImage(systemName: "envelope.open.fill"),
color: primaryColor
),
unread: CourierStyles.Inbox.SwipeActionStyle(
icon: UIImage(systemName: "envelope.fill"),
color: primaryLightColor
)
),
archivingSwipeActionStyle: CourierStyles.Inbox.ArchivingSwipeActionStyle(
archive: CourierStyles.Inbox.SwipeActionStyle(
icon: UIImage(systemName: "archivebox.fill"),
color: primaryColor
)
),
unreadIndicatorStyle: CourierStyles.Inbox.UnreadIndicatorStyle(
indicator: .dot,
color: primaryColor
),
titleStyle: CourierStyles.Inbox.TextStyle(
unread: CourierStyles.Font(
font: font!,
color: blackColor
),
read: CourierStyles.Font(
font: font!,
color: blackColor
)
),
timeStyle: CourierStyles.Inbox.TextStyle(
unread: CourierStyles.Font(
font: font!,
color: blackColor
),
read: CourierStyles.Font(
font: font!,
color: blackColor
)
),
bodyStyle: CourierStyles.Inbox.TextStyle(
unread: CourierStyles.Font(
font: font!,
color: blackLightColor
),
read: CourierStyles.Font(
font: font!,
color: blackLightColor
)
),
buttonStyle: CourierStyles.Inbox.ButtonStyle(
unread: CourierStyles.Button(
font: CourierStyles.Font(
font: font!,
color: whiteColor
),
backgroundColor: primaryColor,
cornerRadius: 100
),
read: CourierStyles.Button(
font: CourierStyles.Font(
font: font!,
color: whiteColor
),
backgroundColor: primaryColor,
cornerRadius: 100
)
),
cellStyle: CourierStyles.Cell(
separatorStyle: .singleLine,
separatorInsets: .zero
),
infoViewStyle: CourierStyles.InfoViewStyle(
font: CourierStyles.Font(
font: font!,
color: blackColor
),
button: CourierStyles.Button(
font: CourierStyles.Font(
font: font!,
color: whiteColor
),
backgroundColor: primaryColor,
cornerRadius: 100
)
)
)
}
import Courier_iOS
CourierInboxView(
canSwipePages: true,
lightTheme: getTheme(),
darkTheme: getTheme(),
..
)
import Courier_iOS
let courierInbox = CourierInbox(
canSwipePages: true,
lightTheme: getTheme(),
darkTheme: getTheme(),
..
)
You can control your branding from the Courier Studio
.
Supported Brand Styles | Support |
---|---|
Primary Color |
✅ |
Show/Hide Courier Footer |
✅ |
👋 Branding APIs
can be found here
The raw data you can use to build whatever UI you'd like.
import UIKit
import Courier_iOS
class CustomInboxViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
private var inboxListener: CourierInboxListener? = nil
override func viewDidLoad() {
super.viewDidLoad()
Task {
// Allows you to listen to all inbox changes and show a fully custom UI
self.inboxListener = await Courier.shared.addInboxListener(
onLoading: { [weak self] in
// Called when listener is registered, refreshing or restarting
},
onError: { [weak self] error in
// Called on error or sign out
},
onUnreadCountChanged: { [weak self] count in
// Will return 0 when a user is signed out
},
onFeedChanged: { [weak self] set in
// Called when the feed initially loads or is restarted from scratch
},
onArchiveChanged: { [weak self] set in
// Called when the archive initially loads or is restarted from scratch
},
onPageAdded: { [weak self] feed, set in
// Called when pagination happens
},
onMessageChanged: { [weak self] feed, index, message in
// Called when a message is change (i.e. read / unread)
},
onMessageAdded: { [weak self] feed, index, message in
// Called when a message is added (i.e. new message received in realtime)
},
onMessageRemoved: { [weak self] feed, index, message in
// Called when a message is removed (i.e. message is archived)
}
)
}
}
deinit {
self.inboxListener?.remove()
}
}
import Courier_iOS
Task {
// Listen to all inbox events
// Only one "pipe" of data is created behind the scenes for network / performance reasons
let inboxListener = await Courier.shared.addInboxListener(
onLoading: { [weak self] in
// Called when listener is registered, refreshing or restarting
},
onError: { [weak self] error in
// Called on error or sign out
},
onUnreadCountChanged: { [weak self] count in
// Will return 0 when a user is signed out
},
onFeedChanged: { [weak self] set in
// Called when the feed initially loads or is restarted from scratch
},
onArchiveChanged: { [weak self] set in
// Called when the archive initially loads or is restarted from scratch
},
onPageAdded: { [weak self] feed, set in
// Called when pagination happens
},
onMessageChanged: { [weak self] feed, index, message in
// Called when a message is change (i.e. read / unread)
},
onMessageAdded: { [weak self] feed, index, message in
// Called when a message is added (i.e. new message received in realtime)
},
onMessageRemoved: { [weak self] feed, index, message in
// Called when a message is removed (i.e. message is archived)
}
)
// Stop the current listener
inboxListener.remove()
// Remove all listeners
// This will also remove the listener of the prebuilt UI
await Courier.shared.removeAllInboxListeners()
// The amount of inbox messages to fetch at a time
// Will affect prebuilt UI
await Courier.shared.setPaginationLimit(123)
// The available messages the inbox has
let inboxMessages = await Courier.shared.inboxMessages
let archivedMessages = await Courier.shared.archivedMessages
// Fetches the next page of messages
try await Courier.shared.fetchNextInboxPage(.feed || .archived)
// Reloads the inbox
// Commonly used with pull to refresh
try await Courier.shared.refreshInbox()
// Handle events
try await Courier.shared.readMessage("...")
try await Courier.shared.unreadMessage("...")
try await Courier.shared.openMessage("...")
try await Courier.shared.clickMessage("...")
try await Courier.shared.archiveMessage("...")
// Reads all the messages
// Writes the update instantly and performs request in background
try await Courier.shared.readAllInboxMessages()
}
// Mark message as read/unread
let message = InboxMessage(...)
// Calls Courier.shared... under the hood
message.markAsRead()
message.markAsUnread()
message.markAsOpened()
message.markAsClicked()
message.markAsArchived()
👋 Inbox APIs
can be found here