Notification Payload は、サーバーが APNS を通じて iOS デバイスに送信する JSON 構造体であり、push 通知の内容と受信時の動作を定義します。ペイロードには、テキスト、音、バッジ、メディア添付、バックグラウンド処理を制御する必須およびオプションのキーが含まれます。Apple Developer Documentation, 2026によると、一般的な通知の場合、最大ペイロードサイズは 4096 バイト、VoIP push の場合は 5120 バイトであり、転送できるデータ量に厳格な制限を設けています。
まとめ
Notification Payload は、サーバーが APNS (Apple Push Notification Service) に送信し、iOS デバイスに配信する JSON オブジェクトです。ペイロードには、システムが通知を表示するために必要なすべてのデータが含まれます: タイトル、テキスト、音、バッジ、バックグラウンド処理のためのメタデータです。ペイロード構造は Apple によって厳格に規制されており、システムが正しく処理できるように必須のキーが含まれています。
サーバーが APNS HTTP/2 API を通じて push 通知を送信するとき、リクエストには認証ヘッダーと JSON ボディ—ペイロードが含まれます。APNS はペイロードを検証します: JSON が不正だったり、サイズ制限を超えたりすると、Apple サーバーは 400 Bad Request エラーを返します。検証後、APNS はペイロードをデバイスに配信し、iOS がそれを解析して、通知の処理方法—バナーの表示、バックグラウンドタスクの実行、音の再生—を決定します。
APNS ペイロード形式は、iOS 2 の簡単なテキストペイロードから、現代のバージョンでの複数コンポーネントからなる JSON 構造へと進化しました。iOS 10 では mutable-content によるメディア添付のサポートが登場し、iOS 12 では thread-id による通知グルーピングが追加され、iOS 15 ではライブアクティビティのための supports-live-activities が導入されました。今日では、ペイロードには、必要な通知の動作に応じて最大 15 の異なるキーを含めることができます。
ルートオブジェクトには、aps ディクショナリとトップレベルのオプションのカスタムフィールドが含まれます。aps ディクショナリは唯一の必須要素ですが、その中には、通知のタイプに応じて、alert、badge、sound、content-available、mutable-content、interruption-level などの複数のキーの組み合わせが存在します。
| aps キー | タイプ | 目的 |
|---|---|---|
| alert | String または Dictionary | 通知のテキスト、または title、subtitle、body、ローカライゼーションを含むオブジェクト |
| badge | Number | アプリアイコン上の数字; 0 はバッジを削除 |
| sound | String | 音声ファイル名またはシステム音の場合は default |
| content-available | Number (1) | バックグラウンド起動フラグ; 1 = サイレント 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 (フォーカスを抜ける、特別な権限が必要)、critical (医療・緊急事態) の値を取ります。relevance-score (0–1) は、フォーカスシステムが同じカテゴリ内の通知をランク付けするのに役立ちます。
thread-id キーは、ノーティフィケーションセンターで通知をグループ化します。同じ thread-id をもつすべての通知は、ユーザーが展開できる単一のグループとして表示されます。これは、メッセンジャーで同じ連絡先からのメッセージがまとめられる場合や、同じタイプの複数の通知を送信するアプリに特に便利です。
カスタムフィールドは、aps ディクショナリの外部にあり、開発者がデバイスに追加データを送信するために追加するキーです。サーバーはそれらをペイロードのルート JSON オブジェクトに含め、アプリは UNNotificationContent の userInfo を通じて取得します。カスタムフィールドは aps とキー名が重複してはならず、解析中の競合を防ぎます。
主な制限は、ペイロードの総サイズが 4096 バイトを超えてはならないことです。カスタムフィールドは、必須の aps キーとこの制限を争うため、送信するデータのサイズを最小限にすることが重要です。ショートなキー名を使用し(例: “uid” は “user-id” の代わり)、大きな JSON 構造を避け、完全なデータオブジェクトの代わりに識別子のみを送信します。
カスタムフィールドは、サーバーから伝わり、検証なしで信頼してはなりません。常に検証してください解析時にカスタムフィールドの型と値を: オプショナルバインディングでキーの存在を確認し、as? String/Int/Dictionary で期待される型に変換し、値がない場合の処理を行います。ペイロードからのデータに対しては、force unwrap (!) を絶対に使用しないでください—サーバーが無効なデータを送信する可能性があり、アプリがクラッシュする可能性があります。
{
"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 制限の 1 バイトを消費します。
異なるシナリオの push 通知では、ペイロードのキーの組み合わせが違います。いくつかのタイピカルな例を見てみましょう: シンプルなテキスト通知、ローカライズされた通知、サイレント push、メディア添付付きリッチ通知です。
テキストと音のベーシックなペイロード—ユーザーに通知を表示するための最小構成です。文字列としての alertは短いメッセージを提供し、sound default は標準のシステム音を再生します。Badge はオプションで、アプリアイコン上の数値を設定します。category と thread-id は、グルーピングとインタラクティビティのために追加されます。
{
"aps": {
"alert": "リマインダー: 15分後に会議",
"badge": 3,
"sound": "default"
}
}
異なる言語のデバイスに通知を送信するには、ハードコードされたテキストの代わりに、ローカライゼーションキーを使用します。title-loc-keyは、アプリの Localizable.strings のキーを参照し、title-loc-args は引数を提供します。これにより、すべてのデバイスに 1 つのペイロードを送信でき、アプリが適切な言語でテキストを表示します。
{
"aps": {
"alert": {
"title-loc-key": "NEW_MESSAGE_TITLE",
"title-loc-args": ["アンナ"],
"loc-key": "NEW_MESSAGE_BODY",
"loc-args": ["こんにちは!"]
},
"sound": "message.caf"
}
}
通知を表示せずにバックグラウンド同期を行うには、alert なしで content-available: 1 を使用します。カスタムフィールドは、処理のための操作タイプとデータを指定します。システムは、アプリをバックグラウンドで起動し、fetchCompletionHandler で didReceiveRemoteNotification をコールし、アプリが同期を実行します。
{
"aps": {
"content-available": 1
},
"sync-type": "invalidate-cache",
"timestamp": "2026-07-03T12:00:00Z"
}
メディア添付を表示するには、Service Extension を起動するための mutable-content: 1 と、カスタムフィールド内の画像 URL が必要です。mutable-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 でペイロードにアクセスします。カスタムデータを抽出し、次のアクションを決定するためには、正しいパーシングが不可欠です。
ユーザーが通知をタップすると、システムは UNUserNotificationCenterDelegate の didReceive response メソッドをコールします。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 を検証し、データ型を検証します。ペイロードが無効の場合は、不要な処理に時間をかけないように、即座に元のコンテンツでコンプリーションハンドラーをコールします。
プロダクションで push 通知をデバッグするには、構造化されたペイロードロギングを使用します。OSLogは、“notifications” カテゴリで debug レベルでペイロードをログできます。サーバー側では APNS 応答を監視します: 成功応答には、送信されたペイロードとの対応付けのための apns-id が含まれ、400 エラーは不正な JSON またはサイズ制限超過を示しています。
よくある質問
最大ペイロードサイズは、一般的な push 通知の場合は 4096 バイト、VoIP push (PushKit) の場合は 5120 バイトです。この制限を超えると、APNS は 400 Bad Request エラーを返します。サイズは文字ではなくバイトで計算されます—UTF-8 エンコーディングを考慮してください。
alert 内で loc-key、title-loc-key、loc-args、title-loc-args のキーを使用します。アプリは、デバイスの言語に基づいて、自分の Localizable.strings から翻訳を代入します。これにより、言語に関係なく、すべてのデバイスに単一のペイロードを送信できます。
content-availableは、通知を表示せずに、データ処理(サイレント push)のためにアプリをバックグラウンドで起動します。mutable-contentは、表示前にコンテンツを変更する Service Extension を起動します。両方のキーを組み合わせて、バックグラウンド処理とその後の通知変更を行うことができます。
テストには APNS Sandbox を使用し、Apple サーバーの HTTP 応答を確認します: 200 OK は配信成功を意味します。構造検証には、CI/CD パイプラインで JSON スキーマを使用します。Xcode では、xcrun simctl push を使用してシミュレーターでテスト通知を送信します。
apns-idは、APNS システムにおける固有の push 通知識別子で、配信成功後に応答で返されます。Logs API を通じて配信を追跡したり、デバッグに使用されます。サーバーは、送信された各通知に対して apns-id を保存する必要があります。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。