Edit the profile
Early access. Tell us what you're building and we'll set you up. Contact us
api.lempile.com/users/me/editUnipile'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-KeystringOptional. With a key, the write gets a receipt (
GET /writes/{key}) and a repeat replays the first answer.≤ 200 chars
Request body
account_idstringrequiredBody only.
typestringOne ofXTWITTERnamestringOne line. Counted as X counts it (an emoji is 2).
≥ 1 chars · ≤ 50 charsbiostringLine breaks kept;
""clears it. Unipile'ssummaryis taken too.≤ 160 charslocationstringOne line;
""clears it. Words, not Unipile's LinkedIn place id.≤ 30 charswebsitestring · uriOne https address, a host with a dot, no spaces or credentials. It can't be emptied.
≤ 100 charsusernamestringThe new handle, with or without
@. It comes last, on X's Change username page.Pattern^@?[A-Za-z0-9_]{4,15}$dry_runbooleanReads every window and answers
ProfileEditDryRun: nothing is given, typed or pressed.trueorfalseonly.avatarstring · binaryA JPEG or PNG of at most 2 MB. Unipile's
pictureis taken too.bannerstring · binaryThe header photo: a JPEG or PNG of at most 5 MB. Unipile's
cover_pictureis taken too.
account_idstringrequiredBody only.
typestringOne ofXTWITTERnamestringOne line. Counted as X counts it (an emoji is 2).
≥ 1 chars · ≤ 50 charsbiostringLine breaks kept;
""clears it. Unipile'ssummaryis taken too.≤ 160 charslocationstringOne line;
""clears it. Words, not Unipile's LinkedIn place id.≤ 30 charswebsitestring · uriOne https address, a host with a dot, no spaces or credentials. It can't be emptied.
≤ 100 charscustom_linkobjectUnipile's form of
website; must match it when both are given.›Show fieldsHide fields
urlstringtypeanyAlwaysWEBSITE
usernamestringThe new handle, with or without
@. It comes last, on X's Change username page.Pattern^@?[A-Za-z0-9_]{4,15}$dry_runbooleanReads every window and answers
ProfileEditDryRun: nothing is given, typed or pressed.trueorfalseonly.avatarProfilePicture›Show fieldsHide fields
namestringcontent_typestringOptional: the type is read from the file's bytes.
One ofimage/jpegimage/pngdata_base64stringrequiredThe file's bytes in base64, no
data:prefix.
bannerProfilePicture›Show fieldsHide fields
namestringcontent_typestringOptional: the type is read from the file's bytes.
One ofimage/jpegimage/pngdata_base64stringrequiredThe file's bytes in base64, no
data:prefix.
Responses
200Saved and read back, or a dry run.
›
application/json
ProfileEditedProfileEdited›Show fieldsHide fields
objectanyAlwaysProfileEditedprovideranyAlwaysXaccount_idstringchangedobjectWhat X keeps now, read back on fresh pages: each field changed (
name,bio,location,website,avatarandbanneras the addresses X serves them from,username).previousobjectWhat those fields were.
alreadyarray of stringThe fields that were already as asked (nothing typed for them). A website edit:
truewhen the address was already set.avatar_changedboolean | nullbanner_changedboolean | nullusernamestringThe handle X shows, when one was asked.
websitestring | nullA website edit: the address X keeps.
previous_websitestring | nullA website edit: the one before.
ProfileEditDryRunProfileEditDryRun›Show fieldsHide fields
objectanyAlwaysProfileEditDryRunprovideranyAlwaysXnot_sentanyAlwaystruecurrentobjectWhat each field asked for shows now.
would_changeobjectThe fields Save would change (a picture always:
"new picture").alreadyarray of stringchecksobject›Show fieldsHide fields
save_buttonbooleanphoto_inputsobjectusername_fieldbooleanpassword_requiredboolean
websitestring | nullA website dry run: the address shown now.
wouldstringA website dry run.
One ofsetalready_set
400errors/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.
›
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
typestringrequiredtitlestringstatusintegerrequireddetailstringretry_atstring · date-timecodestringThe browser's own reason, when it refused before the click:
replies_limited,post_not_accepted,gif_not_found,browser_busy…
401Missing or invalid API key ({error, message}), errors/disconnected_account, or errors/reauth_required when X is signed out in the account's browser.
›
{error, message}), errors/disconnected_account, or errors/reauth_required when X is signed out in the account's browser.application/problem+json
typestringrequiredtitlestringstatusintegerrequireddetailstringretry_atstring · date-timecodestringThe browser's own reason, when it refused before the click:
replies_limited,post_not_accepted,gif_not_found,browser_busy…
402subscription_required: the workspace has no active trial or subscription.
›
subscription_required: the workspace has no active trial or subscription.application/problem+json
typestringrequiredtitlestringstatusintegerrequireddetailstringretry_atstring · date-timecodestringThe browser's own reason, when it refused before the click:
replies_limited,post_not_accepted,gif_not_found,browser_busy…
403errors/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.
›
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
typestringrequiredtitlestringstatusintegerrequireddetailstringretry_atstring · date-timecodestringThe browser's own reason, when it refused before the click:
replies_limited,post_not_accepted,gif_not_found,browser_busy…
404errors/resource_not_found: no such account in this workspace, or it isn't an X account.
›
errors/resource_not_found: no such account in this workspace, or it isn't an X account.application/problem+json
typestringrequiredtitlestringstatusintegerrequireddetailstringretry_atstring · date-timecodestringThe browser's own reason, when it refused before the click:
replies_limited,post_not_accepted,gif_not_found,browser_busy…
409errors/username_taken: X says the handle isn't free. errors/in_progress: the same key is still running.
›
errors/username_taken: X says the handle isn't free. errors/in_progress: the same key is still running.application/problem+json
typestringrequiredtitlestringstatusintegerrequireddetailstringretry_atstring · date-timecodestringThe browser's own reason, when it refused before the click:
replies_limited,post_not_accepted,gif_not_found,browser_busy…
422errors/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.
›
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
typestringrequiredtitlestringstatusintegerrequireddetailstringretry_atstring · date-timecodestringThe browser's own reason, when it refused before the click:
replies_limited,post_not_accepted,gif_not_found,browser_busy…
423errors/x_account_locked: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.
›
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
typestringrequiredtitlestringstatusintegerrequireddetailstringretry_atstring · date-timecodestringThe browser's own reason, when it refused before the click:
replies_limited,post_not_accepted,gif_not_found,browser_busy…
501errors/feature_not_implemented: a field an X profile doesn't have, another type, or a LinkedIn account.
›
errors/feature_not_implemented: a field an X profile doesn't have, another type, or a LinkedIn account.application/problem+json
typestringrequiredtitlestringstatusintegerrequireddetailstringretry_atstring · date-timecodestringThe browser's own reason, when it refused before the click:
replies_limited,post_not_accepted,gif_not_found,browser_busy…
502errors/profile_unconfirmed or errors/username_unconfirmed: saved but not read back. Read the profile before trying again.
›
errors/profile_unconfirmed or errors/username_unconfirmed: saved but not read back. Read the profile before trying again.application/problem+json
typestringrequiredtitlestringstatusintegerrequireddetailstringretry_atstring · date-timecodestringThe browser's own reason, when it refused before the click:
replies_limited,post_not_accepted,gif_not_found,browser_busy…
503errors/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.
›
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
typestringrequiredtitlestringstatusintegerrequireddetailstringretry_atstring · date-timecodestringThe browser's own reason, when it refused before the click:
replies_limited,post_not_accepted,gif_not_found,browser_busy…
504errors/timeout: still running, or not sure. Read the receipt.
›
errors/timeout: still running, or not sure. Read the receipt.application/problem+json
typestringrequiredtitlestringstatusintegerrequireddetailstringretry_atstring · date-timecodestringThe browser's own reason, when it refused before the click:
replies_limited,post_not_accepted,gif_not_found,browser_busy…
Was this page helpful?