Skip to content
Docs

Edit the profile

Early access. Tell us what you're building and we'll set you up. Contact us

PATCHapi.lempile.com/users/me/edit

Unipile's "Edit own profile" for an X account: name, bio, location, website, avatar, banner and username, any of them (the others stay as they are). POST works too.

The browser reads X's Edit profile, gives it the pictures (through X's crop window, as is), types each field that isn't already as asked, checks the others unchanged, presses Save and reads everything back on a fresh window; the handle comes last, on X's Change username page, checked free, saved and read back. On a verified account a new name, avatar or handle removes the checkmark until X reviews it again: X asks at Save, and Lempile confirms that notice. After a new handle, Lempile's record of the account follows in the same request.

With website alone the answer is the Website edit's, as it has been since Nov 3 2026: { website, previous_website, already }, or { website, would } for a dry run.

Pictures and a handle can take a few minutes: the request waits 140 seconds, then answers 504 errors/timeout while the browser goes on (up to 10 minutes); send an Idempotency-Key and read GET /writes/{key}.

Scope: accounts.write.

Authentication

X-API-KEY header·A Lempile API key, made in the dashboard under Access tokens.

Headers

  • Idempotency-Keystring

    Optional. With a key, the write gets a receipt (GET /writes/{key}) and a repeat replays the first answer.

    ≤ 200 chars

Request body

  • account_idstringrequired

    Body only.

  • typestring
    One ofXTWITTER
  • namestring

    One line. Counted as X counts it (an emoji is 2).

    ≥ 1 chars · ≤ 50 chars
  • biostring

    Line breaks kept; "" clears it. Unipile's summary is taken too.

    ≤ 160 chars
  • locationstring

    One line; "" clears it. Words, not Unipile's LinkedIn place id.

    ≤ 30 chars
  • websitestring · uri

    One https address, a host with a dot, no spaces or credentials. It can't be emptied.

    ≤ 100 chars
  • usernamestring

    The new handle, with or without @. It comes last, on X's Change username page.

    Pattern^@?[A-Za-z0-9_]{4,15}$
  • dry_runboolean

    Reads every window and answers ProfileEditDryRun: nothing is given, typed or pressed. true or false only.

  • avatarstring · binary

    A JPEG or PNG of at most 2 MB. Unipile's picture is taken too.

  • bannerstring · binary

    The header photo: a JPEG or PNG of at most 5 MB. Unipile's cover_picture is taken too.

Responses

200

Saved and read back, or a dry run.

›

application/json

  • ProfileEditedProfileEdited
    ›Show fields
    • objectany
      AlwaysProfileEdited
    • providerany
      AlwaysX
    • account_idstring
    • changedobject

      What X keeps now, read back on fresh pages: each field changed (name, bio, location, website, avatar and banner as the addresses X serves them from, username).

    • previousobject

      What those fields were.

    • alreadyarray of string

      The fields that were already as asked (nothing typed for them). A website edit: true when the address was already set.

    • avatar_changedboolean | null
    • banner_changedboolean | null
    • usernamestring

      The handle X shows, when one was asked.

    • websitestring | null

      A website edit: the address X keeps.

    • previous_websitestring | null

      A website edit: the one before.

  • ProfileEditDryRunProfileEditDryRun
    ›Show fields
    • objectany
      AlwaysProfileEditDryRun
    • providerany
      AlwaysX
    • not_sentany
      Alwaystrue
    • currentobject

      What each field asked for shows now.

    • would_changeobject

      The fields Save would change (a picture always: "new picture").

    • alreadyarray of string
    • checksobject
      ›Show fields
      • save_buttonboolean
      • photo_inputsobject
      • username_fieldboolean
      • password_requiredboolean
    • websitestring | null

      A website dry run: the address shown now.

    • wouldstring

      A website dry run.

      One ofsetalready_set
400

errors/invalid_parameters or the browser's errors/invalid_*: a field X wouldn't take (a picture that isn't a JPEG or PNG, is empty, isn't valid base64 or is too large; a handle that isn't 4–15 letters, digits or _; dry_run that isn't true or false…). Nothing was changed.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

401

Missing or invalid API key ({error, message}), errors/disconnected_account, or errors/reauth_required when X is signed out in the account's browser.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

402

subscription_required: the workspace has no active trial or subscription.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

403

errors/password_required: X asks for the account's password to change the handle; Lempile never types it. errors/insufficient_permissions: the key lacks accounts.write.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

404

errors/resource_not_found: no such account in this workspace, or it isn't an X account.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

409

errors/username_taken: X says the handle isn't free. errors/in_progress: the same key is still running.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

422

errors/username_field_not_found (no Username field on X's Change username page, as while an X Premium check is under review), errors/username_refused, errors/username_check_failed, errors/username_not_kept, errors/profile_photo_input_not_found, errors/profile_photo_not_taken, errors/profile_field_not_found, errors/typing_failed, errors/profile_fields_changed, errors/profile_save_unavailable, errors/profile_value_not_kept (detail quotes what X said) or errors/idempotency_key_reused. A refusal after the Edit profile part was saved carries done.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

423

errors/x_account_locked: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

501

errors/feature_not_implemented: a field an X profile doesn't have, another type, or a LinkedIn account.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

502

errors/profile_unconfirmed or errors/username_unconfirmed: saved but not read back. Read the profile before trying again.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

503

errors/service_unavailable (the account isn't ready, or the browser runner can't be reached), errors/no_client_session, or errors/maintenance with retry_at.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

504

errors/timeout: still running, or not sure. Read the receipt.

›

application/problem+json

  • typestringrequired
  • titlestring
  • statusintegerrequired
  • detailstring
  • retry_atstring · date-time
  • codestring

    The browser's own reason, when it refused before the click: replies_limited, post_not_accepted, gif_not_found, browser_busy…

Was this page helpful?