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

# Language and identity

> Change a Lusor Phone's system language, the device identity apps read, and its advertising ID.

These routes change how a Lusor Phone presents itself to apps. They work on Lusor Phones only. Any other phone returns `409 not_managed_phone`.

An API key can make these changes on its own workspace. In the app, admins and members can.

## How a change is applied

Every change here works the same way:

1. The `PUT` or `POST` answers `202` at once, with `state: "pending"`.
2. Read the matching `GET` until `state` is `applied` or `failed`.

| Field | Meaning |
| - | - |
| `state` | `pending` while the change is applied, then `applied`, `failed` or `unknown`. `null` if no change was ever made. |
| `error` | Why a change did not apply. `phone_not_ready`, `phone_offline`, `task_failed` and `device_busy` mean it failed and nothing changed: send it again to retry. `task_unconfirmed` and `dispatch_unconfirmed` go with `unknown`. |
| `inProgress` | `language`, `identity` or `ad_id_reset` while one is still being applied, otherwise `null`. |

Only one change runs at a time. Another change is refused with `409 phone_busy` until it settles.

`unknown` means the phone may or may not have taken the change. Further changes are refused with `phone_busy` until support resolves it, so an irreversible advertising-ID reset is never repeated by accident. Contact support if you see it.

The values the `GET` routes report are the ones the phone was actually given. A `failed` or `unknown` change does not change them.

## Language

`PUT …/language` sets the phone's system language and, optionally, its region.

| Field | Meaning |
| - | - |
| `language` | ISO 639 language code, for example `de`. Required. |
| `country` | ISO 3166-1 two-letter region, for example `DE`. Optional. |

```bash cURL theme={null}
curl -X PUT https://api.lusor.ai/v1/workspaces/$WS/devices/$DEVICE/language \
  -H "X-Api-Key: $LUSOR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "language": "de", "country": "DE" }'
```

```python Python theme={null}
import os, time, requests

BASE = f"https://api.lusor.ai/v1/workspaces/{os.environ['WS']}/devices/{os.environ['DEVICE']}"
H = {"X-Api-Key": os.environ["LUSOR_API_KEY"]}

requests.put(f"{BASE}/language", headers=H, json={"language": "de", "country": "DE"})
while True:
    lang = requests.get(f"{BASE}/language", headers=H).json()["data"]
    if lang["state"] != "pending":
        break
    time.sleep(5)
print(lang)
```

```javascript Node.js theme={null}
const BASE = `https://api.lusor.ai/v1/workspaces/${process.env.WS}/devices/${process.env.DEVICE}`;
const H = { "X-Api-Key": process.env.LUSOR_API_KEY, "Content-Type": "application/json" };

await fetch(`${BASE}/language`, {
  method: "PUT", headers: H, body: JSON.stringify({ language: "de", country: "DE" }),
});
let lang;
do {
  await new Promise((r) => setTimeout(r, 5000));
  lang = (await (await fetch(`${BASE}/language`, { headers: H })).json()).data;
} while (lang.state === "pending");
console.log(lang);
```

The phone may restart to apply it. `GET …/language` returns `language` and `country` as last set, or `null` if none has been set.

A language change is refused with `409 phone_busy` while a session or live viewer is using the phone.

## Identity

`PUT …/identity` sets the device identity that apps read. Send only the fields you want to change. At least one is required.

| Field | Meaning | Example |
| - | - | - |
| `brand` | Brand | `google` |
| `manufacturer` | Manufacturer | `Google` |
| `model` | Model name | `Pixel 8` |
| `device` | Device codename | `shiba` |
| `name` | Product name | `shiba` |
| `fingerprint` | Build fingerprint, `brand/name/device:release/id/incremental:type/tags`, up to 200 characters | |
| `androidId` | The Android ID, 16 hex digits | |

Text fields are 1 to 64 letters, digits, spaces or `. _ + -`. Any other key, such as a raw Android system property, returns `400 identity_prop_refused`.

> [!WARNING]
>
> Once the values are written (`state: "applied"`, `restartQueued: true`), **the phone restarts** to apply them. This takes a few minutes.

The values stay through restarts and resets. To undo a change, set the old values again.

`GET …/identity` returns the latest value of each field you have set. Fields you never set keep the phone's own values and are absent.

## Advertising ID

`POST …/advertising-id/reset` gives the phone a new Google advertising ID. It takes no body.

> [!WARNING]
>
> This is irreversible. The previous ID cannot be restored.

`GET …/advertising-id` reports how the last reset ended. The ID itself is not returned.

## Errors

| Status | `error` | Meaning |
| - | - | - |
| `400` | `language_invalid`, `identity_invalid` | A value is not valid. |
| `400` | `identity_prop_refused` | A key that is not one of the identity fields. |
| `402` | `billing_required` | An advertising-ID reset on a Lusor Phone that is not covered by an active paid plan. |
| `409` | `not_managed_phone` | Not a Lusor Phone. |
| `409` | `phone_busy` | A session, a live viewer, a restart or reset, or another change holds the phone. Nothing changed. |
| `409` | `phone_not_ready` | The phone is not set up yet, or has been removed. |
| `502` | `change_outcome_unknown` | The request timed out and the change may still be applied. Read the setting before retrying. |


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