# Personal applet backend API

An instance is one applet on one device. Currently `applet=dog` is supported. Account aliases organize URLs, never authorization. Data and viewer grants remain scoped to the signed-in owner and the selected device/app instance. Device-only sends no applet data or remote AI calls. Gallery retention is seven days or newest 100 images (max 100 KB each, 640 px). Metrics are observed estimates and retained daily for seven days. No old local photos/history are backfilled.

## Control-agent setup (on the device)

Ask whether the user wants a backend portal for this applet on this device. If yes, ask for the portal email, desired alias, and whether to share photos; never guess these. Use the discovered owner API (requires its grant, an Idempotency-Key and approval for the exact action):

`POST /v1/owner/configure`

`{"action":"dog.configure","options":{"personal_backend":true,"backend_email":"owner@gmail.com","user_alias":"my-alias","photo_sharing":true}}`

Return the resulting `link_url` to the user. The device link code can be claimed only by that verified email; the browser still requires the user's explicit link action. The selected alias is saved after linking. An existing account or global remote-view setting never silently enables this applet backend. `personal_backend:false` stops uploads and remote AI, cancels active model requests, revokes viewers, and requests server deletion. Local history stays. Offline deletion is reported as pending until confirmed. `GET /v1/applets/dog-monitor` exposes consent, pending deletion, portal identity, state and metrics. Start/stop/camera/model/history owner actions use the same implementation as native controls. No permanent agent authority is granted by one approval.

## Account routing and alias API

`GET /api/account/profile` reads the authenticated account's email and alias. `POST /api/account/profile {"alias":"my-alias"}` creates or changes its address. A verified HttpOnly email session or legacy Google bearer session is required; POST requires Origin https://bridgit.cc. Aliases are unique 3–30 lowercase letters/numbers/hyphens, start with a letter, and cannot use reserved site routes. Alias changes do not change any grants. Public aliases contain no profile data themselves. Private pages check the signed-in account, including when an alias exists but belongs to someone else.

Routes: `/my-alias` overview, `/my-alias/myapps` applets, `/my-alias/devices` linked devices. Legacy `/myapps` remains an entrance and sends a signed-in account to its chosen alias.

## Private web backend

Base: https://bridgit-feedback.bridgit-app.workers.dev. All paths below are under `/v1/watch`. Use the existing verified Google session bearer or verified email session. Browser email sessions use the same-origin `/api/watch/v1/watch/...` proxy; raw email session tokens are never returned to JavaScript. Every read checks authorization, including direct images. Responses are private/no-store.

| Method and route | Purpose |
| --- | --- |
| GET `/applets` | Owner instances and accepted viewer instances, with role and device name |
| GET `/applet?phone=<install>&applet=dog&day=YYYY-MM-DD` | Selected device day's metrics, separate latest live state, timezone and retention policy; omitted day selects Today in the device timezone |
| GET `/applet/gallery?phone=<install>&applet=dog&day=YYYY-MM-DD&before=<capture-ms>` | Newest-first image metadata; 25 per page; `next` cursor for older images |
| GET `/applet/image?phone=<install>&applet=dog&id=<id>` | Private JPEG, reauthorized on every request, never a public media URL |
| GET `/applet/shares?phone=<install>&applet=dog` | Owner-only pending/accepted viewer list |
| POST `/applet/shares?phone=<install>&applet=dog` `{"email":"viewer@gmail.com"}` | Owner-only email invitation, seven-day expiry, at most ten/hour and 20 viewers/pending invites per instance; repeat resends pending only |
| DELETE `/applet/shares?phone=<install>&applet=dog` `{"id":"<share-id>"}` | Owner-only immediate revocation, including pending tokens |
| GET `/applet/invite?token=<token>` | Matching verified recipient previews the exact applet/device; no access granted yet |
| POST `/applet/invite` `{"token":"<token>"}` | Matching verified recipient explicitly accepts a single-use invitation |

Viewer access covers images and metrics for that instance only, not generic activity, controls, other apps/devices, deletion, or re-sharing. Tokens are stored as hashes. Wrong/expired/revoked accounts and guessed object IDs fail closed. Revocation cannot erase copies a viewer already saved.

## Device-to-server operations

The install signs these requests with its existing Keystore identity. Browser or agent credentials cannot impersonate an install.

- POST `/v1/watch/link-code` accepts `phone_name`, optional expected `email` and `user_alias`. The code expires after ten minutes; wrong verified email does not consume it.
- POST `/v1/watch/applets/backend {"applet":"dog","enabled":true,"since":<consent-ms>}` enables only that instance after verified linking. False deletes that instance's server images, metric snapshots and shares. Old remote-view consent is insufficient.
- POST `/v1/watch/dog` accepts the bounded sanitized summary, timezone, optional small JPEG, capture timestamp and matching reading/camera metadata. The client gates before serialization/queueing. The server rejects missing consent and stale photos, enforces capture interval and retention, and guards writes against a stale consent generation.
