Zernio
APIFor you
Zernio
APIFor you
Platforms

X

Overview

Publish

Posts & editingReplies & quotesMedia & videoFields, geo & polls

Engage

Analytics & engagementInbox

Reference

Limits & errors
Dashboard
OverviewPlatformsAPI ReferenceResources
X

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 @) or participantId (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

FeatureSupported
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).

FeatureSupported
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.received and comment.received payloads.
  • X API usage: what a DM read and send costs.
Was this page helpful?

Analytics & engagement

Read post analytics for X with GET /v1/analytics, and retweet, bookmark and follow with the Twitter engagement endpoints.

Limits & errors

Every platformSpecificData field for X, what X's API does not expose, and the errors you will see with their fixes.

On this page

Before you startSend a DMDirect messagesCommentsIf it failsRelated