Send DM API
Send a direct message to a user as the authenticated account. Requires a logged-in session for the acting account. Billed at $0.0016 per call. Cost: $0.0016 per call.
POST dm/send sends a direct message from the authenticated Twitter/X account to a specified recipient. It requires recipient_id and text, and returns ok (whether the send succeeded), message_id, conversation_id, recipient_id, and text. The call requires a logged-in session for the sending account and is billed at $0.0016 per request.
Authorization
bearerAuth Pass your API key as a bearer token on every request: Authorization: Bearer <API_KEY>.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/dm/send" \ -H "Content-Type: application/json" \ -d '{ "recipient_id": "44196397", "text": "Hello from the TwitterAPIs DM API" }'{ "ok": true, "message_id": "1899999999999999999", "conversation_id": "44196397-11348282", "recipient_id": "44196397", "text": "Hello from the TwitterAPIs DM API"}{ "error": "bad_request", "message": "Missing or malformed parameter. Fix the request before retrying."}{ "error": "unauthorized", "message": "The API key is missing, malformed, or revoked. Check the Authorization header."}{ "error": "insufficient_credits", "message": "Your balance is exhausted. Top up your credits to continue."}{ "error": "forbidden", "message": "The acting account is not authorized for this write action, or has no logged-in session."}{ "error": "not_found", "message": "The resource does not exist, for example a deleted tweet or a private account."}{ "error": "rate_limited", "message": "Too many requests. Back off and retry with exponential backoff."}{ "error": "server_error", "message": "Something failed on our side. Retry with backoff; if it persists, contact support."}Pricing
| Unit | Price |
|---|---|
| Per call | $0.0016 |
| Per 1,000 calls | $1.60 |
When to use
Use POST dm/send when your application needs to send a new direct message to a specific user as the authenticated account, for example after a form submission, a support handoff, or an automated outreach trigger. Use it instead of a conversation-read endpoint when the goal is to write a message, not retrieve existing DM history or list threads.
Notes
- Requires a registered session for the acting account (POST /twitter/customer/session); a DM is sent from your own session, never a shared pool account.
- recipient_id + text may be sent in the query string or a JSON request body.
Related endpoints
- DM Inbox: List the Direct Message conversations for your registered account.
- DM Conversation: Read the message history of one DM conversation by conversation_id.
FAQ
What happens if the message fails to send?
The response still returns ok as false and message_id as null. conversation_id can also be null if the upstream response did not include it, so check ok before relying on message_id or conversation_id being populated.
How do I identify the recipient, by username or user ID?
recipient_id must be the recipient's numeric Twitter user ID, not a username or handle. If you only have a username, resolve it to a numeric ID first before calling dm/send.
DM Conversation GET
Fetch the messages inside a single DM conversation. Pass a conversation_id from GET /dm/list. Each message carries its ID, sender ID, timestamp, and text. Authenticate with a registered session (POST /customer/session) or per-call x-auth-token and x-ct0 headers. Read-only: this does not send DMs. Cost: $0.0016 per call.
Overview
Account Session: Bring your own X session cookies (recommended), or mint a session from a username and password, so write actions and private-data reads act as your account. Free.