Notification Payload é uma estrutura JSON que o servidor envia através do APNS para um dispositivo iOS, definindo o conteúdo de uma notificação push e o comportamento ao recebê-la. O payload inclui chaves obrigatórias e opcionais que controlam texto, som, badge, anexos de mídia e processamento em segundo plano. De acordo com Apple Developer Documentation, 2026, o tamanho máximo do payload é de 4096 bytes para notificações comuns e 5120 bytes para VoIP push, impondo limites rigorosos à quantidade de dados transferidos.
Principais Pontos
Notification Payload é um objeto JSON que o servidor envia ao APNS (Apple Push Notification Service) para entrega a um dispositivo iOS. O payload contém todos os dados necessários para o sistema exibir a notificação: título, texto, som, badge e metadados para processamento em segundo plano. A estrutura do payload é estritamente regulamentada pela Apple e inclui chaves obrigatórias para o processamento correto pelo sistema.
Quando o servidor envia uma notificação push através da API HTTP/2 do APNS, a solicitação contém cabeçalhos de autorização e um corpo JSON — o payload. APNS valida o payload: se o JSON for inválido ou exceder o limite de tamanho, o servidor da Apple retorna um erro 400 Bad Request. Após a validação, o APNS entrega o payload ao dispositivo, onde o iOS o analisa e determina como lidar com a notificação — exibir um banner, executar uma tarefa em segundo plano ou reproduzir um som.
O formato do payload APNS evoluiu de um payload de texto simples no iOS 2 para uma estrutura JSON multicomponente nas versões modernas. iOS 10 introduziu suporte para anexos de mídia via mutable-content, iOS 12 adicionou agrupamento de notificações via thread-id, e iOS 15 introduziu supports-live-activities para Live Activities. Hoje, um payload pode conter até 15 chaves diferentes dependendo do comportamento desejado da notificação.
O objeto raiz do payload contém um dicionário aps e campos personalizados opcionais no nível superior. O dicionário aps é o único elemento obrigatório, mas várias combinações de chaves podem aparecer dependendo do tipo de notificação: alert, badge, sound, content-available, mutable-content, interruption-level e outras.
| Chave aps | Tipo | Propósito |
|---|---|---|
| alert | String ou Dictionary | Texto da notificação ou objeto com title, subtitle, body e localização |
| badge | Number | Número no ícone do aplicativo; 0 remove o badge |
| sound | String | Nome do arquivo de som ou default para o som do sistema |
| content-available | Number (1) | Sinalizador de ativação em segundo plano; 1 = silent push |
| mutable-content | Number (1) | Sinalizador de ativação da Service Extension para modificar conteúdo |
| category | String | Identificador de categoria para botões e Content Extension |
| thread-id | String | Identificador de grupo para agrupar notificações |
| interruption-level | String | Nível de interrupção: passive, active, time-sensitive, critical |
| relevance-score | Number (0–1) | Prioridade da notificação para o sistema de classificação inteligente |
A chave alert pode ser uma string simples (que se torna o corpo da notificação) ou um dicionário com os campos title, subtitle e body. O formato dicionário permite definir o título e subtítulo separadamente do texto principal. Para notificações localizadas, são usadas as chaves title-loc-key, title-loc-args, loc-key e loc-args, que referenciam o Localizable.strings do aplicativo. Isso permite enviar um payload sem texto em um idioma específico — o aplicativo substitui a tradução.
A partir do iOS 15, a Apple introduziu o mecanismo Focus Mode, que exige que o desenvolvedor especifique o nível de interrupção da notificação. interruption-level aceita os valores: passive (sem som, sem ativar a tela), active (comportamento padrão), time-sensitive (atravessa o Focus, requer autorização especial) e critical (situações médicas/de emergência). A chave relevance-score (0–1) ajuda o sistema Focus a classificar notificações dentro de uma mesma categoria.
A chave thread-id agrupa notificações na Central de Notificações. Todas as notificações com o mesmo thread-id são exibidas como um único grupo que o usuário pode expandir. Isso é especialmente útil para mensageiros, onde as mensagens de um contato são agrupadas, ou para aplicativos que enviam muitas notificações do mesmo tipo.
Campos personalizados são quaisquer chaves fora do dicionário aps que o desenvolvedor adiciona para transmitir dados adicionais ao dispositivo. O servidor os inclui no objeto JSON raiz do payload, e o aplicativo os recupera via userInfo em UNNotificationContent. Campos personalizados não devem duplicar nomes de chaves do aps para evitar conflitos de análise.
A principal limitação é que o tamanho total do payload não deve exceder 4096 bytes. Campos personalizados competem por esse limite com as chaves obrigatórias do aps, por isso é importante minimizar o tamanho dos dados transmitidos. Use nomes de chave curtos (por exemplo, “uid” em vez de “user-id”), evite grandes estruturas JSON e transmita apenas identificadores em vez de objetos de dados completos.
Campos personalizados vêm do servidor e não devem ser confiados sem verificação. Sempre valide os tipos e valores dos campos personalizados ao analisá-los: verifique a existência da chave via binding opcional, converta para o tipo esperado com as? String/Int/Dictionary e trate o caso de valor ausente. Nunca use force unwrap (!) para dados do payload — o servidor pode enviar dados inválidos, causando a falha do aplicativo.
{
"aps": {
"alert": {
"title": "Nova mensagem",
"body": "Olá! Como vai?"
},
"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"
}
Use um estilo de nomenclatura consistente para campos personalizados em todos os payloads do projeto. kebab-case (message-type) ou camelCase (messageType) — ambas as abordagens são aceitáveis, mas a consistência dentro do projeto é importante. Evite nomes longos: “uid” em vez de “user-identifier”, “img” em vez de “profile-image-url”. Cada caractere em um nome de chave consome um byte do limite de 4096.
Cenários diferentes de notificações push exigem diferentes combinações de chaves no payload. Vejamos vários exemplos típicos: uma notificação de texto simples, uma notificação localizada, um Silent Push e uma Notificação Rich com anexo de mídia.
Um payload básico com texto e som — a configuração mínima para exibir uma notificação ao usuário. Alert como string fornece uma mensagem curta, sound default reproduz o som padrão do sistema. Badge é opcional e define o contador no ícone do aplicativo. category e thread-id são adicionados para agrupamento e interatividade.
{
"aps": {
"alert": "Lembrete: reunião em 15 minutos",
"badge": 3,
"sound": "default"
}
}
Para enviar notificações para dispositivos com idiomas diferentes, use chaves de localização em vez de texto fixo. title-loc-key referencia uma chave no Localizable.strings do aplicativo, e title-loc-args fornece argumentos. Isso permite enviar um único payload para todos os dispositivos, e o aplicativo exibe o texto no idioma apropriado.
{
"aps": {
"alert": {
"title-loc-key": "NEW_MESSAGE_TITLE",
"title-loc-args": ["Ana"],
"loc-key": "NEW_MESSAGE_BODY",
"loc-args": ["Olá!"]
},
"sound": "message.caf"
}
}
Para sincronização em segundo plano sem exibir uma notificação, use content-available: 1 sem alert. Campos personalizados especificam o tipo de operação e os dados para processamento. O sistema ativa o aplicativo em segundo plano, chama didReceiveRemoteNotification com fetchCompletionHandler, e o aplicativo realiza a sincronização.
{
"aps": {
"content-available": 1
},
"sync-type": "invalidate-cache",
"timestamp": "2026-07-03T12:00:00Z"
}
Para exibir um anexo de mídia, é necessário mutable-content: 1 para ativar a Service Extension, juntamente com uma URL de imagem em um campo personalizado. mutable-content: 1 sinaliza ao sistema para iniciar UNNotificationServiceExtension, que baixa a imagem da URL e a adiciona como UNNotificationAttachment. A chave category especifica uma categoria registrada para exibir botões de ação.
{
"aps": {
"alert": {
"title": "Novo produto",
"body": "Confira a nova coleção"
},
"category": "product",
"mutable-content": 1
},
"media-url": "https://cdn.example.com/product.jpg"
}
UNNotificationContent.userInfo contém o dicionário completo do payload recebido após o processamento do sistema. O aplicativo acessa o payload no delegado do UNUserNotificationCenter ao receber uma notificação (em primeiro plano), ao tocar em uma notificação, bem como na Service Extension e Content Extension. A análise correta é essencial para extrair dados personalizados e determinar as próximas ações.
Quando o usuário toca em uma notificação, o sistema chama o método didReceive response no UNUserNotificationCenterDelegate. response.notification.request.content.userInfo contém o payload completo. O desenvolvedor extrai campos personalizados, determina o tipo de ação (por exemplo, abrir um chat, navegar para um produto) e aciona a navegação correspondente no aplicativo.
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()
}
A Service Extension recebe o payload antes da notificação ser exibida e pode modificá-lo. A validação do payload é o primeiro passo em didReceive: verifique campos personalizados obrigatórios, valide a URL do anexo e verifique os tipos de dados. Se o payload for inválido, chame o completion handler com o conteúdo original imediatamente para evitar desperdício de tempo em processamento desnecessário.
Para depurar notificações push em produção, use registro estruturado de payloads. OSLog permite registrar o payload com a categoria “notifications” no nível debug. No lado do servidor, monitore as respostas do APNS: uma resposta bem-sucedida contém apns-id para corresponder ao payload enviado, enquanto um erro 400 indica JSON malformado ou excedente de tamanho.
Perguntas Frequentes
O tamanho máximo do payload é 4096 bytes para notificações push comuns e 5120 bytes para VoIP push (PushKit). Exceder este limite faz com que o APNS retorne um erro 400 Bad Request. O tamanho é contado em bytes, não em caracteres — considere a codificação UTF-8.
Use as chaves loc-key, title-loc-key, loc-args e title-loc-args dentro de alert. O aplicativo substitui a tradução do seu Localizable.strings com base no idioma do dispositivo. Isso permite enviar um único payload para todos os dispositivos independentemente do idioma.
content-available ativa o aplicativo em segundo plano para processamento de dados (silent push) sem exibir uma notificação. mutable-content ativa a Service Extension para modificar o conteúdo antes da exibição. Ambas as chaves podem ser usadas juntas para processamento em segundo plano e posterior modificação da notificação.
Use APNS Sandbox para testes e verifique a resposta HTTP do servidor da Apple: 200 OK significa entrega bem-sucedida. Para validação de estrutura, use esquemas JSON no seu pipeline CI/CD. No Xcode, envie notificações de teste pelo simulador usando xcrun simctl push.
apns-id é um identificador único de notificação push no sistema APNS, retornado na resposta após uma entrega bem-sucedida. É usado para rastrear a entrega via Logs API e para depuração. O servidor deve armazenar apns-id para cada notificação enviada.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também