Create a new session on this device
Starts an agent run on this phone without a persistent agent.
Returns 202 Accepted { id, status: "queued" } immediately; poll
GET /v1/sessions/{id}/status or GET /v1/sessions/{id}/events
for progress.
Concurrent same-device session create returns
429 { error: 'device_busy', currentSessionId }.
curl --request POST \
--url https://api.lusor.ai/v1/workspaces/{workspaceId}/devices/{deviceId}/sessions \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--data '
{
"prompt": "<string>",
"maxDurationSecs": 2,
"recording": false,
"stealthInput": true,
"schema": {},
"app": "<string>",
"secrets": [
"<string>"
],
"model": "<string>",
"idempotencyKey": "<string>"
}
'const options = {
method: 'POST',
headers: {'X-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
prompt: '<string>',
maxDurationSecs: 2,
recording: false,
stealthInput: true,
schema: {},
app: '<string>',
secrets: ['<string>'],
model: '<string>',
idempotencyKey: '<string>'
})
};
fetch('https://api.lusor.ai/v1/workspaces/{workspaceId}/devices/{deviceId}/sessions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.lusor.ai/v1/workspaces/{workspaceId}/devices/{deviceId}/sessions"
payload = {
"prompt": "<string>",
"maxDurationSecs": 2,
"recording": False,
"stealthInput": True,
"schema": {},
"app": "<string>",
"secrets": ["<string>"],
"model": "<string>",
"idempotencyKey": "<string>"
}
headers = {
"X-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"id": "<string>",
"status": "queued",
"deviceId": "<string>",
"workspaceId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invocationId": "<string>"
}{
"error": "validation_error",
"details": {}
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "device_busy",
"currentSessionId": "<string>",
"message": "<string>"
}Authorizations
Workspace API key, created in the dashboard under Settings → API Keys.
Headers
Caller-provided key for safe retries. The same key in the same workspace yields the same run id, and a duplicate POST within the retention window returns the original run instead of starting a second one.
256Path Parameters
Workspace UUID. Caller must have access.
Device id (paired into the workspace).
Body
1 - 8192Optional cap on the run's duration, in seconds. The server applies its own upper bound.
x >= 1Record a video of the run.
Run every device action of this session in human-like (stealth)
mode: jittered tap timing, curved swipe paths and a per-key
typing delay. Refused at create with
412 unsupported_stealth_input when the phone's agent does not
support it, so a run never starts only to fail on its first tap.
Saved workspace secrets this run may use, by reference:
<item_slug>.<field>, for example gmail.password. Values are
never sent in the request; the agent types them on the phone
without the model ever seeing them. Every name must already be
saved in the workspace (GET /v1/workspaces/{workspaceId}/vault
lists them), otherwise the request fails with 422
unknown_secret. Omitted: the run may use every secret saved in
the workspace. []: none.
50256^[a-z0-9_-]+\.[a-z0-9_-]+$Provider-qualified model id for this run. Omitted, null or
auto runs the default model, deepseek/deepseek-flash.
Key for retry safety. The Idempotency-Key
header takes precedence over this body field.
256Was this page helpful?
curl --request POST \
--url https://api.lusor.ai/v1/workspaces/{workspaceId}/devices/{deviceId}/sessions \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--data '
{
"prompt": "<string>",
"maxDurationSecs": 2,
"recording": false,
"stealthInput": true,
"schema": {},
"app": "<string>",
"secrets": [
"<string>"
],
"model": "<string>",
"idempotencyKey": "<string>"
}
'const options = {
method: 'POST',
headers: {'X-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
prompt: '<string>',
maxDurationSecs: 2,
recording: false,
stealthInput: true,
schema: {},
app: '<string>',
secrets: ['<string>'],
model: '<string>',
idempotencyKey: '<string>'
})
};
fetch('https://api.lusor.ai/v1/workspaces/{workspaceId}/devices/{deviceId}/sessions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.lusor.ai/v1/workspaces/{workspaceId}/devices/{deviceId}/sessions"
payload = {
"prompt": "<string>",
"maxDurationSecs": 2,
"recording": False,
"stealthInput": True,
"schema": {},
"app": "<string>",
"secrets": ["<string>"],
"model": "<string>",
"idempotencyKey": "<string>"
}
headers = {
"X-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"id": "<string>",
"status": "queued",
"deviceId": "<string>",
"workspaceId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"invocationId": "<string>"
}{
"error": "validation_error",
"details": {}
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "device_busy",
"currentSessionId": "<string>",
"message": "<string>"
}
