X write
Twitter DM API: send direct messages with media
Send text or one media attachment as a direct message from a connected X account. Poll the write action and handle every response. Each send costs 10 credits.
- 200
- 202
- 400
- 401
- 402
- 403
- 404
- 409
- 422
- 429
- 500
- 503
POST
Twitter DM API: send direct messages with media
10 credits per send · Compare plans
Send direct messages with the Twitter DM API
Use this route for approved, one-to-one messages. It sends text or one uploaded media attachment. SDKs, support tools, and server jobs can call it. Choose the connected X account and the recipient’s numeric user ID. Use Twitter profile lookup when you only know a username. Follow X’s Direct Message rules for every message.Authenticate and select the recipient
Authenticate with anx-api-key header or an OAuth bearer token.
The connected X account sends the message on the user’s behalf.
The path userId identifies the recipient, not the sender.
Send only messages approved by your workflow.
Honor recipient privacy, consent, and opt-out decisions.
Read DM history only for approved conversation context.
Send text or one media attachment
Provide non-emptytext for every direct message.
Upload media first with Upload Media.
Place its mediaId inside a one-item media_ids array.
The upload costs another 10 credits.
Empty or multi-item arrays return 400 invalid_input.
This route also rejects reply_to_message_id.
It does not send group messages or accept public media URLs.
Poll and verify the direct message
A200 response contains a terminal write action.
A 202 response requires polling through statusUrl.
Wait for terminal: true before closing the send job.
Xquik settles a pending DM within 15 minutes of the send:
successwithmessageIdmeans X sent it. You pay once.failedwithx_dm_not_sentmeans the conversation shows no DM from the sender since shortly before the send. You pay nothing, andsafeToRetryistrue. If you deleted the DM on X yourself, check before you send it again.expiredmeans Xquik could not check the conversation. You pay nothing. Check the conversation before you send again.
writeActionId, recipient ID, account, request hash, and messageId.
Delete DM takes that messageId later.
If the connection drops, retry with the same idempotency key.
Never create another write while the first action remains nonterminal.
The Xquik POST limit is 120 requests per minute.
Handle every Twitter DM API response
Fix request fields after400.
Replace authentication after 401, then add credits after 402.
Reconnect the X account after 403.
Keep the original request after a 409 idempotency conflict.
422 x_dm_not_allowed means this sender cannot message that person.
Try another approved sender or ask the person to allow DMs.
Honor Retry-After after 429.
429 x_rate_limited means X paused DMs from that account.
Its DMs then get 429 until X’s reset, and Xquik sends nothing to X.
You pay nothing. Retry-After and nextAction.afterMs give the wait.
After 500 or 503, inspect safeToRetry before retrying.
Twitter DM API questions
Can I automate customer support direct messages?
Yes. Queue approved replies and store the exact sent text. Avoid unsolicited bulk messaging and honor every opt-out.Can I send images or video through the API?
Upload the file first, then send its singlemediaId.
This endpoint accepts one attachment per message.
Does this endpoint retrieve message history or create webhooks?
No. Use Get DM History for prior messages. This send route does not configure incoming-DM notifications.Can third-party tools and generated SDKs call this route?
Yes. Use the documented REST fields and authentication. Leavereply_to_message_id unset when a generated SDK exposes it.
Headers
string
required
Your API key. OAuth bearer authentication is also supported. Generate a key from the dashboard.
string
required
Unique key for this intended send. Reuse it only for an exact network replay.
string
required
Must be
application/json.Path parameters
string
required
DM recipient: user ID, username with or without
@, or URL-encoded profile URL, such as x.com/nasa.
An unknown username returns 422 x_target_not_found. See path IDs.Body
string
required
X username or account ID of your connected sender account.
string
required
Non-empty direct message text.
string[]
Optional one-item array containing an uploaded media ID.
Response
Durable write recovery
- Store
id, the nestedhashinrequest,billing, andstatusUrl. - Poll after
Retry-AfterorpollAfterMswhenterminalisfalse. - Retry only when
safeToRetryistrue. - Use a new key when
nextAction.requiresNewIdempotencyKeyistrue.
200 terminal or 202 active
- After HTTP
200, store the result and settled billing. - After HTTP
202, poll the same action. Never submit another write. - After HTTP
400, fix the named field. Use a new idempotency key. - After HTTP
401, fix authentication. Do not retry unchanged. - After HTTP
402, fund the account before another write. - After HTTP
403, reconnect the account. - After HTTP
409, keep the original action. Use a new key for new input. - After HTTP
422, fix the rejected request before retrying. - After HTTP
429, wait forRetry-After. FollownextAction.