iOS & Android push

Mobile delivery uses your Apple/Google credentials — pushed under your app's identity, validated cryptographically at upload, sealed at rest. Native SDKs are on the roadmap; today your app obtains its token natively and registers it with one REST call.

iOS (APNs)

1 · Get a .p8 key

Apple Developer → Certificates, Identifiers & Profiles → Keys → add a key with Apple Push Notifications service enabled. Download the AuthKey_XXXXXXXXXX.p8 (downloadable once), note the Key ID and your Team ID.

2 · Upload in dashboard → Setup → Mobile channels

Team ID, Key ID, your app's Bundle ID, and the .p8 contents. Validation is immediate — a wrong or non-EC key is rejected on the spot with the reason. Use environment development for Xcode debug builds (APNs sandbox), default is production.

3 · Register the token from Swift

func application(_ app: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken t: Data) {
  let token = t.map { String(format: "%02x", $0) }.joined()
  var req = URLRequest(url: URL(string: "https://api.notibase.com/v1/devices")!)
  req.httpMethod = "POST"
  req.setValue("Bearer ck_live_...", forHTTPHeaderField: "Authorization")
  req.setValue("application/json", forHTTPHeaderField: "Content-Type")
  req.httpBody = try! JSONSerialization.data(withJSONObject: [
    "platform": "ios", "token": token,
    "locale": Locale.current.identifier,
    "timezone": TimeZone.current.identifier])
  URLSession.shared.dataTask(with: req).resume()
}

Android (FCM)

1 · Service account

Firebase console → Project settings → Service accounts → Generate new private key. That JSON file is what Notibase needs.

2 · Paste it in dashboard → Setup → Mobile channels

The whole JSON, as-is. Notibase extracts project_id, client_email, private_key, verifies it can sign, and seals it.

3 · Register the token from Kotlin

FirebaseMessaging.getInstance().token.addOnSuccessListener { token ->
  val body = JSONObject(mapOf(
    "platform" to "android", "token" to token,
    "locale" to Locale.getDefault().toLanguageTag(),
    "timezone" to TimeZone.getDefault().id)).toString()
  val req = Request.Builder()
    .url("https://api.notibase.com/v1/devices")
    .header("Authorization", "Bearer ck_live_...")
    .post(body.toRequestBody("application/json".toMediaType()))
    .build()
  OkHttpClient().newCall(req).enqueue(/* … */)
}

Sending & content

The same POST /v1/messages reaches every platform. Per-channel overrides:

"content": {
  "title": "Order shipped 📦", "body": "Arriving Thursday.",
  "apns": { "badge": 1, "sound": "default" },
  "fcm":  { "image": "https://…/banner.png" }
}

Token hygiene — automatic

When Apple answers 410 Unregistered or Google answers UNREGISTERED (app uninstalled, token rotated), Notibase expires the device immediately: your subscriber counts stay honest and dead tokens never count against you. Details in Delivery errors.