# Register phone devices

Barua will send phone notifications only to devices your backend registered
for a person. This release stores those registrations. Sending arrives in a
following release, so nothing reaches a phone yet.

## Before you start

Upload your app's Apple key first, as in
[Prepare phone notifications](/docs/guides/notifications.md). A registration
names the bundle id and environment of that upload. Notifications don't need
to be turned on.

Your backend needs a live event key with `devices:write`. An existing key
never gains it, so create a new one with `manage.mjs action` and
`--secret-file`, using a connection that has `setup:write`:

```json
{"action":"key.create","input":{"mode":"live","label":"Device registration","capabilities":["devices:write"]}}
```

Test keys can't register devices. Keep this key on your server.

## From the app to your backend

After the person signs in, the app asks for notification permission and
receives its device token from Apple. It sends the token as hex to your own
backend, over the app's signed-in connection. The app never calls Barua.

```swift
func application(_ application: UIApplication,
                 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
  let token = deviceToken.map { String(format: "%02x", $0) }.joined()
  Task { try? await api.post("/me/device-token", body: ["token": token]) } // your backend
}
```

Apple can issue a new token, for example after the app is reinstalled, so
send the current one at every launch.

## Register the device

Your backend calls Barua with the person's `external_id`, the same one your
events use:

```sh
curl -X PUT https://barua.ai/api/integrations/v1/devices \
  -H "Authorization: Bearer $BARUA_DEVICE_KEY" -H 'Content-Type: application/json' \
  -d '{"provider":"apns","app":"com.example.app","environment":"production","token":"6f1c9a2e4b7d0835c2e9f14a7b3d6e0c58a1f2b9d4e7c03a6b8f1e2d5c9a4b70","external_id":"user_42"}'
```

`environment` is `production` for App Store and TestFlight builds and
`sandbox` for builds you run from Xcode, matching the key you uploaded. The
answer is `{"registered":true,"registered_at":"...","bound_at":"..."}`. It never
contains the token.

Registering the same token again is safe. When the same token arrives for
another person, as on a shared phone, Barua moves the device to them. A
person keeps at most 10 devices: an eleventh replaces one Apple reported
gone, or else the one registered longest ago.

Barua answers 409 `unknown_identity` until it knows the person. Send their
sign-up or first service event and wait until it shows as applied. Then
register again. 409 `notification_app_not_found` means no key was uploaded
for that bundle id and environment. On 429, wait for `Retry-After` and send
the same request again. A 503 is safe to retry with backoff, because a
repeated registration only refreshes the same device.

## Forget the device

At sign-out, send the same body with `DELETE`. Include `external_id`: Barua
then removes the device only while it still belongs to that person, so a
late sign-out can't remove the next person's registration on a shared phone.
The answer is `{"deleted":true}` or `{"deleted":false}`, and repeating it is
harmless.

Erasing a person removes their devices, and deleting an app removes the
devices registered for it. An `external_id` used again after an erasure
starts with none.

Exact rules are in the
[events reference](/skills/barua-setup/references/events.md#phone-devices).
