Device Token — це унікальний ідентифікатор, який APNS призначає кожному пристрою iOS для маршрутизації push-сповіщень. Токен генерується системою під час реєстрації додатка для отримання сповіщень і повинен бути переданий на сервер для надсилання push саме на цей пристрій. Згідно з Apple Developer Documentation, 2026, Device Token може змінюватися при перевстановленні додатка, відновленні пристрою з резервної копії або оновленні iOS, тому сервер повинен регулярно оновлювати токени для забезпечення доставки.
Головне
Device Token (токен пристрою) — це унікальний ідентифікатор у вигляді hex-рядка, який APNS (Apple Push Notification Service) генерує для кожного додатка на пристрої iOS. Токен є ключем, за яким сервер надсилає push-сповіщення на конкретний пристрій. Без коректного Device Token сервер не може доставити push — APNS відхиляє запит з помилкою 400 BadRequest.
Device Token створюється системою iOS при першому зверненні додатка до APNS після встановлення. Процес генерації включає криптографічну прив'язку до ідентифікатора додатка (bundle ID) та унікального ідентифікатора пристрою (UID), після чого APNS повертає додатку 32-байтовий токен у hex-форматі (64 символи). Токен не є постійним — система може згенерувати новий за певних умов.
Коли сервер надсилає push-сповіщення, він включає Device Token у HTTP/2 запит до APNS. APNS перевіряє дійсність токена: якщо токен належить до іншого середовища (sandbox замість production), прострочений або відкликаний, сервер Apple повертає помилку 410 Gone або 400 BadRequest. Тільки після успішної перевірки токена APNS починає доставку сповіщення на пристрій.
Device Token не слід плутати з IDFA (Identifier for Advertisers), IDFV (Identifier for Vendor) або UID (Unique Device Identifier). IDFA та IDFV використовуються для реклами та аналітики, UID — апаратний серійний номер. Device Token існує виключно для push-сповіщень і не розкриває інформацію про користувача або пристрій за межами APNS.
| Ідентифікатор | Призначення | Постійність |
|---|---|---|
| Device Token | Маршрутизація push-сповіщень APNS | Може змінитися |
| IDFA | Реклама та відстеження | Скидається користувачем |
| IDFV | Ідентифікація вендора (аналітика) | Постійний для додатків одного розробника |
| Bundle ID | Унікальний ідентифікатор додатка | Постійний |
Процес отримання Device Token складається з кількох обов'язкових кроків, починаючи від запиту дозволу у користувача і закінчуючи передачею токена на сервер. Кожен крок критично важливий — пропуск будь-якого з них призводить до неможливості надсилання push-сповіщень на пристрій.
Першим кроком додаток запитує у користувача дозвіл на надсилання сповіщень через UNUserNotificationCenter.current().requestAuthorization. Користувач може погодитися, заборонити або вибрати опціональні опції (alert, badge, sound). Без явної згоди користувача система не видасть Device Token, навіть якщо додаток викличе registerForRemoteNotifications. Після отримання дозволу додаток викликає UIApplication.shared.registerForRemoteNotifications(), що ініціює процес реєстрації в APNS.
Після реєстрації APNS повертає токен через делегат AppDelegate: application(_:didRegisterForRemoteNotificationsWithDeviceToken:). Успішний виклик містить об'єкт Data з токеном, який необхідно конвертувати в hex-рядок для передачі на сервер. У разі помилки система викликає application(_:didFailToRegisterForRemoteNotificationsWithError:) з описом проблеми: неправильне налаштування сертифікатів, відсутність мережі або неправильна конфігурація проекту.
Після отримання токена додаток повинен негайно передати його на свій сервер для збереження в базі даних. API-запит включає токен, ідентифікатор пристрою (для зіставлення), середовище (sandbox/production) та опціонально додаткові дані: версію ОС, модель пристрою, мову. Рекомендується повторювати передачу токена при кожному запуску додатка, щоб сервер завжди мав актуальний токен.
// Запит дозволу та реєстрація в APNS
func registerForPushNotifications() {
UNUserNotificationCenter.current()
.requestAuthorization(options: [.alert, .sound, .badge]) {
[weak self] granted, error in
guard granted else {
print("Дозвіл не отримано")
return
}
DispatchQueue.main.async {
UIApplication.shared
.registerForRemoteNotifications()
}
}
}
// Отримання Device Token від APNS
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
let tokenString = deviceToken
.map { String(format: "%02.2hhx", $0) }
.joined()
print("Device Token: \(tokenString)")
// Відправка токена на сервер
PushTokenService.shared
.sendTokenToServer(tokenString) { success in
if success {
UserDefaults.standard.set(tokenString,
forKey: "lastDeviceToken")
}
}
}
Серверна частина push-системи повинна зберігати Device Token в базі даних, асоційований з користувачем і середовищем. При надсиланні сповіщення сервер формує запит до APNS, включаючи токен в URL та JWT-токен (або сертифікат) для авторизації. Коректне управління токенами критично впливає на відсоток доставки push-сповіщень.
Таблиця токенів на сервері повинна містити як мінімум: Device Token (унікальний), ідентифікатор користувача, середовище (sandbox/production), дату останнього оновлення та статус (активний/неактивний). Рекомендується додавати індекс за токеном для швидкого пошуку при надсиланні та за користувачем для отримання списку всіх пристроїв користувача. Багато додатків дозволяють одному користувачеві мати кілька пристроїв — кожен зі своїм токеном.
Для надсилання push-сповіщення сервер повинен авторизувати запит до APNS двома способами. Certificate-based використовує SSL-сертифікат, згенерований в Apple Developer Console. Token-based використовує JWT (JSON Web Token) з ключем .p8, який діє до 30 днів без необхідності оновлення сертифіката. Токен-базована авторизація вважається більш сучасною і рекомендується Apple для нових проектів.
Запит до APNS включає HTTP/2 метод POST, URL з шляхом /3/device/{device_token}, заголовки авторизації та JSON-тіло з пейлоудом. Заголовок apns-topic обов'язково містить bundle ID додатка. apns-priority вказує пріоритет доставки (5 — негайно, 10 — з економією батареї). apns-expiration задає час у секундах від епохи, до якого APNS намагатиметься доставити сповіщення.
// Приклад відправки push на Node.js через APNS HTTP/2
const http2 = require('http2');
const client = http2.connect('https://api.push.apple.com');
const deviceToken = 'abcdef0123456789...';
const payload = JSON.stringify({
"aps": { "alert": "Hello!", "sound": "default" }
});
const req = client.request({
':method': 'POST',
':path': `/3/device/${deviceToken}`,
'apns-topic': 'com.example.app',
'apns-priority': '10',
'apns-expiration': '0',
'authorization': `bearer ${jwtToken}`
});
req.write(payload);
req.end();
req.on('response', (headers) => {
if (headers[':status'] === '200') {
console.log('Push надіслано успішно');
}
});
При надсиланні push-сповіщень на велику кількість пристроїв використовуйте пакетне надсилання з контролем швидкості. APNS рекомендує не перевищувати 1500 запитів на секунду на одне з'єднання. При перевищенні ліміту сервер Apple повертає помилку 429 Too Many Requests. Для масштабних розсилок використовуйте кілька з'єднань і розподіляйте навантаження по пристроях рівномірно.
Device Token не є постійним і може змінитися в кількох сценаріях, що вимагає від сервера механізму оновлення. Якщо сервер продовжує надсилати push на застарілий токен, APNS повертає помилку 410 Gone, вказуючи, що токен більше не дійсний для даного середовища.
Apple документує кілька сценаріїв, при яких Device Token змінюється: користувач перевстановлює додаток, відновлює пристрій з iCloud резервної копії, встановлює нову версію iOS, а також при скиданні налаштувань мережі або конфіденційності. У кожному випадку додаток при наступному запуску отримає новий токен від APNS. Сервер повинен оновити токен в базі даних, видаливши старий і зберігши новий.
Коли сервер надсилає push на застарілий токен, APNS повертає HTTP 410 із заголовком apns-unless-timestamp. Цей заголовок вказує час, після якого токен став недійсним. Сервер повинен негайно видалити або деактивувати цей токен в базі даних, щоб не надсилати на нього повторно. Ігнорування помилки 410 призводить до пустої трати ресурсів і зниження deliverability rate.
Для підтримання бази токенів в актуальному стані рекомендується запускати періодичне очищення. Скрипт очищення аналізує логи APNS за останні N днів, знаходить всі токени, на які була отримана помилка 410, і деактивує їх в базі даних. Додатково можна видаляти токени, по яких не було активності користувача більше 90 днів — це непотрібні записи, які тільки збільшують розмір бази даних.
Перед масовим надсиланням push-сповіщень (розсилка, промо-кампанія) рекомендується попередньо перевірити актуальність токенів. APNS не надає прямого API для batch-валідації токенів, тому використовується стратегія надсилання тестового push з низьким пріоритетом та аналіз помилок. Токени, що повернули помилку 410, виключаються з основної розсилки.
Розглянемо повний цикл отримання Device Token в Swift, включаючи обробку помилок та передачу на сервер. Код охоплює запит дозволу, реєстрацію в APNS, конвертацію Data в hex-рядок, обробку помилок та надсилання токена на власний сервер з повторними спробами при невдачі.
import UIKit
import UserNotifications
final class PushNotificationManager: NSObject {
static let shared = PushNotificationManager()
private let apiClient = APIClient()
private var currentToken: String?
func register() {
UNUserNotificationCenter.current()
.requestAuthorization(
options: [.alert, .badge, .sound]) {
[weak self] granted, error in
guard granted else {
Analytics.log(
"Push permission denied")
return
}
DispatchQueue.main.async {
UIApplication.shared
.registerForRemoteNotifications()
}
}
}
func handleDeviceToken(_ tokenData: Data) {
let token = tokenData
.map { String(format: "%02.2hhx", $0) }
.joined()
guard token != currentToken else { return }
currentToken = token
sendTokenToServer(token)
}
func handleRegistrationError(_ error: Error) {
Analytics.log(
"Push registration failed: \(error)")
// Повтор після затримки при мережевих помилках
if let urlError = error as? URLError,
urlError.code == .notConnectedToInternet {
DispatchQueue.main.asyncAfter(
deadline: .now() + 10) { [weak self] in
self?.register()
}
}
}
private func sendTokenToServer(_ token: String) {
let body = PushTokenRequest(
token: token,
environment: Environment.current == .debug
? "sandbox" : "production",
osVersion: UIDevice.current.systemVersion,
locale: Locale.current.identifier
)
apiClient.sendToken(body) { [weak self] result in
if case .success = result {
self?.currentToken = token
}
}
}
}
Помилки при реєстрації в APNS можуть бути викликані різними причинами. Найбільш часті — відсутність мережі, неправильна конфігурація сертифікатів в Xcode (наприклад, відключений capability Push Notifications), використання симулятора (який не підтримує push) або неправильний provisioning profile. В production важливо логувати помилки та, за можливості, повторювати реєстрацію при наступному запуску додатка.
iOS Simulator не підтримує отримання реального Device Token. Для тестування реєстрації на симуляторі використовуйте i386-архітектурні перевірки: в debug-збірці можна симулювати отримання токена або використовувати UI-тести з mock об'єктами. Реальне тестування push-сповіщень завжди виконується на фізичному пристрої, підключеному до Xcode.
Часто задавані питання
Так, Device Token може змінитися при перевстановленні додатка, відновленні пристрою з резервної копії або оновленні iOS. Сервер повинен обробляти оновлення токенів: при отриманні нового токена від відомого пристрою — замінювати старий, при помилці 410 — видаляти токен з бази.
Device Token — це 32-байтова hex-строка з 64 символів у нижньому регістрі (0–9, a–f). Приклад: «a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2». Токен передається як Data з APNS і конвертується в рядок на стороні додатка.
Sandbox-токен видається для додатків, зібраних з розробницьким provisioning profile, і працює тільки з api.sandbox.push.apple.com. Production-токен — для App Store та TestFlight, працює з api.push.apple.com. Сервер повинен розрізняти середовища і надсилати push на відповідний APNS endpoint.
Помилка 410 Gone означає, що Device Token недійсний. Сервер повинен негайно видалити цей токен з бази даних і припинити спроби надсилання на нього. Заголовок apns-unless-timestamp у відповіді вказує, з якого часу токен перестав працювати.
Перевірте виклик делегата application(_:didRegisterForRemoteNotificationsWithDeviceToken:) в AppDelegate. Якщо метод викликається — токен отримано. Використовуйте debugging-логи або OSLog для виведення токена в консоль Xcode. На фізичному пристрої перевірте, що токен надсилається на сервер через Network Link Conditioner.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також