MobPush.APNS (mob_push v0.2.2)

Copy Markdown View Source

APNs HTTP/2 adapter for MobPush.

Sends push notifications to iOS devices via Apple Push Notification service using token-based auth (p8 key) over HTTP/2. Called internally by MobPush.send/3 — you can also call it directly for advanced use cases.

Configuration

config :mob_push, :apns,
  key_id:    "XXXXXXXXXX",           # 10-char Key ID from the Apple Developer portal Keys page
  team_id:   "XXXXXXXXXX",           # 10-char Team ID from Membership Details
  bundle_id: "com.example.myapp",    # must match the app's bundle ID exactly
  key_file:  "/path/to/AuthKey_XXXXXXXXXX.p8",  # path to the .p8 file on disk
  # OR: key_pem: "-----BEGIN PRIVATE KEY-----\n..."  # PEM string (from secret manager, etc.)
  env:       :sandbox                # :sandbox | :production (default: :sandbox)

Sandbox vs production: These are completely separate APNs endpoints with separate device token namespaces. A sandbox token sent to the production endpoint returns "BadDeviceToken". Use :sandbox for Xcode/TestFlight dev builds and :production for App Store / TestFlight production builds.

Payload options

KeyTypeDescription
:titlestringBold title line (required)
:bodystringMain text (required)
:subtitlestringSecond line under the title, shown in lighter weight
:badgeintegerBadge count on the app icon; pass 0 to clear
:soundstring"default" for system sound; or a filename (no extension) bundled in the app. Files must be .aiff, .wav, or .caf and under 30 seconds.
:content_availablebooleanSilent push — wakes the app in the background without showing any alert. The app has ~30 seconds of background time.
:datamapArbitrary key-value pairs merged into the APNs root payload. Keys are stringified; values are passed through as-is (can be nested).

Authentication

Uses ES256 JWT tokens signed with the .p8 key. Tokens are valid for 1 hour; MobPush.TokenCache refreshes them 5 minutes early. On a 403 response, the token is evicted and a fresh one is fetched on the next call.

Usage

MobPush.APNS.send("device_token_hex", %{
  title:    "New message",
  subtitle: "From Alice",
  body:     "Hey, are you free tonight?",
  badge:    3,
  sound:    "default",
  data:     %{screen: "chat", thread_id: "42"}
})

Summary

Functions

Decides the apns-push-type header value for a payload.

Send a push notification to an iOS device token.

Functions

push_type_for(payload)

@spec push_type_for(map()) :: String.t()

Decides the apns-push-type header value for a payload.

Apple enforces this header (since iOS 13). The two shapes users hit:

  • "background" — silent push. Payload has content_available: true AND NO user-visible field (no :title, :body, :subtitle, :sound, or :badge). Sending a truly silent push with "alert" returns HTTP 400 BadPushType from Apple. See MOB-84.
  • "alert" — the default for everything else (any payload with an alert, badge, or sound). This includes hybrid alerts that ALSO set content_available — Apple treats those as alert-type per the docs.

Mob.Push doesn't use the other push types (voip, location, liveactivity, etc.) yet; extend this function if new use cases need them.

send(device_token, payload)

@spec send(device_token :: String.t(), payload :: map()) :: :ok | {:error, term()}

Send a push notification to an iOS device token.