{"id":13461802,"url":"https://github.com/swift-server-community/APNSwift","last_synced_at":"2025-03-24T22:35:05.665Z","repository":{"id":37089792,"uuid":"169297566","full_name":"swift-server-community/APNSwift","owner":"swift-server-community","description":"📱HTTP/2 Apple Push Notification Service built with swift - send push notifications to iOS, iPadOS, tvOS, macOS, watchOS, visionOS, and Safari!","archived":false,"fork":false,"pushed_at":"2024-07-22T16:07:28.000Z","size":479,"stargazers_count":677,"open_issues_count":6,"forks_count":102,"subscribers_count":18,"default_branch":"main","last_synced_at":"2024-08-13T00:22:15.327Z","etag":null,"topics":["apns","apns-http2","apnswift","apple","apple-push-notifications","safari-push-notifications","sswg","swift","swift-nio","swift-nio-http2"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/swift-server-community.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":"SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["kylebrowning"]}},"created_at":"2019-02-05T19:17:33.000Z","updated_at":"2024-08-13T00:22:24.653Z","dependencies_parsed_at":"2023-10-12T00:28:31.053Z","dependency_job_id":"319336aa-c2b3-4d41-a7a1-042bb438a669","html_url":"https://github.com/swift-server-community/APNSwift","commit_stats":{"total_commits":224,"total_committers":32,"mean_commits":7.0,"dds":0.25,"last_synced_commit":"c84a4c76cd8f14981db7b6d926ec58bd5b6607e5"},"previous_names":["kylebrowning/apnswift"],"tags_count":43,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swift-server-community%2FAPNSwift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swift-server-community%2FAPNSwift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swift-server-community%2FAPNSwift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swift-server-community%2FAPNSwift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/swift-server-community","download_url":"https://codeload.github.com/swift-server-community/APNSwift/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245366204,"owners_count":20603438,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apns","apns-http2","apnswift","apple","apple-push-notifications","safari-push-notifications","sswg","swift","swift-nio","swift-nio-http2"],"created_at":"2024-07-31T11:00:58.024Z","updated_at":"2025-03-24T22:35:00.648Z","avatar_url":"https://github.com/swift-server-community.png","language":"Swift","funding_links":["https://github.com/sponsors/kylebrowning"],"categories":["Swift"],"sub_categories":[],"readme":"[![sswg:graduated|94x20](https://img.shields.io/badge/sswg-graduated-green.svg)]([https://github.com/swift-server/sswg/blob/master/process/incubation.md#sandbox-level](https://www.swift.org/sswg/incubation-process.html#graduation-requirements))\n[![Build](https://github.com/kylebrowning/APNSwift/workflows/test/badge.svg)](https://github.com/kylebrowning/APNSwift/actions)\n[![Documentation](https://img.shields.io/badge/documentation-blueviolet.svg)](https://swiftpackageindex.com/swift-server-community/APNSwift/documentation)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fswift-server-community%2FAPNSwift%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/swift-server-community/APNSwift)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fswift-server-community%2FAPNSwift%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/swift-server-community/APNSwift)\n\u003ch1\u003e APNSwift\u003c/h1\u003e\n\nA non-blocking Swift module for sending remote Apple Push Notification requests to [APNS](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server) built on AsyncHttpClient.\n\n- [Installation](#installation)\n- [Getting Started](#getting-started)\n- [Sending a simple notification](#sending-a-simple-notification)\n- [Sending Live Activity Update](#sending-live-activity-update--end)\n- [Authentication](#authentication)\n- [Logging](#logging)\n    - [**Background Activity Logger**](#background-activity-logger)\n    - [**Notification Send Logger**](#notification-send-logger)\n- [Server Example](#server-example)\n- [iOS Examples](#ios-examples)\n- [Original pitch and discussion on API](#original-pitch-and-discussion-on-api)\n\n## Installation\n\nTo install `APNSwift`, just add the package as a dependency in your [**Package.swift**](https://github.com/apple/swift-package-manager/blob/master/Documentation/PackageDescriptionV4.md#dependencies).\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/swift-server-community/APNSwift.git\", from: \"6.0.0\"),\n]\n```\n\n## Getting Started\nAPNSwift aims to provide semantically correct structures to sending push notifications. You first need to setup a [`APNSClient`](https://github.com/swift-server-community/APNSwift/blob/main/Sources/APNS/APNSClient.swift). To do that youll need to know your authentication method \n\n```swift\nlet client = APNSClient(\n    configuration: .init(\n        authenticationMethod: .jwt(\n            privateKey: try .init(pemRepresentation: privateKey),\n            keyIdentifier: keyIdentifier,\n            teamIdentifier: teamIdentifier\n        ),\n        environment: .development\n    ),\n    eventLoopGroupProvider: .createNew,\n    responseDecoder: JSONDecoder(),\n    requestEncoder: JSONEncoder()\n)\n\n// Shutdown the client when done\ntry await client.shutdown()\n```\n\n## Sending a simple notification\nAll notifications require a payload, but that payload can be empty. Payload just needs to conform to `Encodable`\n\n```swift\nstruct Payload: Codable {}\n\ntry await client.sendAlertNotification(\n    .init(\n        alert: .init(\n            title: .raw(\"Simple Alert\"),\n            subtitle: .raw(\"Subtitle\"),\n            body: .raw(\"Body\"),\n            launchImage: nil\n        ),\n        expiration: .immediately,\n        priority: .immediately,\n        topic: \"com.app.bundle\",\n        payload: Payload()\n    ),\n    deviceToken: \"device-token\"\n)\n```\n\n## Sending Live Activity Update / End\nIt requires sending `ContentState` matching with the live activity configuration to successfully update activity state. `ContentState` needs to conform to `Encodable` and `Sendable`.\n\n```swift\ntry await client.sendLiveActivityNotification(\n    .init(\n          expiration: .immediately,\n          priority: .immediately,\n          appID: \"com.app.bundle\",\n          contentState: ContentState,\n          event: .update,\n          timestamp: Int(Date().timeIntervalSince1970)\n    ),\n    deviceToken: activityPushToken\n)\n```\n\n```swift\ntry await client.sendLiveActivityNotification(\n    .init(\n          expiration: .immediately,\n          priority: .immediately,\n          appID: \"com.app.bundle\",\n          contentState: ContentState,\n          event: .end,\n          timestamp: Int(Date().timeIntervalSince1970),\n          dismissalDate: .immediately // Optional to alter default behaviour\n    ),\n    deviceToken: activityPushToken\n)\n```\n## Authentication\n`APNSwift` provides two authentication methods. `jwt`, and `TLS`. \n\n**`jwt` is preferred and recommend by Apple** \nThese can be configured when created your `APNSClientConfiguration`\n\n*Notes: `jwt` requires an encrypted version of your .p8 file from Apple which comes in a `pem` format. If you're having trouble with your key being invalid please confirm it is a PEM file*\n```\nopenssl pkcs8 -nocrypt -in /path/to/my/key.p8 -out ~/Downloads/key.pem\n```\n\n## Logging\nBy default APNSwift has a no-op logger which will not log anything. However if you pass a logger in, you will see logs.\n\nThere are currently two kinds of loggers.\n#### **Background Activity Logger**\nThis logger can be passed into the `APNSClient` and will log background things like connection pooling, auth token refreshes, etc. \n\n#### **Notification Send Logger**\nThis logger can be passed into any of the `send:` methods and will log everything related to a single send request. \n\n## Server Example\nTake a look at [Program.swift](https://github.com/swift-server-community/APNSwift/blob/main/Sources/APNSExample/Program.swift)\n\n## iOS Examples\n\nFor an iOS example, open the example project within this repo. \n\nOnce inside configure your App Bundle ID and assign your development team. Build and run the ExampleApp to iOS Simulator, grab your device token, and plug it in to server example above. Background the app and run Program.swift\n\n## Original pitch and discussion on API\n\n* Pitch discussion: [Swift Server Forums](https://forums.swift.org/t/apple-push-notification-service-implementation-pitch/20193)\n* Proposal: [SSWG-0006](https://forums.swift.org/t/feedback-nioapns-nio-based-apple-push-notification-service/24393)\n* 5.0 breaking changings: [Swift Server Forums]([Blog post here on breaking changing](https://forums.swift.org/t/apnswift-5-0-0-beta-release/60075/3))\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswift-server-community%2FAPNSwift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswift-server-community%2FAPNSwift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswift-server-community%2FAPNSwift/lists"}