Notification Payload — este structura JSON pe care serverul o trimite prin APNS către dispozitivul iOS, determinând conținutul notificării push și comportamentul la primirea acesteia. Payload-ul include chei obligatorii și opționale care controlează textul, sunetul, badge-ul, atașamentele media și procesarea în fundal. Conform Apple Developer Documentation, 2026, dimensiunea maximă a payload-ului este de 4096 de octeți pentru notificările obișnuite și 5120 de octeți pentru VoIP push, ceea ce impune restricții stricte asupra cantității de date transmise.
Principalele puncte
Notification Payload (payload-ul notificării) — este un obiect JSON pe care serverul îl trimite către APNS (Apple Push Notification Service) pentru livrare pe dispozitivul iOS. Payload-ul conține toate datele necesare sistemului pentru afișarea notificării: titlu, text, sunet, badge și metadate pentru procesarea în fundal. Structura payload-ului este strict reglementată de Apple și include chei obligatorii pentru procesarea corectă de către sistem.
Când serverul trimite o notificare push prin HTTP/2 API APNS, cererea conține antete de autorizare și corpul JSON — payload-ul. APNS verifică validitatea payload-ului: dacă JSON-ul este incorect sau depășește limita de dimensiune, serverul Apple returnează o eroare 400 Bad Request. După validare, APNS livrează payload-ul pe dispozitiv, unde sistemul iOS îl parsează și determină cum să proceseze notificarea — să afișeze un banner, să lanseze o sarcină în fundal sau să redea un sunet.
Formatul payload-ului APNS a evoluat de la un simplu payload text în iOS 2 la o structură JSON multicomponentă în versiunile moderne. iOS 10 a adus suport pentru atașamente media prin mutable-content, iOS 12 a adăugat gruparea notificărilor prin thread-id, iar iOS 15 a introdus supports-live-activities pentru Live Activities. Astăzi, payload-ul poate conține până la 15 chei diferite, în funcție de comportamentul dorit al notificării.
Obiectul rădăcină al payload-ului conține dicționarul aps și câmpuri personalizate opționale la nivel superior. Dicționarul aps este singurul element obligatoriu, dar în interiorul său pot apărea diferite combinații de chei în funcție de tipul notificării: alert, badge, sound, content-available, mutable-content, interruption-level și altele.
| Cheia aps | Tip | Destinație |
|---|---|---|
| alert | String sau Dictionary | Textul notificării sau obiect cu title, subtitle, body, localizare |
| badge | Number | Numărul pe iconița aplicației; 0 șterge badge-ul |
| sound | String | Numele fișierului audio sau default pentru sunetul de sistem |
| content-available | Number (1) | Flag de activare în fundal; 1 = silent push |
| mutable-content | Number (1) | Flag de activare Service Extension pentru modificarea conținutului |
| category | String | Identificatorul categoriei pentru butoane și Content Extension |
| thread-id | String | Identificatorul grupului pentru gruparea notificărilor |
| interruption-level | String | Nivelul de întrerupere: passive, active, time-sensitive, critical |
| relevance-score | Number (0–1) | Prioritatea notificării pentru sistemul de clasificare inteligentă |
Cheia alert poate fi un simplu șir de caractere (care devine corpul notificării) sau un dicționar cu câmpurile title, subtitle, body. Formatul dicționar permite setarea titlului și subtitlului separat de textul principal. Pentru notificări localizate se folosesc cheile title-loc-key, title-loc-args, loc-key, loc-args, care fac referire la Localizable.strings al aplicației. Acest lucru permite trimiterea unui payload fără text într-o anumită limbă — aplicația înlocuiește traducerea.
Începând cu iOS 15, Apple a adăugat mecanismul Focus Mode, care necesită ca dezvoltatorul să specifice nivelul de întrerupere al notificării. interruption-level acceptă valorile: passive (fără sunet, fără trezirea ecranului), active (comportament standard), time-sensitive (străpunge focusul, necesită special entitlement) și critical (situații medicale/de urgență). Cheia relevance-score (0–1) ajută sistemul Focus să clasifice notificările în cadrul aceleiași categorii.
Cheia thread-id combină notificările în grupuri în Notification Center. Toate notificările cu același thread-id sunt afișate ca un singur grup pe care utilizatorul îl poate extinde. Acest lucru este util în special pentru aplicațiile de mesagerie, unde mesajele de la un contact sunt grupate împreună, sau pentru aplicațiile care trimit multe notificări de același tip.
Câmpuri personalizate — sunt orice chei în afara dicționarului aps pe care dezvoltatorul le adaugă pentru a transmite date suplimentare către dispozitiv. Serverul le include în obiectul JSON rădăcină al payload-ului, iar aplicația le primește prin userInfo în UNNotificationContent. Câmpurile personalizate nu trebuie să dubleze numele cheilor din aps pentru a evita conflictele la parsare.
Principala restricție — dimensiunea totală a payload-ului nu trebuie să depășească 4096 de octeți. Câmpurile personalizate concurează pentru această limită cu cheile obligatorii aps, de aceea este important să minimizați dimensiunea datelor transmise. Folosiți nume scurte de chei (de exemplu, „uid“ în loc de „user-id“), evitați structurile JSON mari și transmiteți doar identificatori, nu obiecte de date complete.
Câmpurile personalizate vin de la server și nu trebuie să aveți încredere în ele fără verificare. Validați întotdeauna tipurile și valorile câmpurilor personalizate la parsare: verificați prezența cheii prin optional binding, convertiți la tipul așteptat cu as? String/Int/Dictionary și gestionați cazul absenței valorii. Nu folosiți niciodată force unwrap (!) pentru datele din payload — serverul poate trimite date incorecte, iar aplicația se va prăbuși.
{
"aps": {
"alert": {
"title": "Mesaj nou",
"body": "Salut! Ce faci?"
},
"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"
}
Folosiți un stil unitar de denumire a câmpurilor personalizate în toate payload-urile proiectului. kebab-case (message-type) sau camelCase (messageType) — ambele abordări sunt acceptabile, dar este important să respectați una în cadrul proiectului. Evitați numele lungi: „uid“ în loc de „user-identifier“, „img“ în loc de „profile-image-url“. Fiecare caracter din numele cheii este un octet din limita de 4096.
Diferite scenarii de notificări push necesită diferite combinații de chei în payload. Să analizăm câteva exemple tipice: notificare text simplă, notificare cu localizare, Silent Push și Rich Notification cu atașament media.
Payload de bază cu text și sunet — configurația minimă pentru afișarea unei notificări utilizatorului. Alert ca șir de caractere oferă un mesaj scurt, sound default redă sunetul standard de sistem. Badge-ul este opțional și setează contorul pe iconiță. category și thread-id sunt adăugate pentru grupare și interactivitate.
{
"aps": {
"alert": "Amintire: întâlnirea în 15 minute",
"badge": 3,
"sound": "default"
}
}
Pentru trimiterea către dispozitive cu limbi diferite, folosiți chei de localizare în loc de text fix. title-loc-key face referire la o cheie din Localizable.strings al aplicației, iar title-loc-args înlocuiește argumentele. Acest lucru permite trimiterea unui singur payload către toate dispozitivele, iar aplicația afișează textul în limba corespunzătoare.
{
"aps": {
"alert": {
"title-loc-key": "NEW_MESSAGE_TITLE",
"title-loc-args": ["Ana"],
"loc-key": "NEW_MESSAGE_BODY",
"loc-args": ["Salut!"]
},
"sound": "message.caf"
}
}
Pentru sincronizarea în fundal fără afișarea notificării, se folosește content-available: 1 și absența alert. Câmpurile personalizate indică tipul operațiunii și datele de procesat. Sistemul activează aplicația în fundal, apelează didReceiveRemoteNotification cu fetchCompletionHandler, iar aplicația execută sincronizarea.
{
"aps": {
"content-available": 1
},
"sync-type": "invalidate-cache",
"timestamp": "2026-07-03T12:00:00Z"
}
Pentru afișarea unui atașament media este necesar mutable-content: 1 pentru activarea Service Extension și URL-ul imaginii într-un câmp personalizat. mutable-content: 1 semnalează sistemului să lanseze UNNotificationServiceExtension, care va descărca imaginea de la URL și o va adăuga ca UNNotificationAttachment. category indică o categorie înregistrată pentru afișarea butoanelor de acțiune.
{
"aps": {
"alert": {
"title": "Produs nou",
"body": "Vezi noua colecție"
},
"category": "product",
"mutable-content": 1
},
"media-url": "https://cdn.example.com/product.jpg"
}
UNNotificationContent.userInfo conține dicționarul complet al payload-ului primit după procesarea de către sistem. Aplicația accesează payload-ul în delegatul UNUserNotificationCenter la primirea notificării (în prim-plan), la apăsarea notificării, precum și în Service Extension și Content Extension. Parsarea corectă este obligatorie pentru extragerea datelor personalizate și determinarea acțiunilor ulterioare.
Când utilizatorul apasă pe o notificare, sistemul apelează metoda didReceive response în UNUserNotificationCenterDelegate. În response.notification.request.content.userInfo se află payload-ul complet. Dezvoltatorul extrage câmpurile personalizate, determină tipul acțiunii (de exemplu, deschiderea chatului, navigarea la produs) și apelează navigarea corespunzătoare în aplicație.
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 primește payload-ul înainte de afișarea notificării și îl poate modifica. Validarea payload-ului — primul pas în didReceive: verificați prezența câmpurilor personalizate obligatorii, corectitudinea URL-ului pentru atașamente și tipul datelor. Dacă payload-ul este invalid, apelați imediat completion handler cu conținutul original, fără a pierde timp cu procesare inutilă.
Pentru depanarea notificărilor push în producție, utilizați logarea structurată a payload-urilor. OSLog permite logarea payload-ului cu categoria „notifications“ și nivelul debug. Pe partea de server, urmăriți răspunsurile APNS: un răspuns de succes conține apns-id pentru corelare cu payload-ul trimis, iar eroarea 400 indică un JSON invalid sau depășirea dimensiunii.
Întrebări frecvente
Dimensiunea maximă a payload-ului — 4096 de octeți pentru notificările push obișnuite și 5120 de octeți pentru VoIP push (PushKit). La depășire, APNS returnează eroarea 400 Bad Request. Dimensiunea se calculează în octeți, nu în caractere — luați în considerare codificarea UTF-8.
Folosiți cheile loc-key, title-loc-key, loc-args și title-loc-args în interiorul alert. Aplicația înlocuiește traducerea din Localizable.strings propriu pe baza limbii dispozitivului. Acest lucru permite trimiterea unui singur payload către toate dispozitivele, indiferent de limba lor.
content-available activează aplicația în fundal pentru procesarea datelor (silent push) fără a afișa notificarea. mutable-content activează Service Extension pentru modificarea conținutului înainte de afișare. Ambele chei pot fi folosite împreună pentru procesarea în fundal și modificarea ulterioară a notificării.
Utilizați APNS Sandbox pentru testare și verificați răspunsul HTTP al serverului Apple: 200 OK înseamnă trimitere reușită. Pentru validarea structurii, folosiți scheme JSON în pipeline-ul CI/CD. În Xcode, trimiteți notificări de test prin simulator cu comanda xcrun simctl push.
apns-id — un identificator unic al notificării push în sistemul APNS, returnat în răspunsul la o trimitere reușită. Folosit pentru urmărirea livrării prin Logs API și pentru depanare. Serverul ar trebui să salveze apns-id pentru fiecare notificare trimisă.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și