With XMTP, a user can have one or more inboxes they use to access their messages. An inbox ID is a stable identifier for a user’s messaging identity and is used as the destination for messages in direct message and group conversations. It is derived from the public key material in their key package.
An inbox can have multiple identities associated with it. An identity has a kind, such as EOA or SCW, and a string, which in the case of an EOA or SCW, is an Ethereum address.
All messages associated with these identities flow through the one inbox ID and are accessible in any XMTP app.
The first time someone uses your app with an identity they’ve never used with any app built with XMTP, your app creates an inbox ID and installation associated with the identity. To do this, you create a client for their identity.
The client creates an inbox ID and installation ID associated with the identity. By default, this identity is designated as the recovery identity. A recovery identity will always have the same inbox ID and cannot be reassigned to a different inbox ID.
When you make subsequent calls to create a client for the same identity and a local database is not present, the client uses the same inbox ID, but creates a new installation ID.
An inbox ID can have up to 10 app installations before it needs to revoke installations.
You can enable a user to add multiple identities to their inbox. Added identities use the same inbox ID and the installation ID of the installation used to add the identity.
You can enable a user to remove an identity from their inbox. You cannot remove the recovery identity.
An inbox ID is limited to 256 inbox updates. Inbox updates include actions like:
Add a wallet
Remove a wallet
Add an installation
Revoke an installation
The backend enforces the limit only when it receives the update. The SDK does not reject it in advance. If the backend rejects an update because the inbox log is full, rotate the inbox ID to continue. Rotation permanently removes access to the old inbox’s conversations.
Why this limit exists: Every client that interacts with the inbox must fetch and validate its identity updates. In a group, the work increases for every member with a long update history.
XMTP enforces a 10-installation limit per inbox. When an inbox reaches 10 active installations, the user must revoke at least one installation before adding a new one. This limit keeps group sizes manageable and protects against accidental exhaustion of the inbox update limit.
Important
The only way to avoid consuming installation updates is to ensure your XMTP database is persisted and reloaded between app sessions and deployments. When you reuse an existing database, you maintain the same installation instead of creating a new one each time.
Installations accumulate per backend. Deployments that use different backends have separate inboxes and separate counts.
Database files follow the pattern xmtp-{env}-{inbox-id}.db3. env is only a file-name label. Changing it selects a different database and creates another installation.
Show a user the installation ID, last activity time, app version, and device data that your app stores. Revoking an installation removes its future access. It does not delete its local copy of earlier messages.
Task
Browser, Node
Kotlin, Swift
Read inbox state
client.inboxState()
client.inboxState()
Read several inbox states
Client.fetchInboxStates(ids, backend)
Client.inboxStatesForInboxIds(ids, api)
Revoke selected installations
client.revokeInstallations(ids)
client.revokeInstallations(ids)
Revoke all other installations
client.revokeAllOtherInstallations()
client.revokeAllOtherInstallations()
Static state lookup and revocation can run without a logged-in client. Browser and Node take a reusable backend made with createBackend. On mobile, pass ClientOptions.Api(backendUrl: …).
If the user cannot open any active installation, build the required signature request from the inbox state, ask the recovery identity to sign it, and submit it through the static revoke call.
Adding an identity that already belongs to another inbox silently removes it from that inbox. The user loses access through that identity to the former inbox.
Browser and Node call unsafe_addAccount(signer, true). Kotlin and Swift call addAccount(identity). Both perform the same irreversible reassignment when the identity already belongs to another inbox.
When an inbox has multiple associated identities, the identities array is ordered by the client_timestamp_ns field, which sorts identities based on when they were added to the inbox, placing the earliest added identity first.
For UI display purposes, use the only identity when there is one. Otherwise, use the first non-recovery identity in the ordered array.
If the user removes an identity from the inbox, the identity no longer has access to the inbox it was removed from.
The identity can no longer be added to or used to access conversations in that inbox. If someone sends a message to the identity, the message is not associated with the original inbox. If the user logs in to a new installation with the identity, this will create a new inbox ID.
The recovery identity and its signer can be used to sign transactions that remove identities and revoke installations. An added identity cannot remove the recovery identity because it does not control the recovery signer.
The identity accesses that inbox ID and does not create a new inbox ID. If it is reassigned to a different inbox, it can no longer open the former inbox.