> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xquik.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Twitter API delete tweet: remove an owned post by ID

> Remove one owned post by Tweet ID through a connected X account. Save approval evidence, poll the write status, and verify the deleted ID. Costs 10 credits.

<Panel>
  <Tabs defaultTabIndex={0} sync={false}>
    <Tab title="200" id="response-x-write-delete-tweet-200">
      ```json theme={null}
      {
        "object": "x_write_action",
        "id": "12345",
        "writeActionId": "12345",
        "action": "delete_tweet",
        "status": "success",
        "terminal": true,
        "retryable": false,
        "safeToRetry": false,
        "statusUrl": "/api/v1/x/write-actions/12345",
        "pollAfterMs": null
      }
      ```
    </Tab>

    <Tab title="202" id="response-x-write-delete-tweet-202">
      ```json theme={null}
      {
        "object": "x_write_action",
        "id": "12346",
        "writeActionId": "12346",
        "action": "delete_tweet",
        "status": "dispatching",
        "terminal": false,
        "retryable": false,
        "safeToRetry": false,
        "statusUrl": "/api/v1/x/write-actions/12346",
        "pollAfterMs": 2000
      }
      ```
    </Tab>

    <Tab title="400" id="response-x-write-delete-tweet-400">
      ```json theme={null}
      {
        "error": "missing_idempotency_key",
        "message": "Idempotency-Key is required. Generate one unique key for this write.",
        "charged": false,
        "chargedCredits": "0",
        "retryable": false,
        "safeToRetry": true
      }
      ```
    </Tab>

    <Tab title="401" id="response-x-write-delete-tweet-401">
      ```json theme={null}
      {
        "error": "unauthenticated",
        "message": "Authentication required. Provide a valid API key or bearer token."
      }
      ```
    </Tab>

    <Tab title="402" id="response-x-write-delete-tweet-402">
      ```json theme={null}
      {
        "error": "insufficient_credits",
        "message": "Insufficient credits. Top up or subscribe to continue."
      }
      ```
    </Tab>

    <Tab title="403" id="response-x-write-delete-tweet-403">
      ```json theme={null}
      {
        "error": "account_needs_reauth",
        "message": "X account needs re-authentication. Re-add the account."
      }
      ```
    </Tab>

    <Tab title="404" id="response-x-write-delete-tweet-404">
      ```json theme={null}
      {
        "error": "account_not_found",
        "message": "X account not found. Connect it first at /dashboard/account?tab=x-accounts."
      }
      ```
    </Tab>

    <Tab title="409" id="response-x-write-delete-tweet-409">
      ```json theme={null}
      {
        "error": "idempotency_conflict",
        "message": "Idempotency-Key was already used with a different request.",
        "charged": false,
        "chargedCredits": "0",
        "retryable": false,
        "safeToRetry": true
      }
      ```
    </Tab>

    <Tab title="422" id="response-x-write-delete-tweet-422">
      ```json theme={null}
      {
        "error": "x_rejected",
        "message": "X rejected this request. Check what you sent & the account on x.com before you try again."
      }
      ```
    </Tab>

    <Tab title="429" id="response-x-write-delete-tweet-429">
      ```json theme={null}
      {
        "error": "x_rate_limited",
        "message": "X rate limited this account. Try again in about 15 minutes. Send fewer requests from this account."
      }
      ```
    </Tab>

    <Tab title="500" id="response-x-write-delete-tweet-500">
      ```json theme={null}
      {
        "error": "x_write_failed",
        "message": "Write action failed unexpectedly. Contact support if this persists."
      }
      ```
    </Tab>

    <Tab title="503" id="response-x-write-delete-tweet-503">
      ```json theme={null}
      {
        "error": "write_tracking_unavailable",
        "message": "Write tracking unavailable. Try again.",
        "charged": false,
        "chargedCredits": "0",
        "retryable": true,
        "safeToRetry": true
      }
      ```
    </Tab>
  </Tabs>
</Panel>

<blockquote className="agent-llms-directive">
  For the complete documentation index, see <a href="/llms.txt">llms.txt</a>.
</blockquote>

<Callout icon="coins" color="#5c3327">
  **10 credits per call** · [All plans](https://xquik.com/#pricing) from \$0.00012/credit
</Callout>

Use this route to remove 1 owned post by ID.
It accepts 1 Tweet ID per request.
Select the connected X account that published the tweet.
Save approval evidence before sending the request.
Send 1 unique `Idempotency-Key` for the intended deletion.
Store the returned write action and poll `statusUrl` when needed.
Confirm `targetId` matches the requested Tweet ID after terminal success.
X also documents an official [Delete Post endpoint](https://docs.x.com/x-api/posts/delete-post).
Authenticate with Xquik credentials. Store the write response.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE https://xquik.com/api/v1/x/tweets/1895432178065391234 \
    -H "x-api-key: xq_YOUR_KEY_HERE" \
    -H "Idempotency-Key: tweet-delete-1895432178065391234" \
    -H "Content-Type: application/json" \
    -d '{
      "account": "elonmusk"
    }' | jq '{
      status,
      terminal,
      safe_to_retry: .safeToRetry,
      write_action_id: .id,
      request_hash: .request.hash,
      requested_tweet_id: "1895432178065391234",
      confirmed_tweet_id: (.result.id // .tweetId // .targetId),
      charged_credits: .billing.chargedCredits,
      poll_path: (if .terminal then null else .statusUrl end)
    }'
  ```

  ```javascript Node.js theme={null}
  const tweetId = "1895432178065391234";
  const response = await fetch(`https://xquik.com/api/v1/x/tweets/${tweetId}`, {
    method: "DELETE",
    headers: {
      "x-api-key": "xq_YOUR_KEY_HERE",
      "Idempotency-Key": "tweet-delete-1895432178065391234",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      account: "elonmusk",
    }),
  });
  const result = await response.json();
  if (!response.ok) {
    throw new Error(JSON.stringify(result));
  }
  const deletionRecord = {
    status: result.status,
    terminal: result.terminal,
    safe_to_retry: result.safeToRetry,
    write_action_id: result.id,
    request_hash: result.request.hash,
    requested_tweet_id: tweetId,
    confirmed_tweet_id: result.result?.id ?? result.tweetId ?? result.targetId ?? null,
    account: result.account,
    charged_credits: result.billing.chargedCredits,
    poll_path: result.terminal ? null : result.statusUrl,
  };
  process.stdout.write(`${JSON.stringify(deletionRecord)}\n`);
  ```

  ```python Python theme={null}
  import json
  import requests

  tweet_id = "1895432178065391234"
  response = requests.delete(
      f"https://xquik.com/api/v1/x/tweets/{tweet_id}",
      headers={
          "x-api-key": "xq_YOUR_KEY_HERE",
          "Idempotency-Key": "tweet-delete-1895432178065391234",
      },
      json={
          "account": "elonmusk",
      },
  )
  result = response.json()
  response.raise_for_status()
  deletion_record = {
      "status": result["status"],
      "terminal": result["terminal"],
      "safe_to_retry": result["safeToRetry"],
      "write_action_id": result["id"],
      "request_hash": result["request"]["hash"],
      "requested_tweet_id": tweet_id,
      "confirmed_tweet_id": (
          (result.get("result") or {}).get("id")
          or result.get("tweetId")
          or result.get("targetId")
      ),
      "account": result["account"],
      "charged_credits": result["billing"]["chargedCredits"],
      "poll_path": None if result["terminal"] else result["statusUrl"],
  }
  print(json.dumps(deletion_record))
  ```

  ```go Go theme={null}
  package main

  import (
      "bytes"
      "encoding/json"
      "fmt"
      "io"
      "net/http"
  )

  type DeleteTweetResponse struct {
      ID string `json:"id"`
      Status string `json:"status"`
      Terminal bool `json:"terminal"`
      SafeToRetry bool `json:"safeToRetry"`
      StatusURL string `json:"statusUrl"`
      TargetID *string `json:"targetId"`
      TweetID *string `json:"tweetId"`
      Request struct {
          Hash string `json:"hash"`
      } `json:"request"`
      Account map[string]any `json:"account"`
      Billing struct {
          ChargedCredits string `json:"chargedCredits"`
      } `json:"billing"`
      Result *struct {
          ID string `json:"id"`
      } `json:"result"`
  }

  func main() {
      tweetID := "1895432178065391234"
      body, err := json.Marshal(map[string]string{
          "account": "elonmusk",
      })
      if err != nil {
          panic(err)
      }

      req, err := http.NewRequest(
          "DELETE",
          "https://xquik.com/api/v1/x/tweets/"+tweetID,
          bytes.NewReader(body),
      )
      if err != nil {
          panic(err)
      }
      req.Header.Set("x-api-key", "xq_YOUR_KEY_HERE")
      req.Header.Set("Idempotency-Key", "tweet-delete-1895432178065391234")
      req.Header.Set("Content-Type", "application/json")

      resp, err := http.DefaultClient.Do(req)
      if err != nil {
          panic(err)
      }
      defer resp.Body.Close()
      if resp.StatusCode >= 400 {
          responseBody, _ := io.ReadAll(resp.Body)
          panic(string(responseBody))
      }

      var result DeleteTweetResponse
      if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
          panic(err)
      }
      var confirmedTweetID any
      if result.Result != nil && result.Result.ID != "" {
          confirmedTweetID = result.Result.ID
      } else if result.TweetID != nil {
          confirmedTweetID = *result.TweetID
      } else if result.TargetID != nil {
          confirmedTweetID = *result.TargetID
      }
      var pollPath any
      if !result.Terminal {
          pollPath = result.StatusURL
      }
      deletionRecord := map[string]any{
          "status": result.Status,
          "terminal": result.Terminal,
          "safe_to_retry": result.SafeToRetry,
          "write_action_id": result.ID,
          "request_hash": result.Request.Hash,
          "requested_tweet_id": tweetID,
          "confirmed_tweet_id": confirmedTweetID,
          "account": result.Account,
          "charged_credits": result.Billing.ChargedCredits,
          "poll_path": pollPath,
      }
      encoded, err := json.Marshal(deletionRecord)
      if err != nil {
          panic(err)
      }
      fmt.Println(string(encoded))
  }
  ```
</CodeGroup>

## Delete one owned tweet by ID

Send the exact Tweet ID in the path.
Send its author account in the request body.
The connected account must own the target tweet.
You cannot delete another account's tweet with this route.

A reply is also a tweet with its own ID.
Delete the reply ID without deleting its parent tweet.
Use [Get Tweet](/api-reference/x/get-tweet) before deletion.
Save the returned author, text, creation time, media, and conversation ID.

Create a dedicated idempotency key for each intended deletion.
Reuse that key only after an interrupted response.
Never reuse a create-tweet key for deletion.

## Authenticate the tweet owner

Send an Xquik API key or OAuth 2.1 bearer token.
Then identify the connected X account with `account`.
The request never accepts an X password or session cookie.
Keep API keys on your server, not inside browser or mobile clients.

The official X endpoint uses a user access token.
Its permissions differ from Xquik authentication.
Read X's [Manage Posts guide](https://docs.x.com/x-api/posts/manage-tweets/introduction) for that separate contract.

## Save tweet deletion evidence

This API workflow cannot restore a deleted tweet.
Show the final tweet text during approval.
Keep the approver, approval time, and reason beside the Tweet ID.

Store these fields after sending the request:

* Store `id` as the write action ID.
* Store `request.hash` for exact request matching.
* Store `account` for the connected tweet owner.
* Store `targetId` for the confirmed Tweet ID.
* Store `status`, `terminal`, and `statusUrl` for polling.
* Store `billing.chargedCredits` for the deletion charge.
* Store `safeToRetry` before considering another request.

A replacement tweet receives a different Tweet ID.
Keep the deleted ID in the audit record.
Join replies, analytics, and moderation records with the deleted ID.

## Run bulk or scheduled tweet cleanup

This route deletes 1 tweet per request.
It does not provide a bulk-delete operation.
Feed approved Tweet IDs through the route individually.
Create a unique `Idempotency-Key` for every Tweet ID.

Delete tweets from a queue, one at a time. Store every write action.
After HTTP `429`, wait for `Retry-After` before continuing.
X publishes separate limits for its [Delete Post endpoint](https://docs.x.com/x-api/fundamentals/rate-limits).
Those limits do not replace Xquik's response headers.

This endpoint does not schedule future deletion.
Let your scheduler call it at the approved time.
Keep each scheduled Tweet ID and approval reference together.

## Verify tweet deletion

A `202` response means the deletion is still running.
Poll `statusUrl` until `terminal` becomes `true`.
Never submit another deletion while the action is running.

After terminal success, accept `targetId`, `tweetId`, or `result.id` as
confirmation. Call [Get Tweet](/api-reference/x/get-tweet) with that ID.
Store the lookup time and result beside the write action.

Save the unavailable lookup beside the successful write action.
Before terminal success, an unavailable lookup proves nothing.
A missing tweet does not always prove deletion.

## Handle delete tweet errors

Never infer failure from a client timeout.
Poll the returned action before sending another request.
Use [Twitter API error handling](/api-reference/x-write/get-write-action-status)
for every lifecycle field and retry rule.

* For `400`, fix the Tweet ID or account value.
* For `401`, replace invalid Xquik authentication.
* For `402`, add credits before another deletion.
* For `403`, reconnect the selected X account.
* For `409`, keep the original action and payload.
* For `422`, review the rejection before retrying.
* For `429`, wait for `Retry-After`.
* For `500` or `503`, trust `safeToRetry` and `terminal`.

## Choose tweet deletion, unlike, or unretweet

Use tweet deletion only when the connected account owns the published post.
It removes that post. It does not reverse a like or repost.

Use [Unlike Tweet](/api-reference/x-write/unlike) to remove one account's like.
Use [Unretweet](/api-reference/x-write/unretweet) to remove one account's
repost. Both actions keep the source tweet.

| Cleanup intent | API route | What changes |
| - | - | - |
| Remove an owned post | `DELETE /x/tweets/{id}` | The connected account's tweet becomes unavailable. |
| Remove a like | `DELETE /x/tweets/{id}/like` | Xquik removes only that account's like. |
| Remove a repost | `DELETE /x/tweets/{id}/retweet` | Xquik removes only that account's repost. |
| Remove a reply | `DELETE /x/tweets/{id}` | Xquik deletes the owned reply tweet by its own ID. |

Never delete the source tweet when a campaign only needs engagement cleanup.
Check the route during approval. Record the intended state.

## Twitter API delete tweet questions

### Can the API delete another user's tweet?

No. The connected account must own the target tweet.
Use the author's own connected account and exact Tweet ID.

### Can the API delete all tweets at once?

No bulk route exists here.
Submit 1 approved Tweet ID per request.
Store each deletion's key, write action, and terminal result.

### Can I schedule a tweet deletion?

Yes, through your own scheduler.
Call this endpoint at the approved time.
The endpoint itself does not store a future schedule.

### Which libraries can delete a tweet?

Any HTTP client can call this REST endpoint.
The examples cover cURL, Node.js, Python, and Go.
Keep credentials in server-side code.

### How should recurring tweet cleanup work?

Select owned Tweet IDs using an approved retention policy.
Save a copy of each tweet before deletion.
Send 1 deletion, store its action, and verify its terminal result.

## Headers

<ParamField header="x-api-key" type="string">
  Send your Xquik API key in this header. Alternatively, send an OAuth 2.1 bearer token.
</ParamField>

<ParamField header="Authorization" type="string">
  Send `Bearer <token>` instead of `x-api-key` when using OAuth 2.1.
</ParamField>

<ParamField header="Idempotency-Key" type="string" required>
  Unique key for this intended write. Reuse it only for an exact network replay.
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be `application/json`.
</ParamField>

## Path parameters

<ParamField path="id" type="string" required>
  Post ID or URL-encoded post URL, such as `x.com/nasa/status/20`. See [path IDs](/api-reference/overview#path-ids).
  The connected account must own the post.
</ParamField>

## Body

<ParamField body="account" type="string" required>
  X username or account ID identifying which connected X account owns the tweet. Xquik strips the `@` prefix if included.
</ParamField>

## Response

## Durable write recovery

<Warning>
  Send one unique `Idempotency-Key` per intended write.
  Replay the same account, target, payload, and media after a lost response.
  Keep the original key for that replay.
</Warning>

1. Store `id`, the nested `hash` in `request`, `billing`, and `statusUrl`.
2. Poll after `Retry-After` or `pollAfterMs` when `terminal` is `false`.
3. Retry only when `safeToRetry` is `true`.
4. Use a new key when `nextAction.requiresNewIdempotencyKey` is `true`.

### 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 for `Retry-After`. Follow `nextAction`.

See [Get Write Action Status](/api-reference/x-write/get-write-action-status)
for every lifecycle field, terminal state, billing field, and retry rule.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.