Skip to content

Push Notifications (A1) ​

The Chatter API sends push notifications through Apple Push Notification service (APNs) using your APNs key. You configure it once with the developer endpoints, and the app registers each device token.

When pushes are sent ​

TriggerSent toCondition
New messageEvery other member's devicesDevice has no open WebSocket, and the conversation is not muted
Friend request receivedRecipient's devicesDevice has no open WebSocket
Friend request acceptedSender's devicesDevice has no open WebSocket

Devices with an open socket receive the WebSocket event instead, so the user never gets both.

Setup ​

1. Create an APNs key (once) ​

  1. In Apple Developer → Keys, create a key with Apple Push Notifications service (APNs) enabled.
  2. Download the .p8 file. Note the Key ID and your Team ID.
  3. In Xcode, add the Push Notifications capability to your app target.

2. Register the key with your workspace (once, from your machine) ​

$API and $CK are set as in the Quickstart. Set CS to your clientSecret.

bash
export CS=cs_your_client_secret_here

curl -X PUT $API/developer/apns \
  -H "X-Client-Key: $CK" -H "X-Client-Secret: $CS" \
  -H 'Content-Type: application/json' \
  -d "$(jq -n --arg key "$(cat AuthKey_ABC123DEFG.p8)" \
        '{teamId:"TEAM123456", keyId:"ABC123DEFG", bundleId:"com.yourname.chatter", privateKey:$key}')"

The API uses the right APNs environment for each device token based on the environment the app reports (next step). TestFlight and App Store builds use production. Debug builds from Xcode use sandbox.

Check the configuration:

bash
curl $API/developer/apns -H "X-Client-Key: $CK" -H "X-Client-Secret: $CS"
# {"configured":true,"teamId":"TEAM123456","keyId":"ABC123DEFG","bundleId":"com.yourname.chatter"}

3. Register the device token (in the app) ​

After the user signs in and grants permission, call registerForRemoteNotifications(). Send the token (hex string) to the API:

PUT /me/devices/current/push-token ​

json
{ "token": "a1b2c3…", "environment": "production" }

environment: sandbox for debug builds, production for TestFlight and App Store. 204. Call it on every launch — tokens can change.

DELETE /me/devices/current/push-token ​

Stops pushes to this device. POST /auth/logout does this automatically.

4. Send a test push ​

bash
curl -X POST $API/developer/test-push \
  -H "X-Client-Key: $CK" -H "X-Client-Secret: $CS" \
  -H 'Content-Type: application/json' -d '{"userId":"01JB…"}'
# {"sent":1,"failed":0,"results":[{"deviceId":"01JB8ZD…","status":"sent"}]}

APNs error reasons (for example BadDeviceToken, BadEnvironmentKeyInToken, TopicDisallowed) are returned in results to help you debug.

Payloads ​

New message ​

json
{
  "aps": {
    "alert": { "title": "Ana Souza", "body": "See you at 8?" },
    "sound": "default",
    "badge": 3,
    "thread-id": "01JE…",
    "mutable-content": 1
  },
  "chatter": {
    "type": "message.new",
    "conversationId": "01JE…",
    "messageId": "01JF…",
    "seq": 42,
    "senderId": "01JB…"
  }
}
  • badge: total unread messages for the user across all non-muted conversations.
  • thread-id: groups notifications per conversation.
  • For groups, title is "<sender> @ <group title>".
  • For media, body is "📷 Photo", "🎤 Voice message", "🎥 Video", or "📄 Document".

Friend request ​

json
{
  "aps": { "alert": { "title": "New friend request", "body": "Ben Tan (@ben_tan) wants to be your friend" }, "sound": "default" },
  "chatter": { "type": "friend_request.received", "requestId": "01JD…", "fromUserId": "01JC…" }
}

Friend request accepted ​

json
{
  "aps": { "alert": { "title": "Ben Tan", "body": "accepted your friend request" }, "sound": "default" },
  "chatter": { "type": "friend_request.accepted", "requestId": "01JD…", "friendUserId": "01JC…" }
}

Handling in the app ​

  • Tap: read chatter.type and navigate — message.new → the conversation; friend_request.* → the requests screen or the friend.
  • Foreground: you usually receive the WebSocket event first. Suppress the banner for the conversation that is on screen.
  • Badge: when the user reads messages, update the app icon badge locally (UNUserNotificationCenter.setBadgeCount).
  • Delivered receipts: a push does not mean the app received the message. Send receipt.delivered only after the message is stored locally (after the next sync).

Questions? Reply to your invitation email.