Notification Payload — это JSON-структура, которую сервер отправляет через APNS на устройство iOS, определяя содержимое push-уведомления и поведение при его получении. Пейлоуд включает обязательные и опциональные ключи, управляющие текстом, звуком, badge, медиа-вложениями и фоновой обработкой. По данным Apple Developer Documentation, 2026, максимальный размер пейлоуда составляет 4096 байт для обычных уведомлений и 5120 байт для VoIP push, что накладывает строгие ограничения на количество передаваемых данных.
Главное
Notification Payload (пейлоуд уведомления) — это JSON-объект, который сервер отправляет в APNS (Apple Push Notification Service) для доставки на устройство iOS. Пейлоуд содержит все данные, необходимые системе для отображения уведомления: заголовок, текст, звук, badge и метаданные для фоновой обработки. Структура пейлоуда строго регламентирована Apple и включает обязательные ключи для корректной обработки системой.
Когда сервер отправляет push-уведомление через HTTP/2 API APNS, запрос содержит заголовки авторизации и JSON-тело — пейлоуд. APNS проверяет валидность пейлоуда: если JSON некорректен или превышает лимит размера, сервер Apple возвращает ошибку 400 Bad Request. После валидации APNS доставляет пейлоуд на устройство, где система iOS парсит его и определяет, как обработать уведомление — показать баннер, запустить фоновую задачу или воспроизвести звук.
Формат пейлоуда APNS эволюционировал от простого текстового payload в iOS 2 до многокомпонентной JSON-структуры в современных версиях. iOS 10 принесла поддержку media attachments через mutable-content, iOS 12 добавила группировку уведомлений через thread-id, а iOS 15 ввела supports-live-activities для Live Activities. Сегодня пейлоуд может содержать до 15 различных ключей в зависимости от требуемого поведения уведомления.
Корневой объект пейлоуда содержит словарь aps и опциональные кастомные поля на верхнем уровне. Словарь aps — единственный обязательный элемент, но внутри него могут присутствовать различные комбинации ключей в зависимости от типа уведомления: alert, badge, sound, content-available, mutable-content, interruption-level и другие.
| Ключ aps | Тип | Назначение |
|---|---|---|
| alert | String или Dictionary | Текст уведомления или объект с title, subtitle, body, локализацией |
| badge | Number | Число на иконке приложения; 0 удаляет badge |
| sound | String | Имя звукового файла или default для системного звука |
| content-available | Number (1) | Флаг фоновой активации; 1 = silent push |
| mutable-content | Number (1) | Флаг активации Service Extension для модификации контента |
| category | String | Идентификатор категории для кнопок и Content Extension |
| thread-id | String | Идентификатор группы для группировки уведомлений |
| interruption-level | String | Уровень прерывания: passive, active, time-sensitive, critical |
| relevance-score | Number (0–1) | Приоритет уведомления для системы умного ранжирования |
Ключ alert может быть простой строкой (которая становится телом уведомления) или словарём с полями title, subtitle, body. Словарный формат позволяет задать заголовок и подзаголовок отдельно от основного текста. Для локализованных уведомлений используются ключи title-loc-key, title-loc-args, loc-key, loc-args, которые ссылаются на Localizable.strings приложения. Это позволяет отправлять пейлоуд без текста на конкретном языке — приложение подставляет перевод.
Начиная с iOS 15 Apple добавила механизм Focus Mode, который требует от разработчика указывать уровень прерывания уведомления. interruption-level принимает значения: passive (без звука, без пробуждения экрана), active (стандартное поведение), time-sensitive (пробивает фокус, требует special entitlement) и critical (медицинские/чрезвычайные ситуации). Ключ relevance-score (0–1) помогает системе Focus ранжировать уведомления внутри одной категории.
Ключ thread-id объединяет уведомления в группы в Notification Center. Все уведомления с одинаковым thread-id отображаются как одна группа, которую пользователь может развернуть. Это особенно полезно для мессенджеров, где сообщения от одного контакта группируются вместе, или для приложений, отправляющих много уведомлений одного типа.
Кастомные поля — это любые ключи вне словаря aps, которые разработчик добавляет для передачи дополнительных данных на устройство. Сервер включает их в корневой JSON-объект пейлоуда, а приложение получает их через userInfo в UNNotificationContent. Кастомные поля не должны дублировать имена ключей из aps, чтобы избежать конфликтов при парсинге.
Главное ограничение — общий размер пейлоуда не должен превышать 4096 байт. Кастомные поля конкурируют за этот лимит с обязательными ключами aps, поэтому важно минимизировать размер передаваемых данных. Используйте короткие имена ключей (например, "uid" вместо "user-id"), избегайте больших JSON-структур и передавайте только идентификаторы, а не полные объекты данных.
Кастомные поля приходят от сервера и не должны доверяться без проверки. Всегда валидируйте типы и значения кастомных полей при парсинге: проверяйте наличие ключа через optional binding, конвертируйте в ожидаемый тип с помощью as? String/Int/Dictionary и обрабатывайте случай отсутствия значения. Никогда не используйте force unwrap (!) для данных из пейлоуда — сервер может отправить некорректные данные, и приложение упадёт с crash.
{
"aps": {
"alert": {
"title": "Новое сообщение",
"body": "Привет! Как дела?"
},
"badge": 5,
"sound": "default",
"category": "message",
"thread-id": "chat_4521",
"mutable-content": 1
},
"sender-id": "user_789",
"chat-id": "chat_4521",
"message-type": "text",
"image-url": "https://cdn.example.com/img.jpg"
}
Используйте единый стиль именования кастомных полей во всех пейлоудах проекта. kebab-case (message-type) или camelCase (messageType) — оба подхода допустимы, но важно придерживаться одного в рамках проекта. Избегайте длинных имён: "uid" вместо "user-identifier", "img" вместо "profile-image-url". Каждый символ в имени ключа — это байт из лимита 4096.
Разные сценарии push-уведомлений требуют разных комбинаций ключей в пейлоуде. Рассмотрим несколько типовых примеров: простое текстовое уведомление, уведомление с локализацией, Silent Push и Rich Notification с медиа-вложением.
Базовый пейлоуд с текстом и звуком — минимальная конфигурация для отображения уведомления пользователю. Alert как строка даёт короткое сообщение, sound default воспроизводит стандартный системный звук. Badge опционален и устанавливает счётчик на иконке. category и thread-id добавляются для группировки и интерактивности.
{
"aps": {
"alert": "Напоминание: встреча через 15 минут",
"badge": 3,
"sound": "default"
}
}
Для отправки на устройства с разными языками используйте ключи локализации вместо жёстко заданного текста. title-loc-key ссылается на ключ в Localizable.strings приложения, а title-loc-args подставляет аргументы. Это позволяет отправить один пейлоуд на все устройства, а приложение само отобразит текст на нужном языке.
{
"aps": {
"alert": {
"title-loc-key": "NEW_MESSAGE_TITLE",
"title-loc-args": ["Анна"],
"loc-key": "NEW_MESSAGE_BODY",
"loc-args": ["Привет!"]
},
"sound": "message.caf"
}
}
Для фоновой синхронизации без показа уведомления используется content-available: 1 и отсутствие alert. Кастомные поля указывают тип операции и данные для обработки. Система активирует приложение в фоне, вызывает didReceiveRemoteNotification с fetchCompletionHandler, и приложение выполняет синхронизацию.
{
"aps": {
"content-available": 1
},
"sync-type": "invalidate-cache",
"timestamp": "2026-07-03T12:00:00Z"
}
Для отображения медиа-вложения необходим mutable-content: 1 для активации Service Extension и URL изображения в кастомном поле. mutating-content: 1 сигнализирует системе запустить UNNotificationServiceExtension, который загрузит изображение по URL и добавит его как UNNotificationAttachment. category указывает на зарегистрированную категорию для отображения кнопок действий.
{
"aps": {
"alert": {
"title": "Новый товар",
"body": "Посмотрите новую коллекцию"
},
"category": "product",
"mutable-content": 1
},
"media-url": "https://cdn.example.com/product.jpg"
}
UNNotificationContent.userInfo содержит полный словарь полученного пейлоуда после обработки системой. Приложение получает доступ к пейлоуду в делегате UNUserNotificationCenter при получении уведомления (на переднем плане), при нажатии на уведомление, а также в Service Extension и Content Extension. Корректный парсинг обязателен для извлечения кастомных данных и определения дальнейших действий.
Когда пользователь нажимает на уведомление, система вызывает метод didReceive response в UNUserNotificationCenterDelegate. В response.notification.request.content.userInfo содержится полный пейлоуд. Разработчик извлекает кастомные поля, определяет тип действия (например, открыть чат, перейти на товар) и вызывает соответствующую навигацию в приложении.
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
let userInfo = response.notification
.request.content.userInfo
guard let chatId = userInfo["chat-id"] as? String
else {
completionHandler()
return
}
let messageType = userInfo["message-type"]
as? String ?? "text"
NavigationRouter.shared.navigate(
to: .chat(chatId: chatId,
messageType: messageType))
completionHandler()
}
Service Extension получает пейлоуд до показа уведомления и может модифицировать его. Валидация пейлоуда — первый шаг в didReceive: проверьте наличие обязательных кастомных полей, корректность URL для вложений и тип данных. Если пейлоуд невалиден, вызовите completion handler с исходным контентом немедленно, не тратя время на бесполезную обработку.
Для отладки push-уведомлений на продакшне используйте структурированное логирование пейлоудов. OSLog позволяет логировать пейлоуд с категорией "notifications" и уровнем debug. На серверной стороне отслеживайте ответы APNS: успешный ответ содержит apns-id для сопоставления с отправленным пейлоудом, а ошибка 400 указывает на невалидный JSON или превышение размера.
Часто задаваемые вопросы
Максимальный размер пейлоуда — 4096 байт для обычных push-уведомлений и 5120 байт для VoIP push (PushKit). При превышении APNS возвращает ошибку 400 Bad Request. Размер считается в байтах, не в символах — учитывайте UTF-8 кодировку.
Используйте ключи loc-key, title-loc-key, loc-args и title-loc-args внутри alert. Приложение подставляет перевод из своего Localizable.strings на основе языка устройства. Это позволяет отправить один пейлоуд на все устройства независимо от их языка.
content-available активирует приложение в фоне для обработки данных (silent push) без показа уведомления. mutable-content активирует Service Extension для модификации контента перед показом. Оба ключа могут использоваться вместе для фоновой обработки и последующей модификации уведомления.
Используйте APNS Sandbox для тестирования и проверяйте HTTP-ответ сервера Apple: 200 OK означает успешную отправку. Для валидации структуры используйте JSON-схемы в CI/CD пайплайне. В Xcode отправляйте тестовые уведомления через симулятор командой xcrun simctl push.
apns-id — уникальный идентификатор push-уведомления в системе APNS, который возвращается в ответе на успешную отправку. Используется для отслеживания доставки через Logs API и для отладки. Сервер должен сохранять apns-id для каждого отправленного уведомления.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также