> ## 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 profile update API: name, bio, location, URL

> Update a Twitter profile bio, display name, location, or website through Xquik. Send only changed fields, poll the write action, and handle each response.

<Panel>
  <Tabs defaultTabIndex={0} sync={false}>
    <Tab title="200" id="response-x-write-update-profile-200">
      ```json theme={null}
      {
        "object": "x_write_action",
        "id": "12345",
        "writeActionId": "12345",
        "action": "update_profile",
        "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-update-profile-202">
      ```json theme={null}
      {
        "object": "x_write_action",
        "id": "12346",
        "writeActionId": "12346",
        "action": "update_profile",
        "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-update-profile-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-update-profile-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-update-profile-402">
      ```json theme={null}
      {
        "error": "insufficient_credits",
        "message": "Insufficient credits. Top up or subscribe to continue."
      }
      ```
    </Tab>

    <Tab title="403" id="response-x-write-update-profile-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-update-profile-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-update-profile-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-update-profile-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-update-profile-429">
      ```json theme={null}
      {
        "error": "rate_limit_exceeded",
        "message": "Too many requests. Try again later.",
        "retryAfter": 60
      }
      ```
    </Tab>

    <Tab title="500" id="response-x-write-update-profile-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-update-profile-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>

This route updates public profile text. Change a display
name, bio, location, or website in one request. Send only the fields that need
new values. Omitted fields remain unchanged. The connected account receives
every approved change.

This route does not change a username, avatar, banner, or birth date. Use
[Update Avatar](/api-reference/x-write/update-avatar) or
[Update Banner](/api-reference/x-write/update-banner) for profile images.
Read X's [profile customization guide](https://help.x.com/articles/166743)
before updating profile text.

## Update Twitter profile text

Call `PATCH /x/profile` to update Twitter profile fields from code.
Provide the connected account plus at least 1 supported field. The `name`
field changes the display name, not the `@username`. The `description` field
changes the public bio. The `location` and `url` fields change their matching
public labels.

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

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PATCH https://xquik.com/api/v1/x/profile \
    -H "x-api-key: xq_YOUR_KEY_HERE" \
    -H "Idempotency-Key: profile-update-1895432178065391234" \
    -H "Content-Type: application/json" \
    -d '{
      "account": "myxaccount",
      "name": "New Display Name",
      "description": "Building cool things",
      "location": "San Francisco",
      "url": "https://example.com"
    }' | jq
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://xquik.com/api/v1/x/profile", {
    method: "PATCH",
    headers: {
      "x-api-key": "xq_YOUR_KEY_HERE",
      "Idempotency-Key": "profile-update-1895432178065391234",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      account: "myxaccount",
      name: "New Display Name",
      description: "Building cool things",
      location: "San Francisco",
      url: "https://example.com",
    }),
  });
  const data = await response.json();
  ```

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

  response = requests.patch(
      "https://xquik.com/api/v1/x/profile",
      headers={
          "x-api-key": "xq_YOUR_KEY_HERE",
          "Idempotency-Key": "profile-update-1895432178065391234",
      },
      json={
          "account": "myxaccount",
          "name": "New Display Name",
          "description": "Building cool things",
          "location": "San Francisco",
          "url": "https://example.com",
      },
  )
  data = response.json()
  ```

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

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

  func main() {
      body, _ := json.Marshal(map[string]interface{}{
          "account":     "myxaccount",
          "name":        "New Display Name",
          "description": "Building cool things",
          "location":    "San Francisco",
          "url":         "https://example.com",
      })

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

      resp, err := http.DefaultClient.Do(req)
      if err != nil {
          panic(err)
      }
      defer resp.Body.Close()

      var data map[string]interface{}
      if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
          panic(err)
      }
      fmt.Println(data)
  }
  ```
</CodeGroup>

## Review every profile field

Review the exact display name, bio, location, and website before approval.
Names allow 1 to 50 characters. Bios allow 160 characters. Locations allow 30
characters. Website values must be valid URLs. Empty `description` or
`location` values clear those fields. An empty `name` or invalid URL returns 400. Keep API keys and private notes outside public profiles.

| X profile text update column | Request or response source | Review rule |
| - | - | - |
| Acting X account | Request `account` | Confirm the intended profile. |
| Display name | Request `name` | Keep 1 to 50 characters. |
| Profile bio | Request `description` | Keep 160 characters or fewer. |
| Location | Request `location` | Keep 30 characters or fewer. |
| Website | Request `url` | Verify the public destination. |
| Changed fields | Exact request keys | Leave unrelated profile fields absent. |
| Idempotency key | Request header | Changed field values use another key. |
| Write action ID | Response `id` | Poll the matching lifecycle record. |

## Automate a profile update

Create one idempotency key for each account and field set. Reuse that key after
a network interruption. Workers handling the same update must share it. Change
the key after editing any value. A 200 response is terminal. Poll `statusUrl`
after 202 until `terminal` becomes true.

## Coordinate updates across connected accounts

Send one approved request for each connected X account. Give every request a
key for its exact account and field set. Wait for an account's terminal result
before starting its next profile change. Other accounts may update in parallel
with different keys.

Store the account, requested fields, request hash, write action ID, and status.
Workers use this record to avoid duplicate profile updates.
It also shows which display name, bio, location, or website each action changed.
Give different teams their own API keys. Never share credentials between
unrelated profile workflows.

## Verify the saved Twitter profile

After a terminal write, use
[Twitter Profile Lookup](/api-reference/x/twitter-profile-lookup). Compare its
name, description, location, and website with the approved request. Profile
updates never change posts, tweets, followers, replies, likes, or lists. For a
campaign, save earlier values and restore them with a new key.

Store the earlier and replacement values with the action ID. Apply the
replacement at launch, then verify the public profile. Restore earlier
fields with a new idempotency key after the campaign. With that history, you can reverse each
temporary profile update.

The write action shows the request finished. The later profile lookup
shows the public result. Save both timestamps when profile changes need an audit trail.
Never store authentication tokens with those public profile values.

## Fix Twitter profile update failures

Fix rejected fields after 400. Replace authentication after 401. Add credits
after 402. Reconnect after 403. Connect a missing account after 404. Keep the
original action after 409. Honor `Retry-After` after 429. Check `safeToRetry`
after 500 or 503.

Delete fake verification marks or unsafe profile links, then retry. X documents
more causes in its
[profile save troubleshooting guide](https://help.x.com/en/managing-your-account/cant-save-changes-to-my-account).

Do not create a new action after a network error. Check the saved
`statusUrl` before creating another action. The same request may reuse its
original idempotency key. Change the key after correcting any field. Retry a
server error only when `safeToRetry` allows it.

## Twitter API update profile questions

### What endpoint changes a Twitter display name or bio?

Send `name` or `description` to `PATCH /x/profile`. The `name` field changes
the display name, not the `@username`. An empty `description` clears the bio.

### Can I automate recurring Twitter bio changes?

Yes. Approve every replacement value. Use a new key for each scheduled change.
Check the action and public profile. Keep the earlier bio for rollback.

### Can this Twitter API change an account username?

No. The `name` field changes only the public display name. It never changes the
`@username` or numeric account ID. Keep username changes outside this workflow.

### Does a profile update change tweets or follower counts?

No. Existing tweets, replies, followers, following, likes, lists, and
communities stay unchanged. A later profile lookup may return those counts, but
this route cannot edit them.

### Can this endpoint update a profile picture or banner?

No. Use the dedicated avatar or banner route. Those endpoints validate image
type and size separately.

### Which authentication works with this Twitter API route?

Use an `x-api-key` header or an OAuth bearer token. The chosen connected X
account supplies the profile identity. Generated SDKs can send the same fields
and headers.

### How should I schedule temporary profile changes?

Check both values before adding them to the schedule. Use one key for the
launch action and a different key for the rollback. Poll each action until
terminal, then verify the public profile before continuing.

## Headers

<ParamField header="x-api-key" type="string" required>
  Your API key. OAuth bearer authentication is also supported. Generate a key from the [dashboard](https://xquik.com/dashboard).
</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>

## Body

<ParamField body="account" type="string" required>
  X username or account ID of your connected account to act as.
</ParamField>

<ParamField body="name" type="string">
  Display name. Maximum 50 characters.
</ParamField>

<ParamField body="description" type="string">
  Profile bio. Maximum 160 characters.
</ParamField>

<ParamField body="location" type="string">
  Profile location. Maximum 30 characters.
</ParamField>

<ParamField body="url" type="string">
  Website URL. Must be a valid URL.
</ParamField>

## Response

<Tabs>
  <Tab title="404 Account not found">
    Connect the requested account, then submit a newly approved write.
  </Tab>
</Tabs>

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