Inbox
Send and read X direct messages and manage replies to your posts through the inbox API.
By the end of this page you can open a DM conversation on X (platform value twitter) with POST /v1/inbox/conversations. You can also read the conversations that follow and manage replies to your posts as comments.
Before you start
You need a connected X account (accountId) with the dm.read and dm.write scopes.
X DMs are billed at X's pass-through rate, never on the outbound message meter.
Send a DM
Call POST /v1/inbox/conversations (Create conversation) with:
accountId- the recipient, as
participantUsername(an X handle, with or without the @) orparticipantId(the numeric X user id) message
If a conversation with that person already exists, the message is appended to it.
Before sending, Zernio checks that the recipient accepts DMs from your account. When they do not, it returns 422 with code DM_NOT_ALLOWED.
Pass skipDmCheck: true to skip the check when you have already verified eligibility.
import Zernio from '@zernio/node';
const zernio = new Zernio();
const { data: sent } = await zernio.messages.createInboxConversation({
body: {
accountId: '66b2e19d8c3f5a7e9d0b1c2d',
participantUsername: 'XDevelopers',
message: 'Thanks for the report. Which endpoint returned the error?'
}
});
console.log(sent.data.conversationId, sent.data.messageId);Response (201):
{
"success": true,
"data": {
"messageId": "1852634789012345678",
"conversationId": "2244994945-1234567890",
"participantId": "2244994945",
"participantName": "Developers",
"participantUsername": "XDevelopers"
}
}The conversation then appears in List conversations with platform: "twitter". Later messages go through Send message.
Direct messages
| Feature | Supported |
|---|---|
| List conversations | |
| Fetch messages | |
| Send text messages | |
| Send attachments | (images and videos up to 25 MB) |
| Archive and unarchive |
X's DM API allows 200 requests per 15 minutes and 1,000 per 24 hours per connected X account.
Conversations are cached for 2 minutes. A list read inside that window is served from Zernio's copy rather than X.
X Chat. X's API does not return messages sent or received through X Chat.
X has replaced traditional DMs with end-to-end encrypted "X Chat" for many accounts. Some conversations therefore show only outgoing messages or appear empty.
This is an X platform limitation that affects every third-party application.
Your own X API credentials. X requires the Pro tier ($5,000 per month) or Enterprise access for DM writes.
Comments
Replies to your posts are comments in the inbox (List commented posts).
Reply lookups use cached conversation threads with a 2-minute TTL, to stay within X's rate limits.
To reply under one of your posts, call POST /v1/inbox/comments/{postId} with accountId and message. Add commentId to aim the reply at a specific comment instead of the post itself.
const { data: reply } = await zernio.comments.replyToInboxPost({
path: { postId: '65f1c0a9e2b5af0012ab34cd' },
body: {
accountId: '66b2e19d8c3f5a7e9d0b1c2d',
commentId: '1852634789012345679',
message: 'Fixed in the 2.4 release, thanks for flagging it.'
}
});Response (200):
{
"success": true,
"data": {
"commentId": "1852634789012345680",
"isReply": true
}
}postId takes the Zernio post id or the X post id, so a post published outside Zernio can be answered too.
Send an Idempotency-Key header on retries. The same key with the same body replays the original response instead of posting twice (idempotency).
| Feature | Supported |
|---|---|
| List comments on posts | |
| Post a new comment | |
| Reply to comments | |
| Delete comments | |
| Like and unlike comments | |
| Hide and unhide comments |
If it fails
A 422 on POST /v1/inbox/conversations means the recipient does not accept DMs from your account:
{
"error": "Recipient does not accept DMs from this account",
"code": "DM_NOT_ALLOWED"
}Nothing was sent. The recipient has to open their DMs to your account first.
skipDmCheck: true skips this check. Use it only when you have verified eligibility yourself.
A 429 with code rate_limited means X's DM limit for the account is exhausted. Wait for the window to pass.
Error handling covers the envelope.
Related
- Create conversation: every field, including attachments.
- List conversations and List commented posts: the inbox API.
- Inbox webhooks:
message.receivedandcomment.receivedpayloads. - X API usage: what a DM read and send costs.