Automation API

Android device automation

API Reference

REST API endpoints for automation control

These API endpoints allow you to programmatically control automations on devices. All endpoints require authentication via Bearer token in the Authorization header.

Authentication

All API requests must include an Authorization header with a valid Bearer token:

Authorization: Bearer your_api_token
POST/api/v2/devices/launchAutomation

Launch Automation

Launches a saved automation project on one or more devices. Use this to run automations that have been created and saved in the IDE.

Request Parameters

ParameterTypeRequiredDescription
device_idsstring[]YesArray of device IDs to run the automation on
automationIdstringYesThe ID of the saved automation project
commandstringYesCommand to execute: "start" or "stop"
automationParametersobjectNoParameters defined in the automation schema
jobVariablesobjectNoJob-specific variables for the automation
Example Request
JSON
{
"device_ids": ["device_123456", "device_789012"],
"automationId": "83ba7359-d8eb-4374-8ecb-055af01fddfe",
"command": "start",
"automationParameters": {
"maxRetries": 3,
"timeout": 30000
},
"jobVariables": {
"email": "user@example.com",
"password": "secret123"
}
}

Responses

200Success
JSON
{
"success": true,
"message": "Action performed successfully"
}
400Bad Request
JSON
{
"success": false,
"message": "Some devices offline or not found."
}
POST/api/v2/devices/launchDirectAutomation

Launch Direct Automation

Launches automation code directly on a device without saving it as a project. You provide a unique launch ID (UUID) to track the automation and retrieve logs.

Request Parameters

ParameterTypeRequiredDescription
device_idstringYesThe ID of the device to run automation on
launch_idstring (UUID)YesUnique identifier for this automation launch (generate a UUID)
commandstringYesCommand to execute: "start" or "stop"
codestringYesJavaScript/TypeScript code to execute on the device
automationParametersobjectNoParameters accessible via agent.arguments.automationParameters
jobVariablesobjectNoVariables accessible via agent.arguments.jobVariables
Example Request
JSON
{
"device_id": "device_123456",
"launch_id": "550e8400-e29b-41d4-a716-446655440000",
"command": "start",
"code": "console.log('Hello from automation!');",
"automationParameters": {
"maxRetries": 3
},
"jobVariables": {
"targetUrl": "https://example.com"
}
}

Responses

200Success
JSON
{
"success": true,
"message": "Action performed successfully"
}
400Bad Request
JSON
{
"success": false,
"message": "Some devices offline or not found."
}

Using the launch_id

The launch_id you provide is used to track this specific automation instance. Use this same ID when calling automationLogs to retrieve logs for this automation.

POST/api/v2/devices/stopAllAutomations

Stop All Automations

Stops all running automations on the specified device.

Request Parameters

ParameterTypeRequiredDescription
device_idstringYesThe ID of the device to stop automations on
Example Request
JSON
{
"device_id": "device_123456"
}

Responses

200Success
JSON
{
"success": true,
"message": "All automations stopped successfully"
}
400Bad Request

Invalid device_id or device not found

POST/api/v2/devices/automationLogs

Get Automation Logs

Retrieves console logs from running automations. Only returns logs from the last 10 minutes. Use the from parameter for pagination to get logs after a specific log ID.

Request Parameters

ParameterTypeRequiredDescription
device_idstringYesThe ID of the device to get logs from
automation_idsstring[]YesArray of automation IDs or launch IDs (for direct automations) to get logs for
fromstringNoLog ID to get logs after (for pagination)

automation_ids for Direct Automations

When using launchDirectAutomation, pass the launch_id you provided in the automation_ids array to retrieve logs for that specific automation.

Example Request
JSON
{
"device_id": "device_123456",
"automation_ids": ["550e8400-e29b-41d4-a716-446655440000"],
"from": "e0e1a3ef-7b2a-42b5-8f21-b845fa41c8b9"
}

Responses

200Success
JSON
{
"logs": [
{
"id": "e0e1a3ef-7b2a-42b5-8f21-b845fa41c8b9",
"automationId": "550e8400-e29b-41d4-a716-446655440000",
"message": "Processing screen content...",
"lineNumber": 42,
"messageLevel": "log",
"timestamp": 1755811585870
},
{
"id": "f1f2b4ff-8c3b-53c6-9g32-c956gb52d9ca",
"automationId": "550e8400-e29b-41d4-a716-446655440000",
"message": "Button clicked successfully",
"lineNumber": 45,
"messageLevel": "log",
"timestamp": 1755811586120
}
]
}

Log Levels

LevelDescription
logStandard console.log output
warnWarning messages from console.warn
errorError messages from console.error
PUT/api/v2/automation/file/:id

Write Project File

Creates or updates a file within an automation project. For TypeScript files, the content is automatically compiled to JavaScript.

URL Parameters

ParameterTypeDescription
idstringThe automation project ID

Request Body

ParameterTypeDescription
pathstringRelative file path within the project (e.g., main.ts, utils/helpers.ts)
contentstringThe file content (max ~50MB)
Example Request
JSON
{
"path": "main.ts",
"content": "async function main() {\n console.log('Hello!');\n stopCurrentAutomation();\n}\n\nmain();"
}

Responses

200Success
JSON
{
"success": true,
"path": "main.ts",
"compiledPath": "main.js",
"compiled": true
}
400TypeScript Compilation Error
JSON
{
"success": false,
"message": "TypeScript compilation failed",
"errors": ["Error at 5:10: Property 'foo' does not exist on type 'string'."]
}
404Not Found

Automation project not found or access denied

TypeScript Compilation

When writing .ts files, the TypeScript is automatically compiled and both the source (.ts) and compiled (.js) files are saved. You cannot directly edit .js files that have a paired .ts source.

GET/api/v2/automation/file/:id

Read Project File

Reads the content of a file within an automation project.

URL Parameters

ParameterTypeDescription
idstringThe automation project ID

Query Parameters

ParameterTypeDescription
pathstringRelative file path within the project (e.g., main.ts)
Example Request
Bash
curl "https://xgodo.com/api/v2/automation/file/83ba7359-d8eb-4374-8ecb-055af01fddfe?path=main.ts" \
-H "Authorization: Bearer your_api_token"

Responses

200Success
JSON
{
"success": true,
"content": "async function main() {\n console.log('Hello!');\n stopCurrentAutomation();\n}\n\nmain();",
"path": "main.ts"
}
404Not Found

File or automation project not found

POST/api/v2/automation/commit/:id

Commit Project Changes

Creates a new commit with all current changes in the automation project. The project must have uncommitted changes for this to succeed.

URL Parameters

ParameterTypeDescription
idstringThe automation project ID

Request Body

ParameterTypeDescription
messagestringThe commit message describing the changes (1-1000 characters)
Example Request
JSON
{
"message": "Add error handling to main automation flow"
}

Responses

201Created
JSON
{
"success": true,
"commit": {
"hash": "a1b2c3d4e5f6789012345678901234567890abcd",
"message": "Add error handling to main automation flow"
}
}
400No Changes
JSON
{
"success": false,
"message": "No changes to commit"
}
404Not Found

Automation project not found or access denied

Version Control

Each automation project has built-in version control. After making changes with the Write Project File API, use this endpoint to commit those changes. The commit hash can be used to track versions and revert if needed.

GET/api/v2/automation-project/out-of-steps

Get Out of Steps Records

Retrieves out of steps records for automations where you are the owner or a shared editor. These records contain screenshots and UI data captured when an automation encounters an unknown screen or runs out of steps. Returns one record at a time with cursor-based pagination.

Query Parameters

ParameterTypeDescription
cursorstringDirect link to a specific record by ID
before_cursorstringGet records older than this cursor (for "next" pagination)
after_cursorstringGet records newer than this cursor (for "prev" pagination)
automation_idstringFilter by automation ID
typestringFilter by type: outOfSteps, timeout, debug, crash
statusstringFilter by status: pending, solved, skipped
partialstringFilter by partial: true or false
tagstringFilter by debug tag. default also matches records without a tag. Only debug records carry non-default tags.

Responses

200Success
JSON
{
"success": true,
"result": {
"device_info": { "brand": "Samsung", "model": "Galaxy S21", ... },
"automation_name": "My Automation",
"out_of_steps_id": "507f1f77bcf86cd799439011",
"automation_id": "507f1f77bcf86cd799439012",
"type": "outOfSteps",
"status": "pending",
"screens": [
{
"_id": "507f1f77bcf86cd799439013",
"uiUrl": "https://server.com/outofsteps/2024/01/15/.../ui_....json",
"screenshot": {
"screenshotUrl": "https://server.com/outofsteps/2024/01/15/.../screenshot_....jpeg",
"compressedWidth": 540,
"compressedHeight": 1200,
"originalWidth": 1080,
"originalHeight": 2400
},
"nextStage": "main",
"screenState": "unknown",
"maxSteps": 0,
"timestamp": 1705334400000
}
],
"added": "2024-01-15T12:00:00.000Z"
},
"total": 100,
"currentPage": 1,
"currentCursor": "507f1f77bcf86cd799439011",
"hasNext": true,
"hasPrev": false
}

Screen Object Fields

  • uiUrl - Full URL to the UI JSON file containing the accessibility tree
  • screenshot.screenshotUrl - Full URL to the screenshot JPEG image
  • nextStage - The stage the automation was attempting to reach
  • screenState- The identified screen state (or "unknown")
  • maxSteps - Remaining steps when captured (0 = out of steps)
GET/api/v2/automation-project/out-of-steps/tags

List Debug Tags

Lists the distinct tags used by an automation's debug out of steps records. Debug submissions can carry a tag (default default), and the server retains the 200 most recent debug records per tag per automation. Use the returned tags with the tag filter of the Get Out of Steps Records endpoint.

Query Parameters

ParameterTypeDescription
automation_idstringAutomation whose debug tags to list (required). Must be an automation you own or can edit.

Responses

200Success
JSON
{
"success": true,
"tags": ["default", "login-flow", "checkout"]
}
403Forbidden

Automation not accessible to the caller

PATCH/api/v2/automation-project/out-of-steps/:id/status

Mark Out of Steps Status

Mark an out of steps record as solved or skipped. Only automation editors (owner or shared_editor) can mark status. Once marked, status cannot be changed.

URL Parameters

ParameterTypeDescription
idstringThe out of steps record ID

Request Body

ParameterTypeRequiredDescription
statusstringYesThe status to set: "solved" or "skipped"
Example Request
JSON
{
"status": "solved"
}

Responses

200Success
JSON
{
"success": true,
"message": "Out of steps marked as solved",
"status": "solved"
}
400Already Marked
JSON
{
"success": false,
"message": "Status already marked as \"solved\". Cannot change status once marked."
}
403Forbidden

You don't have permission to mark this out of steps record

Status is Immutable

Once a status is set to solved or skipped, it cannot be changed. Make sure you've addressed the issue before marking it.

PATCH/api/v2/automation-project/out-of-steps/:id/save

Save Out of Steps Record

Saves or unsaves an out of steps record. The server keeps only the most recent records per category (per tag for debug) and auto-deletes older ones; saved records still count toward that limit but are protected from auto-deletion for 2 monthsfrom creation — after that they are cleaned up like any other record. Only automation editors (owner or shared_editor) can toggle this, and it is reversible at any time. The record's current state is returned as the saved field by the Get Out of Steps Records endpoint.

Request Body

FieldTypeDescription
savedbooleantrue to save the record, false to unsave it (required)

Responses

200Success
JSON
{
"success": true,
"message": "Out of steps saved",
"saved": true
}
403Forbidden

You don't have permission to save this out of steps record

Usage Example

Here's a complete example of launching a direct automation and polling for logs:

Example: Launch and Monitor Direct Automation
TypeScript
const API_BASE = "https://xgodo.com";
const TOKEN = "your_api_token";
// Generate a unique launch ID
function generateUUID(): string {
return crypto.randomUUID();
}
async function runDirectAutomation(deviceId: string, code: string) {
const launchId = generateUUID();
// Launch the automation
const launchRes = await fetch(`${API_BASE}/api/v2/devices/launchDirectAutomation`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${TOKEN}`
},
body: JSON.stringify({
device_id: deviceId,
launch_id: launchId,
command: "start",
code: code,
automationParameters: { maxRetries: 3 },
jobVariables: { targetUrl: "https://example.com" }
})
});
const launchData = await launchRes.json();
if (!launchData.success) {
throw new Error(launchData.message);
}
console.log("Automation started with launch ID:", launchId);
// Poll for logs using the launch_id
let lastLogId: string | undefined;
const pollLogs = async () => {
const logsRes = await fetch(`${API_BASE}/api/v2/devices/automationLogs`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${TOKEN}`
},
body: JSON.stringify({
device_id: deviceId,
automation_ids: [launchId], // Use launch_id here
from: lastLogId
})
});
const logsData = await logsRes.json();
for (const log of logsData.logs) {
console.log(`[${log.messageLevel}] ${log.message}`);
lastLogId = log.id;
}
};
// Poll every 2 seconds
const interval = setInterval(pollLogs, 2000);
// Stop after 60 seconds
setTimeout(async () => {
clearInterval(interval);
// Stop the automation
await fetch(`${API_BASE}/api/v2/devices/stopAllAutomations`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${TOKEN}`
},
body: JSON.stringify({ device_id: deviceId })
});
console.log("Automation stopped");
}, 60000);
}
// Usage
runDirectAutomation("device_123456", `
const params = agent.arguments.automationParameters;
const vars = agent.arguments.jobVariables;
console.log("Max retries:", params.maxRetries);
console.log("Target URL:", vars.targetUrl);
await agent.actions.goHome();
console.log("Done!");
stopCurrentAutomation();
`);

Error Handling

401 Unauthorized

The API token is missing, invalid, or expired. Ensure you're passing a valid Bearer token in the Authorization header.

400 Bad Request

The request parameters are invalid or missing. Check that all required fields are provided with correct types.

Device Offline

The target device is not connected. Ensure the device is online and has the Xgodo app running before launching automations.