Norq

Apple Push Notifications (APNs)

APNs (Apple Push Notification service) is a built-in Norq push provider for iOS direct delivery. It builds requests for POST https://api.push.apple.com/3/device/{token} (production) or POST https://api.sandbox.push.apple.com/3/device/{token} (sandbox).

Configuration

providers:
  apns:
    config:
      keyId: AB1234CDEF                       # 10-char Key ID
      teamId: TEAM123ABC                      # 10-char Team ID
      bundleId: com.example.MyApp             # iOS bundle identifier
      keyPath: ./secrets/AuthKey_AB1234CDEF.p8
      # OR inline / env var:
      # keyPem: ${APNS_KEY_PEM}
 
      # Optional — defaults to sandbox
      production: true
routing:
  push: apns
  # OR push.ios specifically

keyId, teamId, bundleId are required, plus exactly one of keyPath (file path) or keyPem (inline / env var). production defaults to false (sandbox).

Environment-variable fallback

If providers.apns is not declared, Norq registers APNs when these env vars are set:

Var Required
NORQ_APNS_KEY_ID yes
NORQ_APNS_TEAM_ID yes
NORQ_APNS_BUNDLE_ID yes
NORQ_APNS_KEY_PATH one of these two
NORQ_APNS_KEY_PEM one of these two
NORQ_APNS_PRODUCTION optional (default false)

Per-token environment override

Push tokens may carry an environment field ("sandbox" or "production") on each recipient — the per-token value overrides the provider-level production flag for that single message. Useful for clients that ship TestFlight builds (sandbox) and App Store builds (production) in parallel and store both flavours of token. Any value other than "sandbox" or "production" errors with push/invalid-environment.

Capabilities

  • Channels: push (ios only — APNs has no Android or web concept).
  • Batching: none. APNs is one HTTP/2 stream per token.
  • apns-topic header: auto-set from the configured bundleId.

CLI cannot deliver

The norq CLI binary cannot send via APNs — Apple’s gateway requires HTTP/2 (the Norq CLI is HTTP/1.1 only via ureq) and the ES256 JWT signing flow is not bundled. Calling norq send while routed to APNs short-circuits with provider/cli-http2-required. SDKs (Node, Python, Go, Java, Ruby) use HTTP/2-capable runtime clients and sign tokens in-process.

Request shape

  • Body: application/json. APS payload:

    {
      "aps": {
        "alert": { "title": "...", "body": "..." },
        "sound": "default",
        "badge": 1,
        "interruption-level": "active"
      }
    }
  • Auth: signed ES256 JWT in the Authorization: Bearer <jwt> header. Norq emits Auth::AppleJwt { key_id, team_id, p8_pem }; the SDK signs with the p8 key per request (cached for ≤1h per Apple’s spec).

  • Required headers: apns-topic: <bundleId>. Per-message headers like apns-priority, apns-push-type, apns-collapse-id, apns-expiration flow through from the push template frontmatter when set.

  • Endpoint: POST https://api.push.apple.com/3/device/{token} (production) or https://api.sandbox.push.apple.com/3/device/{token} (sandbox).

  • Success: 200 (no body). Norq does not extract a message ID from the response — the apns-id header exists in the APNs response but ResponseHints.message_id_header is not set for this provider. The apns-id header IS used as a deduplication key when supplied in the request via idempotency_key (see the Idempotency table in the Providers overview).

  • Retry: defaults — 429 + 5xx (500, 502, 503, 504), 2 retries, 500ms backoff.