> ## 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.

# Remove Twitter bookmark API to unsave a tweet by ID

> Remove 1 bookmark by Tweet ID from a connected X account. Store the write action, result and billed credits. Retry only when safeToRetry is true. 10 credits.

> [tab] 200
>
> ```json theme={null}
> {
>   "object": "x_write_action",
>   "id": "12345",
>   "writeActionId": "12345",
>   "action": "unbookmark",
>   "status": "success",
>   "terminal": true,
>   "retryable": false,
>   "safeToRetry": false,
>   "statusUrl": "/api/v1/x/write-actions/12345",
>   "pollAfterMs": null
> }
> ```

> [tab] 202
>
> ```json theme={null}
> {
>   "object": "x_write_action",
>   "id": "12346",
>   "writeActionId": "12346",
>   "action": "unbookmark",
>   "status": "dispatching",
>   "terminal": false,
>   "retryable": false,
>   "safeToRetry": false,
>   "statusUrl": "/api/v1/x/write-actions/12346",
>   "pollAfterMs": 2000
> }
> ```

> [tab] 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] 401
>
> ```json theme={null}
> {
>   "error": "unauthenticated",
>   "message": "Authentication required. Provide a valid API key or bearer token."
> }
> ```

> [tab] 402
>
> ```json theme={null}
> {
>   "error": "insufficient_credits",
>   "message": "Insufficient credits. Top up or subscribe to continue."
> }
> ```

> [tab] 403
>
> ```json theme={null}
> {
>   "error": "api_key_paused",
>   "message": "This API key is paused. Resume it at dashboard.xquik.com/api-keys to use it again."
> }
> ```

> [tab] 404
>
> ```json theme={null}
> {
>   "error": "account_not_found",
>   "message": "X account not found. Connect it first at /dashboard/x-accounts."
> }
> ```

> [tab] 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] 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] 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] 500
>
> ```json theme={null}
> {
>   "error": "x_write_failed",
>   "message": "Write action failed unexpectedly. Contact support if this persists."
> }
> ```

> [tab] 503
>
> ```json theme={null}
> {
>   "error": "write_tracking_unavailable",
>   "message": "Write tracking unavailable. Try again.",
>   "charged": false,
>   "chargedCredits": "0",
>   "retryable": true,
>   "safeToRetry": true
> }
> ```

> For the complete documentation index, see [llms.txt](https://docs.xquik.com/llms.txt).

**10 credits per call** · [All plans](https://xquik.com) from \$0.00012/credit

Each request removes 1 bookmark by Tweet ID.
Each request uses 1 connected X account.
It never deletes the tweet or changes another account's bookmarks.
Create a unique `Idempotency-Key` for the intended removal.
Store the returned write action and poll `statusUrl` when needed.

```bash cURL theme={null}
curl -X DELETE https://xquik.com/api/v1/x/tweets/1895432178065391234/bookmark \
  -H "x-api-key: xq_YOUR_KEY_HERE" \
  -H "Idempotency-Key: unbookmark-1895432178065391234" \
  -H "Content-Type: application/json" \
  -d '{"account":"elonmusk"}' | jq '{
    status,
    terminal,
    safe_to_retry: .safeToRetry,
    write_action_id: .id,
    requested_tweet_id: "1895432178065391234",
    confirmed_tweet_id: (.result.id // .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}/bookmark`, {
  method: "DELETE",
  headers: {
    "x-api-key": "xq_YOUR_KEY_HERE",
    "Idempotency-Key": "unbookmark-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 removalRecord = {
  status: result.status,
  terminal: result.terminal,
  safe_to_retry: result.safeToRetry,
  write_action_id: result.id,
  requested_tweet_id: tweetId,
  confirmed_tweet_id: result.result?.id ?? result.targetId ?? null,
  charged_credits: result.billing.chargedCredits,
  poll_path: result.terminal ? null : result.statusUrl,
};
process.stdout.write(`${JSON.stringify(removalRecord)}\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}/bookmark",
    headers={
        "x-api-key": "xq_YOUR_KEY_HERE",
        "Idempotency-Key": "unbookmark-1895432178065391234",
    },
    json={"account": "elonmusk"},
)
result = response.json()
response.raise_for_status()
removal_record = {
    "status": result["status"],
    "terminal": result["terminal"],
    "safe_to_retry": result["safeToRetry"],
    "write_action_id": result["id"],
    "requested_tweet_id": tweet_id,
    "confirmed_tweet_id": (result.get("result") or {}).get("id") or result.get("targetId"),
    "charged_credits": result["billing"]["chargedCredits"],
    "poll_path": None if result["terminal"] else result["statusUrl"],
}
print(json.dumps(removal_record))
```

## Remove one bookmark by Tweet ID

Put the exact Tweet ID in the request path.
Put the connected account username or ID in the body.
That account loses the bookmark.

This endpoint accepts 1 Tweet ID per request.
It never deletes the tweet, likes, or reposts.

## Clear many bookmarks

Read the saved posts with [Bookmarks](https://docs.xquik.com/api-reference/x/bookmarks.md).
Send 1 request per Tweet ID with its own `Idempotency-Key`.
Keep each removal in your ledger before the next request.

Show the account owner the posts before the removal starts.
Removed bookmarks don't come back unless the account saves them again.

## Save a removal receipt

| Removal column | Source | Rule |
| - | - | - |
| `acting_account` | Request `account` | Match the account that saved the bookmark. |
| `tweet_id` | Path `id` | Keep the exact bookmarked Tweet ID. |
| `idempotency_key` | Request header | Create a fresh key for each removal. |
| `write_action_id` | Response `id` | Store the removal action. |
| `terminal` | Response `terminal` | Change the local list only when `true`. |
| `safe_to_retry` | Response `safeToRetry` | Retry only when this value is `true`. |

## Twitter remove bookmark API questions

### Can an API remove a bookmark by Tweet ID?

Yes. Send the Tweet ID in the path and the connected account in the body.

### How do I remove all bookmarks?

Page through [Bookmarks](https://docs.xquik.com/api-reference/x/bookmarks.md), then remove each post with this route.
Each removal costs 10 credits.

## Handle errors

Never infer failure from a client timeout.
Poll a returned action before sending another request.

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

## Headers

**x-api-key** `string`

Send your Xquik API key in this header. Alternatively, send an OAuth 2.1 bearer token.

**Authorization** `string`

Send `Bearer <token>` instead of `x-api-key` when using OAuth 2.1.

**Idempotency-Key** `string` *required*

Unique key for this intended write. Reuse it only for an exact network replay.

**Content-Type** `string` *required*

Must be `application/json`.

## Path parameters

**id** `string` *required*

Post ID or URL-encoded post URL, such as `x.com/nasa/status/20`. See [path IDs](https://docs.xquik.com/api-reference/overview.md#path-ids).

## Body

**account** `string` *required*

X username or account ID of the connected X account that removes the bookmark. Xquik strips the `@` prefix if included.

## 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.

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](https://docs.xquik.com/api-reference/x-write/get-write-action-status.md)
for every lifecycle field and terminal state. That page also lists every billing
field and retry rule.


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