XIP-42: Universal 'allow' and 'block' preferences


XIP-42 establishes ‘allow’ and ‘block’ permission preferences, enabling users to explicitly specify which contacts should be able to reach them and which should be blocked across all inbox apps. By respecting these preferences, XMTP inbox apps not only shield users from spam but also give them greater control over their contacts.

Special thanks to @polmaire for initiating the discussion that inspired this XIP.


The ability to ‘allow’ or ‘block’ contacts is fundamental for safeguarding users’ inboxes in messaging. ‘Allow’ promotes a conversation from a ‘request’ or ‘invitations’ UI component to a ‘primary inbox’ component, while ‘Block’ gives users the vital ability to remove spam and other unwanted content from their inbox.

However, because XMTP hasn’t yet standardized a method for communicating these actions across the network, changing preferences in one app does not affect other inboxes. This results in inbox apps failing to remove unwanted conversations and properly display desired communications.


In code we use consent to abbreviate “contact permission preferences”, and denied as the inverse of allowed.

  • New Message Topic: userpreferences-${identifier} for encrypted ConsentList objects (type: 'allowed' | 'denied', addresses: [string]).
  • ConsentState Type: Introduce ConsentState = 'allowed' | 'denied' | 'unknown'.
  • Conversation Field: Add consentState to indicate the consent state of a conversation.
  • APIs: Introduce APIs for retrieving and managing permission preference lists and states.


This approach will enable apps to accurately reflect users’ contact permission preferences by default, thereby shielding them from spam and granting them more ownership and control over their communications.

Backward Compatibility

Apps must adhere to the logic described below to keep the contact permission preferences on the network synchronized with local app’s user preferences, and vice versa.

Update a contact permission preference in the ConsentList on the network in the following scenarios only:

  • A user explicitly denies a contact. For example, the user blocks, unsubscribes from, or otherwise disables messages for the contact. The app should update the corresponding preference in the network to denied.
  • A user explicitly allows a contact. For example, the user allows, subscribes to, or otherwise enables messages for the contact. The app should update the corresponding preference in the network to allowed.
  • An existing conversation has an unknown contact permission preference, but a legacy permission in the local database exists. The app should update the corresponding preference in the network to match the legacy local preference.
  • An existing conversation has an unknown contact permission preference, but has an existing response from the user. The app should update the corresponding preference in the network to allowed.

Test Cases

Test cases will validate the functionality of sending messages using the new message topic and the handling and interpretation of all three permission preferences.

Reference Implementation

The reference implementation in the XMTP reference client demonstrates the integration of contact permission preferences, along with usable code snippets and UI components for allowing and blocking contacts.

Security Considerations

The identifier in the topic is derived from the private key using HKDF and SHA256 to ensure that it cannot be linked back to the user.

Message Envelope Encryption

  1. Generates a new key via HKDF from the user’s identity key.
  2. Encrypts the message via AES-256-GCM using the derived encryption key and the user’s public key as associated data. Then converts it to a PrivatePreferencesPayload protobuf containing the ciphertext, nonce, and salt.

Message Envelope Decryption

  1. Decodes the PrivatePreferencesPayload.
  2. Derives the encryption key via HKDF from the user’s identity key.
  3. Decrypts the contents via AES-256-GCM using the public key as associated data.


Copyright and related rights waived via CC0.


This is really great XMTP team. Many user-friendly experiences can be built on top of this, and clients can leverage onchain data to help users identify “good/known” users whom they would likely want to “allow” vs. “bad/unknown” actors whom they would likely want to block.

Looking forward to working with everyone on this.


We implemented Contact permission preferences at Converse very easily. Working with the XMTP React Native SDK, every status is synced smoothly between the protocol and the application.

Thanks to Contact permission preferences, our users don’t have to worry about keeping their choices if they use different XMTP apps: consent is portable and follows the user.

On the other end, it allows us to protect their inbox in a more efficient manner: thanks to existing allow & block actions, we can learn from the user preferences and filter allow and block suggestions for future conversations (while preserving the user’s privacy).


We’re excited for this upgrade and the opportunities the portable consent layer brings. We built an off-chain, centralized version of subscription/unsubscription preferences in Holder last year and are excited to see the decentralized evolution to manage consent at the protocol level. This is HUGE for empowering permission-based marketing and messaging, which is core to our ethos and beliefs at Holder.

To pull on the permission-based marketing thread — one of our core values back at ExactTarget was actually “Stay True to Permission”. Their “acceptable use policy” is still called the “Permission-Based Marketing Policy” at Salesforce. For the first time, though, that consent can be portable and interoperable across platforms and inboxes, unlike email and SMS.


The capability to support a portable contact preference while preserving privacy and self sovereignty is very powerful. While the protocol enables a seamless UX as a user travels between XMTP clients, the user is in exclusive control of their preference data. For example, if I block a spam or unwanted conversation, my action does not reveal to the sender they have been blocked. The network does not even know I have blocked the sender. This information is private to me, and travels with me wherever I go in XMTP supported apps.

At Unstoppable Domains, we added portable consent across all 3 of our XMTP apps - iOS native, Android native and Web. We felt it is was a critical step in protecting users from spam and other unwanted messages.

Our users appreciate that they can open other apps like Converse and maintain the state of their conversation list.

1 Like

Glad to hear this is a focus and going live :clap::clap: Remember this was an anticipated point of discussion I raised with @mg and @pol at Permissionless 2023.

Online safety is a requirement, not a nice to have. Would be really awesome to have old twitter’s “are you sure you want to send this?” message read and tone identified by local-run ai; would improve the quality of messaging on the network.

Would love to see blocklist leveraged as attestations of bad behavior for global shielding and spam prevention; if enough accounts block someone they could have a global “block preference” applied so their messages are not received. Anyone who thereafter allows receipt from that account is likely a conspirator, so you can let the spam network identify itself for you!