Source: https://docs.any.org/auth/identities.html # Identities The identities directory is the account-global, device-local cache of **every account identity this account has encountered** — across spaces, one-to-one chats and inbox invites. It is where you turn an id you hold (a chat message's `creator`, an object row's `author` or `modifiedBy`, a mention, a 1-1 peer) into a display name and icon. ## Endpoints Account-scoped — these routes sit outside the `/v1/spaces/:spaceId` group. | Method | Path | Purpose | | --- | --- | --- | | GET | `/v1/identities` | every known identity | | GET | `/v1/identities/:identity` | one identity; `404 identity.not_found` when never seen | | GET | `/v1/identities/subscribe` | live directory changes over SSE | ```bash curl -s http://127.0.0.1:7001/v1/identities ``` ```json { "identities": [ { "identity": "A5k…", "name": "Alice", "iconCid": "bafy…", "spaceIds": ["bafyspace1…", "bafyspace2…"] } ] } ``` | Field | Meaning | | --- | --- | | `identity` | the account id | | `name`, `description`, `iconCid` | the last resolved profile — omitted until resolved | | `spaceIds` | spaces where the identity is currently seen; pruned when you leave or offload a space | ```bash any identities list # alias: any contacts any identities get A5k… any identities subscribe ``` ## Profiles are encrypted A profile is pushed to the network encrypted with an account-derived key. That key reaches a contact only through a channel that is already encrypted — a shared space's ACL metadata, or a one-to-one invite. Until it arrives, the directory row surfaces **id-only**: `name`, `description` and `iconCid` are empty. Once the key is in, a background fetch resolves the profile and the row updates. The same applies on a freshly restored device: every contact starts id-only and fills in as keys resolve in the background. > **Why it matters.** The sync nodes store profile bytes they cannot read. A relay learning "who talks to whom" never learns who those people are; only accounts you have actually shared a space or a direct chat with can decrypt your name. The synced decryption key behind each row is never exposed over HTTP. The tech-space dataset that stores it is deliberately excluded from the generic [space-list query](https://docs.any.org/realtime/space-list.md.txt) — `GET /v1/identities` is the one read path. ## Tolerate empty names Render a fallback (a truncated id, a generated avatar) and let the subscribe stream fill the name in. Never block a UI on a resolved name, and do not look for a "fetch raw profile bytes" path — there is none; the directory *is* the resolution surface. ## Live updates `GET /v1/identities/subscribe` uses the same envelope as the members and sync-status streams: ``` event: ready data: {} event: identities data: { "added": [ { …IdentityInfo… } ], "updated": [ { …IdentityInfo… } ], "removed": [ "A5k…" ] } event: lagged data: { "total": 3 } event: closed data: { "reason": "server_shutdown" } ``` One `identities` frame per change batch; any of `added` / `updated` / `removed` may be empty or absent. A contact whose key arrives after the first sighting appears first in `added` with an empty name, then again in `updated` once resolved. On `lagged`, re-`GET` the list to resynchronise. ## No rights here The directory carries **no permission field** by design. Roles are per-space and live on the [members list](https://docs.any.org/collaboration/members-and-roles.md.txt): ``` GET /v1/spaces/:id/members # roster + roles for ONE space GET /v1/identities # global id → profile, across all spaces ``` To show "Alice is an admin of space X", read space X's members. To show her role in every shared space, iterate her `spaceIds` and read each members list — there is no cross-space role rollup. | Question | Surface | | --- | --- | | Who is in this space, with what rights? | `GET /v1/spaces/:id/members` | | What does this account id look like? | `GET /v1/identities/:identity` | | Keep an avatar cache fresh | `GET /v1/identities/subscribe` |