Xgodo API Documentation

API Reference for Jobs, Tasks, Payments, and User Management

LLM / automated agent notice: a complete, plain-text reference of every v2 Client API endpoint and the automation agent docs — generated from the same source as these pages — is available at /docs/llm.txt. Prefer that single file over fetching each section page individually; it is both smaller and easier to parse.

Authentication

Bearer Token Authentication

All API endpoints require authentication using a Bearer token. Include the following header in your requests:

Authorization: Bearer <your_access_token>

Jobs API

Manage job postings, retrieve applicants, and handle job-related operations.

POST/api/v2/jobs/applicants
Retrieve job applicants

Retrieves a list of job applicants for a specified job. Allows for sorting, pagination, and searching within job applicants.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
job_idstringYesThe ID of the job for which to retrieve applicants-
task_idstringNoThe ID of the job task or planned task. Accepts either a job_task_id or planned_task_id - if a planned_task_id is provided, it will be resolved to its associated job_task_id. Used when only one task details is needed. If present, the task result list array will contain only one task or empty array if task not found.-
sortbystringNoField by which to sort job applicants-
orderstringNoSort order. Can be 'asc' for ascending or 'desc' for descendingasc
pageintegerNoPage number for pagination1
limitintegerNoNumber of applicants per page10
hours_agointegerNoThe day interval, specified as the number of days starting from the given hours_ago up to today10
statusstringNoThe status of the task ('processing', 'confirmed', 'notcomplete', 'declined', 'pending')confirmed
searchstringNoSearch term to filter applicants based on worker name, job proof, job title, comment, or worker IPdeveloper

Responses

Status CodeDescriptionResponse Body
200Successfully retrieved job applicantsReturns job details with applicant information including planned_task, job tasks, total tasks, job done count, pending tasks, satisfied tasks, declined tasks, and failed tasks
400Invalid request data or planned task exists but has no associated job task{"error": "Invalid task_id format"} or {"error": "Planned task {id} exists but has no associated job task (job_task_id is null)"}
404Job not found, task_id is neither a valid job task ID nor a planned task ID{"error": "Job with this Id not found"} or {"error": "task_id {id} is neither a valid job task ID nor a planned task ID"}
PUT/api/v2/jobs/applicants
Update job applicants' task statuses

Updates the status of specified job tasks. It supports changing the status, adding comments, and handles referral bonuses if the task is confirmed.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
JobTasks_IdsarrayYesAn array of job task IDs or planned task IDs to be updated. Accepts a mix of job_task_ids and planned_task_ids - planned task IDs will be resolved to their associated job_task_ids.["60d21b4667d0d8992e610c85", "60d21b4667d0d8992e610c86"]
statusstringYesThe new status to set for the job tasksconfirmed
job_idstringYesThe ID of the job to which the tasks belong60d21b4667d0d8992e610c85
commentstringNoOptional comment to add regarding the task updateTask successfully completed.

Responses

Status CodeDescriptionResponse Body
200Successfully updated job task statuses.Returns the updated job task details
400Bad request. Invalid input data, invalid status provided, or planned task exists but has no associated job task.{"error": "Invalid status..."} or {"error": "Planned task {id} exists but has no associated job task (job_task_id is null)"}
404Job or job tasks not found, or ID is neither a valid job task ID nor a planned task ID.{"error": "Job Task with this Id not found"} or {"error": "ID {id} is neither a valid job task ID nor a planned task ID"}
GET/api/v2/jobs/details
Get job details by ID

Returns job details for a specific job ID. When the job is linked to an automation (`automation_id` is set), the response also includes the automation's `automation_parameters_schema`, `job_variables_schema`, and `bucket_schema` so callers can validate / build UIs around the `automationParameters`, `jobVariables`, and bucket payloads accepted by the automation. Each schema follows the `IInputSchema` shape (`{ fields: IFieldSchema[] }`) and is `null` when the automation has no schema configured or the job has no linked automation.

Query Parameters

ParameterTypeRequiredDescriptionExample
job_idstringNoUnique identifier for the job68910c4a5e1c7092a1fdc03a

Example Response

{
  "_id": "68910c4a5e1c7092a1fdc03a",
  "job_id": "68910c4a5e1c7092a1fdc03a",
  "job_type": "devices_automation",
  "payment_type": "action",
  "title": "Create a Google account",
  "category": ["Google"],
  "description": "Create a Google account. ...",
  "proof": "Google account email. ...",
  "Target_Workers": ["worldwide"],
  "few_times": true,
  "premium": false,
  "featured": false,
  "duration": "3",
  "positions": "3",
  "job_price": 0.06,
  "price": "0.30",
  "status": "active",
  "files": [...],
  "added": "2025-08-04T19:38:50.204Z",
  "user": {...},
  "totla_tasks_count": 1,
  "tasks_done_count": 0,
  "tasks_confirmed_count": 0,
  "tasks_running_count": 0,
  "tasks_pending_count": 0,
  "automation_id": "83ba7359-d8eb-4374-8ecb-055af01fddfe",
  "automation_parameters_schema": {
    "fields": [
      { "name": "maxRetries", "type": "number", "required": false, "min": 1, "max": 10 }
    ]
  },
  "job_variables_schema": {
    "fields": [
      { "name": "email", "type": "string", "required": true },
      { "name": "password", "type": "string", "required": true }
    ]
  },
  "bucket_schema": {
    "fields": [
      { "name": "sessionToken", "type": "string", "required": false }
    ]
  }
}
POST/api/v2/jobs/check-uniquenes
Check for uniqueness of job proofs

This endpoint checks if a given search term exists in the job proofs. You can specify the search option to look for exact words or substrings.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
searchstringYesThe term to search for in job proofsdeveloper
optionstringNoThe search option to use. Can be "word" for exact word matching or "charactor" for substring matchingword

Responses

Status CodeDescriptionResponse Body
200Successfully checked for uniquenessReturns a boolean indicating if the search term is unique
400Bad request. Either the search term is missing, or an invalid search option is providedError message describing the validation error
POST/api/v2/jobs/myjobs
Retrieve a list of jobs that you have posted

This endpoint allows a user to retrieve a paginated list of jobs associated with their account. The results can be filtered and sorted based on various parameters.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
pageintegerNoPage number for pagination1
limitintegerNoNumber of items per page10
job_idstringNoFilter jobs by a specific job ID-
statusstringNoFilter jobs by status (e.g., 'active', 'completed')-
orientationstringNoThe orientation for the data sorting (e.g., 'asc' or 'desc')asc
QuerystringNoSearch query for job title or description-
SortBYstringNoField to sort the results by-
POST/api/v2/jobs/submit
Create a new job posting

This endpoint allows users to create a new job posting. It requires specific details about the job, including title, description, category, number of positions, job price, and duration.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
titlestringYesThe title of the job postingSoftware Developer
categorystringYesCategory of the jobEngineering
descriptionstringYesDetailed description of the jobWe are looking for a skilled software developer...
proofstringYesProof or evidence related to the job postingSample proof text.
is_proof_filebooleanNoIndicates if the proof is a file or textfalse
auto_ratebooleanNoWhether the job should be automatically ratedtrue
vcodestringNoVerification code for the job postingcdcdc
Target_WorkersarrayNoList of target workers or countries["worldwide"]
few_timesbooleanNoIndicates if the job can be posted a few timesfalse
premiumbooleanNoIndicates if the job is premiumfalse
featuredbooleanNoWhether the job is featured or notfalse
durationintegerYesDuration for which the job is posted (in days)60
positionsintegerYesNumber of available positions for the job3
daily_limitintegerNoDaily limit for the job posting0
job_pricenumberYesPrice for posting the job100

Responses

Status CodeDescriptionResponse Body
201Job created successfullySuccess message indicating job creation
400Bad request. Invalid or missing required fieldsList of validation error messages
PUT/api/v2/jobs/update-status
Update job status

Updates the status of a specific job.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
job_idstringYesThe ID of the job60c72b2f9b1e8c001c8e4d8a
statusstringYesNew status for the job (active, inactive)active

Responses

Status CodeDescriptionResponse Body
204Job status updated successfully-
400Invalid request body or status-
401Unauthorized action-
404Job not found or invalid job_id-

Tasks API

Manage job tasks, apply for tasks, and submit task completions.

GET/api/v2/tasks/apply
Apply for task submission to a job

This API must be called before tasks/submit API for jobs that have job variables. This endpoint allows workers to apply to an active job. Job variables (if any) will be returned.

Query Parameters

ParameterTypeRequiredDescriptionExample
job_idstringYesUnique identifier for the job68868530c189957861cd698a

Example Response

{
  "_id": "68910c4a5e1c7092a1fdc03c",
  "var1": "Custom variable value 1",
  "var2": "Custom variable value 2"
}
POST/api/v2/tasks/details
Get recent tasks or details of a specific job task

Returns the list of recent tasks of the user. If task_id query param is provided, it will return details of a single task.

Query Parameters

ParameterTypeRequiredDescriptionExample
task_idstringNoThe ID of the job task to fetch details for686f668db9c27eea026e60c7

Request Body Parameters

ParameterTypeRequiredDescriptionExample
pageintegerNoPage number for pagination (starts from 1)1
limitintegerNoNumber of tasks to return per page10

Example Response

{
  "_id": "686f668db9c27eea026e60c7",
  "job_task_id": "686f668db9c27eea026e60c7",
  "worker_id": "676d3525e618d4ad99dae7ff",
  "job_id": "686f44cf8abf68ace53ebc8f",
  "job_title": "Create a Google account",
  "job_price": 0.06,
  "job_proof": "",
  "comment": "",
  "country_code": "IN",
  "worker_ip": "192.168.249.223",
  "status": "confirmed",
  "failureReason": null,
  "reviewed": null,
  "device_owner_share": null,
  "added": "2025-07-10T07:06:53.631Z",
  "updated": "2025-07-10T07:06:53.631Z",
  "proof_files_info": []
}
POST/api/v2/tasks/submit
Submit a task to a job

Submits a task to an active job. The endpoint operates in one of two modes selected by the target job: 1. Manual mode (default) — for regular jobs. Honors job-level gates (worker rating, country, allowed_workers, premium, few_times, custom_vars, predeclared file fields, positions, task_limit, Worker_Invites) and triggers task/job completion emails. 2. Automation data-dump mode — selected automatically when the target job is of type devices_automation, has automation_id set, and has no planned tasks. Used by an automation agent running another job to write structured data into a separate sink job. In this mode the endpoint: • requires the caller's token to carry job_task_id and remote_device_id (i.e. a running agent token); • requires job_proof to be valid JSON; • accepts files in the {name, extension, base64Data} shape, embedded into the JSON proof under proof[name]; • accepts an explicit status of "pending" (default), "failed", or "declined"; • derives device_id and the device-owner share from the agent's remote_device_id; • authorizes by requiring the running agent's parent job and the target data-dump job to share the same automation_id, AND the running job's owner to be the target job's owner or to appear in the target's shared_view / shared_edit; • skips manual-mode gates (rating/country/few_times/custom_vars/proof_files/positions/task_limit/Worker_Invites) and skips completion emails; • does not update automation iteration / success-rate / blacklist analytics — those are reserved for "real" agent-driven tasks created by the automation engine.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
job_idstringYesID of the job. The endpoint runs in one of two modes depending on the target job: "manual" mode for regular jobs, or "automation data-dump" mode when the target job is of type devices_automation with automation_id set and no planned tasks.68868530c189957861cd698a
job_proofstringYesProof of the task done. In automation data-dump mode this string MUST be valid JSON.irjfoirf@gmail.com:iejowiedj:ehiuehwd@outlook.com:wuehuidhewd
custom_varsobjectNoManual mode only. Custom vars obtained from tasks/apply. Required for jobs with variables.{"_id": "68910c4a5e1c7092a1fdc03c", "var1": "value1"}
proof_files_base64arrayNoManual mode only. Array of required and optional proof files in base64 format, mapped to the job's predeclared file fields.[{"fieldName": "screenshot", "fileName": "image.jpg", "base64": "..."}]
statusstringNoAutomation data-dump mode only. One of "pending", "failed", or "declined". Defaults to "pending".pending
filesarrayNoAutomation data-dump mode only. Files to attach to the submission. Each file is written to disk and its public URL is embedded into the JSON job_proof under the key matching `name`. Each base64Data is capped at 5 MB.[{"name": "screenshot", "extension": ".png", "base64Data": "..."}]

Responses

Status CodeDescriptionResponse Body
201Job task submitted successfullySuccess message indicating task submission, job task id and job id
400Bad request — e.g. job_proof is not a string, or in automation data-dump mode job_proof is not valid JSON / files validation failed.Error message describing the validation failure
403Forbidden. Returned for automation data-dump submissions when the caller is not a running agent (token must carry remote_device_id and job_task_id), the agent has no currently-running task, the running job and target job do not share the same automation_id, or the running job's owner has no access (owner / shared_view / shared_edit) to the target data-dump job.Error message describing the authorization failure
404Job not found, running task's job not found, or device not foundError message indicating the missing resource
GET/api/v2/planned_tasks
List unassigned planned tasks for a job

Returns planned tasks for a job that have not yet been assigned to a job task (i.e. job_task_id is null). Supports search, pagination, and sort order. Only the job owner (or a user the job is shared with) can list its planned tasks.

Query Parameters

ParameterTypeRequiredDescriptionExample
job_idstringYesThe ID of the job whose planned tasks should be listed60c72b2f9b1e8c001c8e4d8a
searchstringNoCase-insensitive substring match against the planned task input (max 10,000 chars)john@example.com
pageintegerNoPage number for pagination (starts from 1). Defaults to 11
limitintegerNoNumber of planned tasks to return per page (1-100). Defaults to 1010
sortOrderstringNoSort order by creation time. One of "asc" or "desc". Defaults to "desc"desc

Responses

Status CodeDescriptionResponse Body
200Planned tasks (unassigned) fetched successfully. Only tasks whose job_task_id is null are returned.{"success": true, "data": {"job": {...}, "plannedTasks": [{"planned_task_id": "...", "job_id": "...", "input": "...", "added": "..."}], "total": 42}}
400Bad request - Invalid query parameters{"success": false, "error": "Invalid job id"}
404Job not found or user doesn't own the job{"success": false, "error": "Job not found"}
500Internal server error{"success": false, "message": "Internal Server Error"}
POST/api/v2/planned_tasks/submit
Submit planned tasks for a job

This endpoint allows users to submit multiple planned tasks for a specific job. Planned tasks are pre-defined inputs that will be used when workers apply for the job.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
job_idstringYesThe ID of the job to submit planned tasks for60c72b2f9b1e8c001c8e4d8a
inputsarrayYesArray of input strings for planned tasks (usually JSON strings, minimum 1, maximum 10,000 characters per string)["{\"fname\":\"John\",\"lname\":\"Doe\",\"email\":\"john@example.com\"}", "{\"fname\":\"Jane\",\"lname\":\"Smith\",\"email\":\"jane@example.com\"}"]
remote_device_idstring (UUID v4)NoOptional device ID to pin all submitted tasks to a specific device. When set, the system will only assign these tasks to the specified device. If the device is not available, the task will be retried later.a1b2c3d4-e5f6-7890-abcd-ef1234567890
device_namestringNoOptional device name (system-generated, two-word labels like "Atomic Mammal" or "Enormous Elephant") to pin all submitted tasks to a specific device. Resolved to a remote_device_id server-side. Ignored when remote_device_id is also provided. If the name matches more than one device, the request fails with 400 — use remote_device_id to disambiguate.Atomic Mammal
run_immediatelybooleanNoIf true, the system will attempt to assign the planned tasks immediately after creation (up to 3 attempts, 5 seconds apart). The response will include assignment_results indicating whether each task was assigned. Defaults to false.true

Responses

Status CodeDescriptionResponse Body
200Planned tasks submitted successfully. When run_immediately is true, includes assignment_results.{"success": true, "inserted_ids": [{"planned_task_id": "60c72b2f9b1e8c001c8e4d8a", "input": "{\"fname\":\"John\",\"email\":\"john@example.com\"}"}], "assignment_results": [{"planned_task_id": "60c72b2f9b1e8c001c8e4d8a", "assigned": true}]}
400Bad request - Invalid input data, exceeds available positions, or validation errors{"success": false, "error": "Invalid job id"} or {"success": false, "message": "No enough positions left. Received X tasks in excess."}
404Job not found or user doesn't own the job{"success": false, "error": "Job not found"}
500Internal server error{"success": false, "message": "Internal Server Error"}
DELETE/api/v2/tasks/delete
Delete a job task by ID

This endpoint allows employers to delete a job task. Accepts either a job_task_id or planned_task_id. Only tasks with certain statuses can be deleted to maintain data integrity (failed, declined, confirmed). When deleting via a planned_task_id, the planned task is preserved (with job_task_id set to null) so it can be reused, while only the job task is deleted.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
task_idstringYesThe ID of the job task or planned task to delete. Accepts either a job_task_id or planned_task_id - if a planned_task_id is provided, it will be resolved to its associated job_task_id. When using a planned_task_id, the planned task is preserved (with job_task_id set to null) while the job task is deleted.60c72b2f9b1e8c001c8e4d8a

Responses

Status CodeDescriptionResponse Body
200Job task deleted successfully. If resolved from a planned_task_id, the planned task is preserved with job_task_id set to null.{"success": true, "message": "Job task deleted successfully"}
400Bad request - Invalid task ID, task cannot be deleted due to status restrictions, or planned task exists but has no associated job task{"success": false, "error": "Invalid task id"} or {"success": false, "message": "Cannot delete job task with status 'confirmed'. Only tasks with status: failed, declined can be deleted."} or {"success": false, "error": "Planned task {id} exists but has no associated job task (job_task_id is null)"}
403Forbidden - User doesn't have permission to delete this job task{"success": false, "message": "You don't have permission to delete this job task"}
404Job task not found, or task_id is neither a valid job task ID nor a planned task ID{"success": false, "message": "Job task not found"} or {"success": false, "error": "task_id {id} is neither a valid job task ID nor a planned task ID"}
500Internal server error{"success": false, "message": "Internal Server Error"}
DELETE/api/v2/planned_tasks
Delete one or more planned tasks

Deletes unassigned planned tasks by their IDs. Planned tasks already assigned to a pending or successful job task cannot be deleted — reinitiate or delete the job task first. All IDs must belong to jobs owned by (or shared with edit permission to) the caller.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
planned_task_idsstring[]YesArray of planned task IDs to delete (minimum 1). A planned task that is already assigned to a pending or successful job task cannot be deleted.["60c72b2f9b1e8c001c8e4d8a", "60c72b2f9b1e8c001c8e4d8b"]

Responses

Status CodeDescriptionResponse Body
200Planned tasks deleted successfully{"success": true}
400Bad request - Invalid planned task id, or one of the planned tasks is already assigned to a pending/successful job task{"success": false, "message": "Cannot delete a planned task that is assigned to a pending / successful job task"}
404One or more planned tasks not found, or the job is not owned by the caller{"success": false, "message": "Planned task not found"}
500Internal server error{"success": false, "message": "Internal Server Error"}
POST/api/v2/planned_tasks/reinitiate
Re-initiate failed/declined tasks

This endpoint allows employers to re-initiate one or more failed or declined tasks. Accepts either a single task_id or an array of task_ids. This makes the planned tasks available again for workers to apply.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
task_idstringNoThe ID of a single job task to re-initiate (for backward compatibility)60c72b2f9b1e8c001c8e4d8a
task_idsstring[]NoAn array of job task IDs to re-initiate. Either task_id or task_ids must be provided.["60c72b2f9b1e8c001c8e4d8a", "60c72b2f9b1e8c001c8e4d8b"]

Responses

Status CodeDescriptionResponse Body
200Task re-initiated successfully{"success": true, "message": "Task successfully reinitiated"}
400Bad request - Invalid task ID or task cannot be reinitiated due to status restrictions{"success": false, "error": "Invalid task id"} or {"success": false, "message": "Cannot reinitiate task with status 'confirmed'. Only failed or declined tasks can be reinitiated."}
403Forbidden - User doesn't have permission to reinitiate this task{"success": false, "message": "You don't have permission to reinitiate this task"}
404Job task not found or no planned task associated with this job task{"success": false, "message": "Job task not found"}
500Internal server error{"success": false, "message": "Internal Server Error"}

Payments API

Handle payment operations including withdrawals.

POST/api/v2/payments/withdraw
Withdraw user balance

Initiate a withdrawal to a wallet address.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
amountnumberYesAmount to withdraw10
wallet_addressstringYesWallet address to receive the withdrawal0x1234567890abcdef

Responses

Status CodeDescriptionResponse Body
200Withdrawal successful{"msg": "withdraw done"}
400Insufficient balance, below minimum payout, or invalid requestError message with specific reason
401Unauthorized or missing token-
500Server error-
GET/api/v2/payments/withdrawals
Get recent withdrawal details

Returns the list & details of recent withdrawals made by the user.

Query Parameters

ParameterTypeRequiredDescriptionExample
pageintegerNoPage number for pagination (starts from 1)1
limitintegerNoNumber of withdrawals to return per page10

Responses

Status CodeDescriptionResponse Body
200Details of the withdrawals made by the user-
401Unauthorized or missing token-
404No transactions found-
500Server error-

Example Response

{
  "total_count": 3,
  "transactions": [
    {
      "_id": "67d9f0b57131be1625d301c4",
      "reference_id": "26795145",
      "user_id": "676d3619e618d4ad99dae899",
      "recipient_id": null,
      "crypto_uuid": null,
      "payment_type": "Withdrawal",
      "payment_method": "cryptomus",
      "payment_details": "",
      "transaction_fee": "0",
      "currency": "USD",
      "amount": "-10",
      "wallet_address": "2w",
      "status": "paid",
      "reason": null,
      "created": "2025-03-18T22:16:21.895Z",
      "updated": "2025-03-18T22:16:21.895Z",
      "process_date": "2025-03-18T22:16:21.895Z",
      "transaction_id": "67d9f0b57131be1625d301c4",
      "transaction_proof": "2ca560b36dcdd7c8",
      "__v": 0
    }
  ],
  "page": 1,
  "balance": 3.54,
  "total_withdraw": -30,
  "total_deposit": 0
}

User API

User account management and balance information.

GET/api/v2/user/balance
Get user balance

Returns the user's current balance, active balance and pending earnings.

Responses

Status CodeDescriptionResponse Body
200User balance information retrieved successfully-
401Unauthorized or missing token-
500Server error-

Example Response

{
  "balance": 4.434,
  "active_balance": 4.434,
  "pending_earnings": 1.25
}

Devices API

Device management and information retrieval endpoints.

GET/api/v2/devices
Get debuggable devices

Retrieves a list of devices that are either owned by the user or rented with live payment type.

Responses

Status CodeDescriptionResponse Body
200Successfully retrieved devices list-
401Unauthorized or missing token-
500Server error-

Example Response

[
  {
    "remote_device_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "added": "2025-08-19T10:00:00Z",
    "automations": [],
    "brand": "Samsung",
    "country": "US",
    "isEmulator": false,
    "model": "Galaxy S21",
    "name": "Atomic Mammal",
    "networkType": "wifi",
    "numberOfCores": 8,
    "online": true,
    "processor": "Snapdragon 888",
    "ramMb": 8192,
    "sdkVersion": "31",
    "version": "12"
  }
]
GET/api/v2/devices/market
List market devices (action / online)

Returns devices that are listed on the market with payment_type 'action' and currently online. Each item includes the device name, country, and an isAvailable flag (false when the device has at least one job task in 'running' status, true otherwise). Results can be filtered by country and are sorted by country.

Query Parameters

ParameterTypeRequiredDescriptionExample
countrystringNoFilter devices by country.US
sortDirectionstringNoSort direction for the country field. "asc" or "desc". Defaults to "asc".asc

Responses

Status CodeDescriptionResponse Body
200Successfully retrieved the list of online, action-payment market devices.-
401Unauthorized or missing token-
500Server error-

Example Response

[
  {
    "name": "Atomic Mammal",
    "country": "BR",
    "isAvailable": true
  },
  {
    "name": "Enormous Elephant",
    "country": "US",
    "isAvailable": false
  }
]
GET/api/v2/devices/verified-phone-number
Get the device's verified phone number

Agent-scoped endpoint. Identifies the device from the automation agent token and returns the phone number stored on the device record only when phoneNumberVerified is true. Returns null otherwise. Backs `agent.info.getVerifiedPhoneNumber` in the automation bootstrap.

Responses

Status CodeDescriptionResponse Body
200Returns the verified phone number stored on the device record, or null when the device has no verified phone number.-
400Token is not bound to a device (e.g. user-scoped token rather than an automation agent token).-
401Unauthorized or missing token-
404Device not found-
500Server error-

Example Response

{
  "phoneNumber": "+14155550123"
}

Proxy API

Manage SOCKS5/HTTP proxy credentials. A connection is one credential pair (`connectionId` + `password`) routed through one of your devices. Re-pointing the association to a different device is the IP-rotation primitive — new sessions exit through the new device within ~100 ms; in-flight sessions stay on the old device until they close. Endpoints are scoped to devices the caller owns; the admin endpoint requires the admin token.

POST/api/v2/devices/connections/list
List my connections

All connections owned by, or currently routed through, devices the caller owns. The `password` is plaintext — RMS owns the credential.

Responses

Status CodeDescriptionResponse Body
200All connections owned by, or routed through, devices the caller owns.-
401Missing or invalid API token.-

Example Response

{
  "success": true,
  "connections": [
    {
      "connectionId": "afac150b-951c-449b-918c-3b67fbd83a24",
      "password": "p9F7bX3cVqLtZmK2",
      "ownerUserId": "add02036-6754-4cf7-8432-cc28be4468f0",
      "name": "client-A",
      "createdAt": "2026-04-25T13:22:11Z",
      "deviceId": "add02036-6754-4cf7-8432-cc28be4468f0"
    }
  ]
}
POST/api/v2/devices/connections/create
Create a connection

Generates a fresh `connectionId` (UUID) and 16-char password, associates it with the chosen device, and syncs to the orchestrator + legacy mirror. The plaintext password is in the response — save it now.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
device_idstring (UUID — `remote_device_id`)YesOwned device id.-
namestringNoOptional human label (≤ 100 chars). Cosmetic only — the credential is the auto-generated UUID `connectionId`.-

Responses

Status CodeDescriptionResponse Body
200Created — RMS generates a UUID `connectionId` + 16-char password and pushes to the orchestrator. Save the plaintext password from the response: the orchestrator stores only a hash.-
400`device_id` missing.-
404Device not owned by caller.-

Example Response

{
  "success": true,
  "connection": {
    "connectionId": "afac150b-951c-449b-918c-3b67fbd83a24",
    "password": "p9F7bX3cVqLtZmK2",
    "ownerUserId": "add02036-6754-4cf7-8432-cc28be4468f0",
    "name": "client-A",
    "createdAt": "2026-04-25T13:22:11Z",
    "deviceId": "add02036-6754-4cf7-8432-cc28be4468f0"
  }
}
POST/api/v2/devices/connections/delete
Delete a connection

Cascades on RMS, orchestrator, and the legacy mirror. Active sessions are terminated.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
connection_idstring (UUID)YesThe connection's id (also the SOCKS5 username).-

Responses

Status CodeDescriptionResponse Body
200Deleted on RMS, the orchestrator, and the legacy mirror. Active proxy sessions using this credential are terminated.-
403Connection not owned/routed through any device the caller owns.-
404Connection not found.-
POST/api/v2/devices/connections/password/rotate
Rotate password

Replaces the connection's password (same `connectionId`). Active sessions continue on the old credential until they close.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
connection_idstring (UUID)YesThe connection's id (also the SOCKS5 username).-

Responses

Status CodeDescriptionResponse Body
200Generates a new 16-char password (same `connectionId`).-
403Forbidden.-

Example Response

{ "success": true, "password": "qK4LmPzWxR7aBf3T" }
POST/api/v2/devices/connections/association/set
Move connection to another device (IP rotation)

Hot-swap the exit device. Owner must own both the source connection and the target device.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
connection_idstring (UUID)YesThe connection's id (also the SOCKS5 username).-
device_idstring (UUID)YesTarget device — **must also be owned by the caller**.-

Responses

Status CodeDescriptionResponse Body
200Hot-swap successful. Effective for new SOCKS5/HTTP CONNECT sessions within ~100 ms (orchestrator auth-cache TTL). In-flight sessions stay on the old device until they close.-
403Source connection or target device not owned by caller.-
POST/api/v2/devices/connections/association/delete
Remove association

Connection stays alive but cannot authenticate until re-associated.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
connection_idstring (UUID)YesThe connection's id (also the SOCKS5 username).-

Responses

Status CodeDescriptionResponse Body
200Connection stays but cannot route until a new association is set. Active sessions are terminated.-
403Forbidden.-
POST/api/v2/devices/connections/blacklist/list
List per-connection blacklist

Per-connection block list (in addition to global + per-device).

Request Body Parameters

ParameterTypeRequiredDescriptionExample
connection_idstring (UUID)YesThe connection's id (also the SOCKS5 username).-

Responses

Status CodeDescriptionResponse Body
200Per-connection blacklist domains (in addition to the global blacklist). Suffix matching applies.-
403Forbidden.-

Example Response

{ "success": true, "domains": ["example.com", "tracker.io"] }
POST/api/v2/devices/connections/blacklist/add
Add domains to blacklist

Adds one or more domains to the connection's blacklist. Suffix matching applies on the proxy side — blocking `example.com` also blocks `sub.example.com`.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
connection_idstring (UUID)YesThe connection's id (also the SOCKS5 username).-
domainsstring[]YesNon-empty array of domains to add or remove.-

Responses

Status CodeDescriptionResponse Body
200Updated.-
403Forbidden.-
POST/api/v2/devices/connections/blacklist/remove
Remove domains from blacklist

Removes one or more domains from the connection's blacklist.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
connection_idstring (UUID)YesThe connection's id (also the SOCKS5 username).-
domainsstring[]YesNon-empty array of domains to add or remove.-

Responses

Status CodeDescriptionResponse Body
200Updated.-
403Forbidden.-
POST/api/v2/devices/proxy-logs/list
Query request logs

One log entry per SOCKS5 / HTTP CONNECT attempt. Backed by ClickHouse; results are post-filtered to devices owned by the caller.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
fromstring (ISO 8601)YesInclusive lower bound on `timestamp`.-
tostring (ISO 8601)YesInclusive upper bound on `timestamp`.-
connectionIdstring (UUID)NoFilter to one connection.-
deviceIdstring (UUID)NoFilter to one device — must be owned by the caller.-
targetstringNoSubstring match on the request target (`host:port`).-
action"allowed" | "blocked"NoFilter by outcome.-
limitintegerNoPage size (default 100, max 10000).-
offsetintegerNo0-indexed offset for pagination.-

Responses

Status CodeDescriptionResponse Body
200Request log rows from ClickHouse. Post-filtered to devices owned by the caller.-
400`from`/`to` missing or invalid; `limit` out of range.-

Example Response

{
  "success": true,
  "total": 12345,
  "entries": [
    {
      "timestamp": "2026-04-25T13:22:11Z",
      "connectionId": "afac150b-951c-449b-918c-3b67fbd83a24",
      "deviceId": "add02036-6754-4cf7-8432-cc28be4468f0",
      "serverNode": "server-us-aws",
      "target": "example.com:443",
      "targetType": "domain",
      "port": 443,
      "resolvedIp": "",
      "action": "allowed",
      "blockReason": null,
      "bytesIn": 184213,
      "bytesOut": 4218
    }
  ]
}
POST/api/v2/devices/proxy-bandwidth
Query bandwidth aggregates

Per-(device, connection) byte counts, optionally grouped by hour or day. When `deviceId` is omitted the backend issues one query per owned device and merges.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
deviceIdstring (UUID)NoFilter to one device — must be owned by the caller. Omit to fetch per-device rows for every device the caller owns.-
connectionIdstring (UUID)NoFilter to one connection.-
fromstring (ISO 8601)NoInclusive lower bound.-
tostring (ISO 8601)NoInclusive upper bound.-
groupBy"hour" | "day"NoTime-bucket granularity.-

Responses

Status CodeDescriptionResponse Body
200Aggregated bandwidth rows from the orchestrator.-

Example Response

{
  "success": true,
  "rows": [
    {
      "deviceId": "add02036-6754-4cf7-8432-cc28be4468f0",
      "connectionId": "afac150b-951c-449b-918c-3b67fbd83a24",
      "bytesIn": 152841234,
      "bytesOut": 9183748,
      "bucket": "2026-04-25T13:00:00Z"
    }
  ]
}
GET/api/v2/admin/devices/proxies
List all proxy connections (admin)

Returns every proxy connection across all users, joined with the associated device's metadata and the orchestrator's bandwidth aggregates (24h + lifetime). Requires the admin API token (`X-Admin-Token`). `device` is `null` when the connection has no current association.

Responses

Status CodeDescriptionResponse Body
200Connection list with associated device + bandwidth.-
401Missing or invalid admin API token.-
502Could not reach the proxy orchestrator.-
503Proxy orchestrator / RMS not configured (env vars missing).-

Example Response

{
  "total": 2,
  "proxies": [
    {
      "connection_id": "afac150b-951c-449b-918c-3b67fbd83a24",
      "name": "client-A",
      "password": "p9F7bX3cVqLtZmK2",
      "created_at": "2026-04-25T13:22:11Z",
      "bytes_last_24h": 152841234,
      "bytes_lifetime": 9183748192,
      "device": {
        "remote_device_id": "add02036-6754-4cf7-8432-cc28be4468f0",
        "user_id": "65f3a1c0d4e2f10012abcd34",
        "name": "Atomic Mammal",
        "brand": "Samsung",
        "model": "SM-G998B",
        "country": "US",
        "online": true,
        "is_rented": false,
        "is_onMarket": false
      }
    },
    {
      "connection_id": "eff80cd4-5dd2-4c69-8b34-2f2d073b0178",
      "name": null,
      "password": "qK4LmPzWxR7aBf3T",
      "created_at": "2026-04-25T13:22:12Z",
      "bytes_last_24h": 0,
      "bytes_lifetime": 24576,
      "device": null
    }
  ]
}

Bucket API

Per-(job, device) JSON bucket — the persistent state automations attach to a single hire on a single device. The endpoints below are the **employer-facing** surface, gated by job ownership / share permission. They mirror the same model as the **Buckets** tab on the Job details page. (The agent surface used from inside automations is `agent.utils.bucket` — see the automation docs.)

GET/api/v2/bucket/:job_id
List buckets for a job

Returns a paginated list of every bucket attached to this job, with the device display name resolved for each.

Path Parameters

ParameterTypeRequiredDescriptionExample
job_idstring (ObjectId)YesPath param. The job's `job_id`. Caller must own the job, or have it shared to them (`view` for reads, `edit` for writes/deletes).-

Query Parameters

ParameterTypeRequiredDescriptionExample
pageintegerNo1-indexed page. Defaults to `1`.1
limitintegerNoPage size. Defaults to `20`. Capped at `100`.20

Responses

Status CodeDescriptionResponse Body
200Paginated list of buckets for this job (newest first by `updated_at`). Each entry is enriched with the device's display name.-
404Job not found, or caller does not own / does not have the required share permission (`view` for reads, `edit` for writes / deletes).{ "error": "Job not found" }
500Unexpected DB error.{ "error": "Internal server error" }

Example Response

{
  "buckets": [
    {
      "_id": "65f1...",
      "job_id": "65aa...",
      "remote_device_id": "8b2f-uuid",
      "data": { "sessionToken": "abc123", "loggedIn": true },
      "updated_at": "2026-04-15T08:14:00.000Z",
      "device_name": "Pixel 5 — Lab"
    }
  ],
  "total": 1,
  "page": 1,
  "pages": 1
}
DELETE/api/v2/bucket/:job_id
Delete all buckets for a job

Wipes every bucket associated with this job. Caller must have `edit` access (owner or shared-edit).

Path Parameters

ParameterTypeRequiredDescriptionExample
job_idstring (ObjectId)YesPath param. The job's `job_id`. Caller must own the job, or have it shared to them (`view` for reads, `edit` for writes/deletes).-

Responses

Status CodeDescriptionResponse Body
200All buckets for this job removed. Returns the count deleted.{ "success": true, "deleted": 12 }
404Job not found, or caller does not own / does not have the required share permission (`view` for reads, `edit` for writes / deletes).{ "error": "Job not found" }
500Unexpected DB error.{ "error": "Internal server error" }
GET/api/v2/bucket/:job_id/:device_id
Read a single bucket

Returns the bucket for this `(job_id, device_id)` pair. 404 when none exists or the job is inaccessible.

Path Parameters

ParameterTypeRequiredDescriptionExample
job_idstring (ObjectId)YesPath param. The job's `job_id`. Caller must own the job, or have it shared to them (`view` for reads, `edit` for writes/deletes).-
device_idstring (UUID)YesPath param. Device's `remote_device_id`.-

Responses

Status CodeDescriptionResponse Body
200Returns the bucket document for this `(job_id, device_id)` pair.-
404Either the job is inaccessible to the caller, or no bucket exists for this device.{ "error": "Bucket not found" }
500Unexpected DB error.{ "error": "Internal server error" }

Example Response

{
  "bucket": {
    "_id": "65f1...",
    "job_id": "65aa...",
    "remote_device_id": "8b2f-uuid",
    "data": { "sessionToken": "abc123", "loggedIn": true },
    "updated_at": "2026-04-15T08:14:00.000Z"
  }
}
PUT/api/v2/bucket/:job_id/:device_id
Write a bucket

Replaces the bucket payload for this `(job_id, device_id)` pair (no merge — `data` becomes the new bucket). Validated against the automation's `bucket_schema` when one is defined. Caller must have `edit` access.

Path Parameters

ParameterTypeRequiredDescriptionExample
job_idstring (ObjectId)YesPath param. The job's `job_id`. Caller must own the job, or have it shared to them (`view` for reads, `edit` for writes/deletes).-
device_idstring (UUID)YesPath param. Device's `remote_device_id`.-

Request Body Parameters

ParameterTypeRequiredDescriptionExample
dataobjectYesNew bucket payload. Replaces the existing object (no merge). If the linked automation defines a `bucket_schema`, `data` is validated against it.-

Responses

Status CodeDescriptionResponse Body
200Bucket created or replaced for this `(job_id, device_id)` pair. Returns the saved document.-
400`data` missing / not an object, or schema validation against the automation's `bucket_schema` failed.{ "error": "Invalid bucket data" }
404Job not found, or caller does not own / does not have the required share permission (`view` for reads, `edit` for writes / deletes).{ "error": "Job not found" }
500Unexpected DB error.{ "error": "Internal server error" }
DELETE/api/v2/bucket/:job_id/:device_id
Delete a bucket

Removes the bucket for this `(job_id, device_id)` pair. Caller must have `edit` access.

Path Parameters

ParameterTypeRequiredDescriptionExample
job_idstring (ObjectId)YesPath param. The job's `job_id`. Caller must own the job, or have it shared to them (`view` for reads, `edit` for writes/deletes).-
device_idstring (UUID)YesPath param. Device's `remote_device_id`.-

Responses

Status CodeDescriptionResponse Body
200Bucket for this `(job_id, device_id)` pair removed.{ "success": true }
404Job not found, or caller does not own / does not have the required share permission (`view` for reads, `edit` for writes / deletes).{ "error": "Job not found" }
500Unexpected DB error.{ "error": "Internal server error" }

Device Bucket API

Per-device JSON bucket, shared across every job and automation running on the device. Useful for cross-job state — login cookies, account tokens, app config. Distinct from the per-job bucket: there is no `bucket_schema` validation, and no job context is required, so direct-run automations can use it too. The agent calls these via `agent.utils.deviceBucket`.

POST/api/v2/device-bucket
Read device bucket

Reads the device-scoped bucket. The `remote_device_id` is taken from the token when it carries a device context; non-agent callers must supply it in the body.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
remote_device_idstring (UUID)NoThe device's `remote_device_id`. Optional when the token already carries a device context (agent tokens). Required for plain Client API tokens. Must point to a device the caller owns or is currently running on.-

Responses

Status CodeDescriptionResponse Body
200Returns the device-scoped bucket. `deviceBucket` is `{}` on first read.-
400Token has no device context and `remote_device_id` was not supplied.{ "error": "Device bucket requires a device context (remote_device_id)" }

Example Response

{
  "deviceBucket": {
    "accountToken": "xyz",
    "username": "user@example.com"
  }
}
POST/api/v2/device-bucket/set
Merge into device bucket

Merges the supplied object into the existing device bucket. Existing keys not in the payload are preserved.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
remote_device_idstring (UUID)NoThe device's `remote_device_id`. Optional when the token already carries a device context (agent tokens). Required for plain Client API tokens. Must point to a device the caller owns or is currently running on.-
dataobjectYesNon-null, non-array JSON object. Top-level keys are merged with the stored bucket — existing keys not in the payload are preserved.-

Responses

Status CodeDescriptionResponse Body
200Bucket merged and persisted. Returns the full merged object.-
400Missing device context or `data` is missing / null / an array / not an object.{ "error": "Invalid data. Must be a non-null object." }

Example Response

{
  "success": true,
  "deviceBucket": {
    "accountToken": "xyz",
    "username": "user@example.com"
  }
}

Other API

File upload and temporary file access endpoints.

POST/api/v2/files/upload
Upload temporary file

Uploads a file to temporary storage. Files are automatically deleted after 15 minutes. Maximum file size is 50 MB. Use multipart/form-data with 'file' field name.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
filefileYesFile to upload (multipart/form-data)Binary file data

Responses

Status CodeDescriptionResponse Body
200File uploaded successfully{ "success": true, "message": "File uploaded successfully", "data": { "filename": "1234567890_example.pdf", "originalName": "example.pdf", "size": 1024000, "url": "https://api.example.com/temp/1234567890_example.pdf", "expiresAt": "2025-10-08T12:15:00.000Z" } }
400No file uploaded{ "success": false, "message": "No file uploaded" }
401Unauthorized or missing tokenAuthentication error message
500Server error during upload{ "success": false, "message": "Error uploading file", "error": "Error details" }

Example Response

{
  "success": true,
  "message": "File uploaded successfully",
  "data": {
    "filename": "1234567890_example.pdf",
    "originalName": "example.pdf",
    "size": 1024000,
    "url": "https://api.example.com/temp/1234567890_example.pdf",
    "expiresAt": "2025-10-08T12:15:00.000Z"
  }
}
GET/api/v2/files/temp/:filename
Get uploaded file

Retrieves a previously uploaded temporary file. Files expire after 15 minutes from upload time.

Request Body Parameters

ParameterTypeRequiredDescriptionExample
filenamestringYesFilename returned from the upload endpoint (path parameter)1234567890_example.pdf

Responses

Status CodeDescriptionResponse Body
200File retrieved successfullyBinary file data
400Filename is required{ "success": false, "message": "Filename is required" }
404File not found or expired{ "success": false, "message": "File not found or expired" }
401Unauthorized or missing tokenAuthentication error message
500Server error during retrieval{ "success": false, "message": "Error retrieving file", "error": "Error details" }