Every content type ID has the form authorityId/typeId:versionMajor.versionMinor. The encoded envelope contains the type ID, parameters, content bytes, and optional fallback text. shouldPush is a send option, separate from the content envelope. The table gives each type’s default. An explicit send option can override that default.
Content type
Type ID
Wire payload
Fallback
Default shouldPush
Text
xmtp.org/text:1.0
UTF-8 bytes and an encoding parameter
None
true
Markdown
xmtp.org/markdown:1.0
UTF-8 bytes and an encoding parameter
None
true
Reply
xmtp.org/reply:1.0
Nested EncodedContent; reference parameters
Describes the reply
true
Reaction
xmtp.org/reaction:2.0
ReactionV2 protobuf
Describes the reaction
false
Read receipt
xmtp.org/readReceipt:1.0
Empty
None
false
Attachment
xmtp.org/attachment:1.0
Raw bytes; MIME type and file name parameters
Names the unsupported file
true
Remote attachment
xmtp.org/remoteStaticAttachment:1.0
URL bytes and decryption parameters
Names the unsupported file
true
Multiple remote attachments
xmtp.org/multiRemoteStaticAttachment:1.0
MultiRemoteAttachment protobuf
Describes unsupported attachments
true
Group update
xmtp.org/group_updated:1.0
GroupUpdated protobuf
None
false
Transaction reference
xmtp.org/transactionReference:1.0
JSON-encoded TransactionReference
Describes the transaction
true
Wallet send calls
xmtp.org/walletSendCalls:1.0
JSON-encoded WalletSendCalls
Describes the request
true
Delete message
xmtp.org/deleteMessage:1.0
DeleteMessage protobuf
None
false
Leave request
xmtp.org/leave_request:1.0
LeaveRequest protobuf
None
false
Actions
coinbase.com/actions:1.0
JSON-encoded Actions
Numbered action list
true
Intent
coinbase.com/intent:1.0
JSON-encoded Intent
Names the selected action
true
Browser, Node, Kotlin, and Swift include these standard codecs. Core decodes standard content without app registration. Register codecs only for custom content that your app receives. A codec matches the authority, type ID, and major version; the minor version is not part of this match.
Node exports standalone codecs from @xmtp/node-sdk. Browser exports them from @xmtp/browser-sdk/pure; call initPureWasm() before you use them. Kotlin and Swift expose typed codec wrappers over the same Rust encoders and decoders.
Group updates are local transcripts produced from commits. Apps cannot publish a group-update transcript as an application message. Delete messages are control messages; Core applies authorized deletion and exposes the result as deleted-message content. Use the SDK delete methods to request deletion.
When building with XMTP, you can’t know in advance whether a recipient’s app will support a given content type, especially a custom one. Likewise, your own app might receive messages with content types it doesn’t support.
To prevent a poor user experience or app crashes, you should use the fallback property.
For sending: When sending a message with a custom content type, always provide a fallback string. This string offers a human-readable representation of the content. If the recipient’s app doesn’t support your custom type, it can display the fallback text instead.
For receiving: When your app receives a message, check if it supports the message’s contentType. If not, render the fallback text.
Some background types, such as read receipts, have no fallback. A renderer can skip them. Do not assume that message.content is missing for an unsupported type. Browser and Node expose a content union with unknown and custom variants. Kotlin and Swift expose SDKMessageContent with standard, custom, and unknown variants. Raw bytes and decode errors remain available.
These examples show a text-only renderer. It shows text, skips read receipts, and uses fallback text for other content. Extend it with the types your app can display.
A received or stored message. Its fields are public values. Its actions use
the client that returned it; the message holds that client weakly, so an
action after the client ends or is collected fails with ClientClosed.
The generated base holds the message's fields.
A received or stored message. Its fields are public values. Its actions use
the client that returned it; the message holds that client weakly, so an
action after the client ends or is collected fails with ClientClosed.
The generated base holds the message's fields.
A received or stored message. Its fields are public values. Its actions use
the client that returned it; the message holds that client weakly, so an
action after the client ends or is collected fails with ClientClosed.
The generated base holds the message's fields.
A received or stored message. Its fields are public values. Its actions use
the client that returned it; the message holds that client weakly, so an
action after the client ends or is collected fails with ClientClosed.
The generated base holds the message's fields.
Custom content types allow you to define your own schemas for messages that go beyond what is covered by standard content types. These are useful for experiments, domain-specific features, or app-specific behaviors.
A content type needs a codec which must satisfy the ContentCodec interface from @xmtp/node-sdk or @xmtp/browser-sdk.
Example:
importtype {
interfaceContentCodec<T>
A content codec over public values. The send helpers run its steps before
the send starts: encode, then fallback when the envelope has none, then
shouldPush when the send has no explicit shouldPush option. A step that
throws, rejects, or returns a value of the wrong type fails the send with
XmtpError.CodecEncodeFailed, and the SDK makes no publish attempt. Each
step is a function property, so the value type is checked in both
directions.
ContentCodec,
typeContentTypeId= {
readonlyauthorityId:string;
readonlytypeId:string;
readonlyversionMajor:number;
readonlyversionMinor:number;
}
ContentTypeId,
typeEncodedContent= {
readonlytype:ContentTypeId;
readonlyparameters?:Map<string, string>;
readonlyfallback?:string|undefined;
readonlycontent:Uint8Array;
}
EncodedContent,
} from"@xmtp/node-sdk";
// Define the content type identifier.
exportconst
constCustomContentType:ContentTypeId
CustomContentType:
typeContentTypeId= {
readonlyauthorityId:string;
readonlytypeId:string;
readonlyversionMajor:number;
readonlyversionMinor:number;
}
ContentTypeId= {
authorityId: string
authorityId: "your-domain.com",
typeId: string
typeId: "your-custom-id",
versionMajor: number
versionMajor: 1,
versionMinor: number
versionMinor: 0,
};
// Implement a codec for string values.
exportclass
classCustomCodec
CustomCodecimplements
interfaceContentCodec<T>
A content codec over public values. The send helpers run its steps before
the send starts: encode, then fallback when the envelope has none, then
shouldPush when the send has no explicit shouldPush option. A step that
throws, rejects, or returns a value of the wrong type fails the send with
XmtpError.CodecEncodeFailed, and the SDK makes no publish attempt. Each
step is a function property, so the value type is checked in both
directions.
var TextDecoder:new (label?:string, options?:TextDecoderOptions) =>TextDecoder
The TextDecoder interface represents a decoder for a specific text encoding, such as UTF-8, ISO-8859-2, or GBK. A decoder takes an array of bytes as input and returns a JavaScript string.
Pass custom codec instances in the codecs option to Browser or Node Client.create(), or to Agent.create(). Kotlin and Swift accept a codecs argument on SDKClient.create(). Registration decodes incoming custom content. To send a custom value, pass the codec and value to a typed send method.
This example registers a codec with an agent:
import {
classAgent<ContentTypes=unknown>
Event-driven XMTP agent that routes conversations and messages to middleware.
Agent } from"@xmtp/agent-sdk";
// Set XMTP_WALLET_KEY and XMTP_BACKEND_URL before this program runs.
const
constagent:Agent<unknown>
agent=await
classAgent<ContentTypes=unknown>
Event-driven XMTP agent that routes conversations and messages to middleware.
Create an agent from XMTP_* variables. XMTP_BACKEND_URL overrides options.backend; one must be supplied. Pass backend.credentials in options for backend authentication.