Idempotency & retries
Every write endpoint requires an Idempotency-Key so network retries never double-send a DM, double-follow, or double-charge you.
How it works
- Send a unique
Idempotency-Keyheader with each write (/dm/send,/actions/*,POST /tweets). - The first request with a given key executes and its result is stored.
- Any repeat with the same key returns the stored result — no second send, no second charge. The response carries an
X-Idempotent-Replay: trueheader.
Omitting the header returns
400 invalid_request. Always send one.Choosing a key
Use a value that's stable for the logical operation you're performing:
- One-off action — a random UUID (
uuidgen/crypto.randomUUID()). - Batch / campaign — a deterministic key like
campaign42:acc_1a2b3c:user_44196397. Re-running your job then safely skips anyone already messaged.
Safe retry pattern
async function sendOnce(body, key) {
for (let attempt = 0; attempt < 3; attempt++) {
const res = await fetch("https://api.xautodm.com/v1/dm/send", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.XAUTODM_API_KEY,
"Idempotency-Key": key, // same key across retries
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
if (res.status !== 502) return res.json(); // retry only on upstream errors
await new Promise(r => setTimeout(r, 1000 * (attempt + 1)));
}
}Because the key is constant across attempts, a request that actually succeeded upstream but failed to return won't be sent again — the retry just returns the stored result.