> For the complete documentation index, see [llms.txt](https://codemash.gitbook.io/codemash/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://codemash.gitbook.io/codemash/cloud/push/integrations/providers/apns.md).

# Apple Push Notification service

Connect Apple Push Notification service (APNs) to Push, for iPhone, iPad, Apple Watch, Apple TV and Mac apps.

APNs delivers notifications to your apps on iOS, iPadOS, watchOS, tvOS and macOS. Norbix signs each request to Apple with a **.p8 auth key** from your Apple developer account.

{% hint style="warning" %}
On our test stack the integration saves, but **Test integration** fails with *The input is not a valid Base-64 string …* for a key pasted as the form asks (with the `-----BEGIN PRIVATE KEY-----` lines). Sending through APNs could not be confirmed; the question is open in the docs program. Use [Fake Push (Test Me)](/codemash/cloud/push/integrations/providers/fake.md) to try your flows meanwhile.
{% endhint %}

## Get your credentials

You need a paid membership of the [Apple Developer Program](https://developer.apple.com/programs/enroll/) (individual or organization); sign in at [developer.apple.com/account](https://developer.apple.com/account).

1. **Team Id** — **Account → Membership details**: the 10-character **Team ID**, e.g. `3VVDAGYR37` ([Apple: locate your team ID](https://developer.apple.com/help/account/manage-your-team/locate-your-team-id)).
2. **App Bundle Identifier** — [Certificates, Identifiers & Profiles](https://developer.apple.com/account/resources) → **Identifiers**: the **Identifier** of your app, a reverse-domain string such as `com.acme.shop`. In Xcode it is on the app target's **General** tab (**Bundle Identifier**). It must match the app exactly, including case.
3. **Key Id** and **.p8 key** — **Certificates, Identifiers & Profiles → Keys** → the add button (**+**) → enter a **Key Name**, tick **Apple Push Notifications service (APNs)** → **Continue** → **Register** → **Download**. The file is `AuthKey_<Key ID>.p8`; the **Key ID** (e.g. `CSWUWZ6VUU`) is shown under the key name.

Apple lets you download a `.p8` key **once**. If you lose it, revoke it and create a new key. One key serves every app of the team; you still create one integration per bundle id.

## Connect it in Cloud

**Where:** Push → Integrations → **Add New Integration** → Apple Push Notification service → **Connect** · `/projects/<project>/push/integrations/new/apns`

| Field                                                          | Required | What it does                                                                                                                                  | Example                             |
| -------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
| Team Id                                                        | yes      | Your Apple developer team.                                                                                                                    | `3VVDAGYR37`                        |
| App Bundle Identifier                                          | yes      | The app that receives the notifications.                                                                                                      | `com.acme.shop`                     |
| Key Id                                                         | yes      | The id of the auth key.                                                                                                                       | `CSWUWZ6VUU`                        |
| Private key (.p8)                                              | yes      | The whole text of the `.p8` file, from `-----BEGIN PRIVATE KEY-----` to `-----END PRIVATE KEY-----`. Encrypted on save and never shown again. | contents of `AuthKey_CSWUWZ6VUU.p8` |
| Production environment → **Use Apple production APNs gateway** | no       | On = Apple's production gateway (App Store and TestFlight builds). Off = the sandbox gateway, for builds signed with a development profile.   | off                                 |
| Integration Name                                               | yes      | The name in your integrations list.                                                                                                           | `Acme iOS app (APNs)`               |

<figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-7a1429aaf11b2f36a83122d7c38be2f4485670b2%2Fapns-form-1.png?alt=media" alt="New Apple APNs Integration form filled: Team Id 3VVDAGYR37, App Bundle Identifier com.acme.shop, Key Id CSWUWZ6VUU, the end of a made-up .p8 key, the production switch off, Integration Name Acme iOS app (APNs), and Cancel and Save"><figcaption><p>The filled form (the key is made up for the docs).</p></figcaption></figure>

Press **Save**. The page turns into **Editing Apple APNs integration** with the integration id (`int_…`) and the badges **ENABLED**, **NOT TESTED**, **NOT CONFIRMED**.

<figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-40a18db35dad9e0fec281433274844d0625667d5%2Fapns-saved-2.png?alt=media" alt="Editing Apple APNs integration int_iuH9gfpLnR1VPxGgDePOd with the badges ENABLED, NOT TESTED, NOT CONFIRMED; Team Id and App Bundle Identifier filled, Key Id and the private key empty with the Info box about secrets"><figcaption><p>After save.</p></figcaption></figure>

On the edit page **Key Id** and **Private key (.p8)** are empty: type both again when you change anything and press **Save**.

## Test and set as default

Press **Test integration** at the bottom of the page — see [Test an integration](/codemash/cloud/push/integrations/test.md). A token from a development build works only with the sandbox gateway and a production token only with the production gateway; a correct key with the wrong switch looks exactly like a broken key. Then choose **Actions → Set as default** if campaigns should pick it — see [Set an integration as default](/codemash/cloud/push/integrations/set-default.md).

## Common errors

| Message                                                                       | Cause                                                                             | Fix                                               |
| ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------- |
| Could not send push via Apple Apn … The input is not a valid Base-64 string … | Seen on every test on our stack with a PEM key.                                   | Open question; use the Fake provider meanwhile.   |
| Required                                                                      | An empty field — on edit also **Key Id** and the key.                             | Fill every field, type the secrets again.         |
| BadDeviceToken (from Apple)                                                   | The token is from the other gateway (sandbox vs production), or not an iOS token. | Match the production switch to the build.         |
| InvalidProviderToken (from Apple)                                             | Wrong Team Id, Key Id or key.                                                     | Copy them again from the Apple developer account. |
