Appearance
API reference
Base URL https://app.areslogin.io/api/v1. Requests and responses are JSON. Times are ISO 8601 in UTC.
Authentication
Authorization: Bearer ares_...X-API-Key: ares_... is accepted as well.
Rate limits
Each key may send 120 requests per minute. Every response carries:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed per minute |
X-RateLimit-Remaining | Requests left in the current minute |
X-RateLimit-Reset | Seconds until the counter resets |
Over the limit the API answers 429 with Retry-After (seconds).
Errors
json
{ "error": { "code": "profile_not_found", "message": "Profile not found." } }| HTTP | code | When |
|---|---|---|
| 400 | invalid_json, invalid_parameter | Body or parameter is wrong |
| 400 | device_required | Several devices online and no device_id given |
| 400 | browser_version_unavailable | That browser version cannot be used on the device |
| 400 | invalid_proxy | Proxy has no host or port |
| 400 | start_failed | The device could not start the browser |
| 401 | unauthorized | Key missing, wrong or revoked |
| 402 | subscription_expired | Plan expired; profiles cannot be started |
| 403 | forbidden | The member behind the key lacks permission |
| 403 | profile_limit_reached | Plan's profile count is used up |
| 403 | two_factor_required | Action is protected by 2FA in the app |
| 403 | plan_limit_reached | Plan's automation or daily run limit is used up |
| 404 | profile_not_found, device_not_found, group_not_found, automation_not_found, task_not_found, not_found | |
| 409 | group_exists | A group with this name already exists |
| 409 | proxy_in_use | The proxy is assigned to a profile |
| 409 | not_in_trash | The profile is not in the trash |
| 409 | already_running, profile_running | Stop the profile first |
| 409 | running_on_other_device | Running on another device |
| 409 | concurrent_limit_reached | Plan's running-profile count is used up |
| 429 | rate_limited | Too many requests |
| 503 | device_offline | The AresLogin app is not open on the device |
Account
GET /me
Account, plan limits and usage.
Returns 200:
json
{
"id": 12,
"username": "anna",
"name": "Anna",
"email": "anna@example.com",
"country": "VN",
"language": "vi",
"currency": "VND",
"role": "member",
"limits": {
"profiles": 100,
"running_profiles": 10
},
"usage": {
"profiles": 37,
"running_profiles": 2
},
"api_key": {
"id": 5,
"name": "seeding server",
"rate_limit_per_minute": 120
}
}GET /devices
Computers running your AresLogin app.
Returns 200:
json
{
"data": [
{
"id": "5yp3n9wx04",
"name": "MacBook Pro",
"online": true,
"platform": "macos_x64",
"app_version": "0.1.9",
"running_profiles": 1,
"max_running_profiles": 5,
"owned": true,
"last_seen_at": "2026-10-05T08:30:00.000Z"
}
]
}GET /browsers
Browser versions a new profile can use.
| Query | Type | |
|---|---|---|
device_id | string | Check availability for this device |
Returns 200:
json
{
"data": [
{
"browser": "chrome",
"version": "153.0.8010.52",
"name": "Chrome 153",
"installed": true,
"supported": true,
"automation": "cdp"
}
]
}GET /groups
Profile groups.
Returns 200:
json
{
"data": [
{
"id": 3,
"name": "Shopee",
"notes": "",
"profile_count": 24,
"created_at": "2026-10-05T08:30:00.000Z"
}
],
"ungrouped_profile_count": 12
}GET /proxies
Saved proxies. Passwords are never returned.
Returns 200:
json
{
"data": [
{
"id": 81,
"type": "http",
"host": "1.2.3.4",
"port": 8080,
"username": "user",
"country": "VN",
"notes": "",
"expires_at": "2026-10-05T08:30:00.000Z",
"profile_count": 2
}
]
}GET /wallet
Wallet balance, subscription and recent transactions. Read-only. Topping up and changing plans are done in the app.
Returns 200:
json
{
"balance": 1,
"currency": "",
"subscription": {
"plan": "",
"profiles": 1,
"members": 1,
"expires_at": "2026-10-05T08:30:00.000Z",
"days_left": 1,
"auto_renew": true
},
"transactions": [
{
"id": 1,
"type": "top_up",
"amount": 1,
"balance_after": 1,
"note": "",
"created_at": "2026-10-05T08:30:00.000Z"
}
]
}GET /orders
The 100 most recent orders.
Returns 200:
json
{
"data": [
{
"id": 1,
"type": "plan_purchase",
"amount": 1,
"status": "new",
"created_at": "2026-10-05T08:30:00.000Z"
}
]
}GET /activity
Activity log.
| Query | Type | |
|---|---|---|
page | integer | |
per_page | integer |
Returns 200:
json
{
"data": [
{
"id": 1,
"at": "2026-10-05T08:30:00.000Z",
"user_id": 1,
"action": "",
"device_id": "abc123",
"profile_id": "abc123",
"detail": ""
}
],
"total": 12
}GET /overview
Counts at a glance.
Returns 200:
json
{
"profiles": {
"ready": 1,
"running": 1,
"creating": 1
},
"browsers": {
"chrome": 1,
"firefox": 1
},
"proxies": 1,
"running_sessions": 1
}Groups
POST /groups
Create a group.
| Field | Type | |
|---|---|---|
name | string | |
notes | string |
json
{
"name": "Shopee"
}Returns 201:
json
{
"id": 3,
"name": "Shopee",
"notes": "",
"profile_count": 24,
"created_at": "2026-10-05T08:30:00.000Z"
}PATCH /groups/{id}
Rename a group or change its notes.
| Field | Type | |
|---|---|---|
name | string | |
notes | string |
Returns 200:
json
{
"id": 3,
"name": "Shopee",
"notes": "",
"profile_count": 24,
"created_at": "2026-10-05T08:30:00.000Z"
}DELETE /groups/{id}
Delete a group. Profiles in the group are NOT deleted; they become ungrouped.
Returns 200:
json
{
"id": 1,
"deleted": true,
"ungrouped_profiles": 1
}Proxies
POST /proxies
Add proxies. Send one proxy as fields, or many as list (one host:port:user:pass per line).
| Field | Type | |
|---|---|---|
host | string | |
port | integer | |
username | string | |
password | string | |
country | string | |
notes | string | |
list | string |
json
{
"host": "1.2.3.4",
"port": 8080,
"username": "user",
"password": "pass",
"country": "VN"
}Returns 201:
json
{
"created": 1
}POST /proxies/bulk-delete
Delete several proxies. Proxies still assigned to a profile are skipped and counted in in_use.
| Field | Type | |
|---|---|---|
ids | integer[] |
json
{
"ids": [
11,
12
]
}Returns 200:
json
{
"deleted": 1,
"in_use": 1,
"forbidden": 1
}DELETE /proxies/{id}
Delete a proxy.
Returns 200:
json
{
"id": 1,
"deleted": true
}Profiles
GET /profiles
List profiles.
| Query | Type | |
|---|---|---|
page | integer | Default 1. |
per_page | integer | Default 50. Up to 200. |
search | string | Matches name, id, tags, notes |
group_id | string | A group id |
tag | string | Exact tag |
status | ready, running, creating | |
device_id | string | Profiles stored on that device |
Returns 200:
json
{
"data": [
{
"id": "40df428e",
"name": "shop-01",
"serial_number": 118,
"status": "ready",
"browser": "chrome",
"browser_version": "153.0.8010.52",
"device_id": "5yp3n9wx04",
"group_id": 3,
"owner_id": 12,
"tags": [
"shopee",
"vn"
],
"notes": "",
"proxy": {
"id": 81,
"address": "1.2.3.4:8080",
"country": "VN"
},
"fingerprint": {
"platform": "windows",
"platform_version": "10.0.0",
"brand": "Chrome",
"user_agent_version": null,
"timezone": null,
"language": null,
"cpu_cores": 8,
"memory_gb": 8,
"gpu": null,
"screen": {
"width": 1920,
"height": 1080
},
"seed": 123456
},
"created_at": "2026-10-05T08:30:00.000Z",
"updated_at": "2026-10-05T08:30:00.000Z",
"last_started_at": "2026-10-05T08:30:00.000Z",
"running_on": []
}
],
"page": 1,
"per_page": 1,
"total": 12
}POST /profiles
Create a profile.
| Field | Type | |
|---|---|---|
name | string | Required. |
browser | chrome, firefox | Default chrome. |
browser_version | string | A version from GET /browsers. Default is the newest |
proxy | ProxyInput | A saved proxy id, a string such as http://user:pass@host:port or host:port:user:pass, or an object. null removes the proxy. |
group_id | integer | |
tags | string[] | |
notes | string | |
device_id | string | Where to create it. Default is your online device |
fingerprint | Fingerprint | Fields you leave out are generated. |
json
{
"name": "shop-01",
"proxy": "http://user:pass@1.2.3.4:8080",
"tags": [
"shopee"
]
}Returns 201:
json
{
"id": "40df428e",
"name": "shop-01",
"serial_number": 118,
"status": "ready",
"browser": "chrome",
"browser_version": "153.0.8010.52",
"device_id": "5yp3n9wx04",
"group_id": 3,
"owner_id": 12,
"tags": [
"shopee",
"vn"
],
"notes": "",
"proxy": {
"id": 81,
"address": "1.2.3.4:8080",
"country": "VN"
},
"fingerprint": {
"platform": "windows",
"platform_version": "10.0.0",
"brand": "Chrome",
"user_agent_version": null,
"timezone": null,
"language": null,
"cpu_cores": 8,
"memory_gb": 8,
"gpu": null,
"screen": {
"width": 1920,
"height": 1080
},
"seed": 123456
},
"created_at": "2026-10-05T08:30:00.000Z",
"updated_at": "2026-10-05T08:30:00.000Z",
"last_started_at": "2026-10-05T08:30:00.000Z",
"running_on": []
}Returns 202: The device has not finished creating the profile yet.
GET /profiles/{id}
Get a profile.
Returns 200:
json
{
"id": "40df428e",
"name": "shop-01",
"serial_number": 118,
"status": "ready",
"browser": "chrome",
"browser_version": "153.0.8010.52",
"device_id": "5yp3n9wx04",
"group_id": 3,
"owner_id": 12,
"tags": [
"shopee",
"vn"
],
"notes": "",
"proxy": {
"id": 81,
"address": "1.2.3.4:8080",
"country": "VN"
},
"fingerprint": {
"platform": "windows",
"platform_version": "10.0.0",
"brand": "Chrome",
"user_agent_version": null,
"timezone": null,
"language": null,
"cpu_cores": 8,
"memory_gb": 8,
"gpu": null,
"screen": {
"width": 1920,
"height": 1080
},
"seed": 123456
},
"created_at": "2026-10-05T08:30:00.000Z",
"updated_at": "2026-10-05T08:30:00.000Z",
"last_started_at": "2026-10-05T08:30:00.000Z",
"running_on": []
}PATCH /profiles/{id}
Update a profile. Send only the fields to change. Browser version and fingerprint cannot change while the profile is running.
| Field | Type | |
|---|---|---|
name | string | |
notes | string | |
tags | string[] | |
group_id | integer | |
proxy | ProxyInput | A saved proxy id, a string such as http://user:pass@host:port or host:port:user:pass, or an object. null removes the proxy. |
browser_version | string | |
fingerprint | Fingerprint | Fields you leave out are generated. |
json
{
"notes": "warmed up",
"tags": [
"shopee",
"vn"
]
}Returns 200:
json
{
"id": "40df428e",
"name": "shop-01",
"serial_number": 118,
"status": "ready",
"browser": "chrome",
"browser_version": "153.0.8010.52",
"device_id": "5yp3n9wx04",
"group_id": 3,
"owner_id": 12,
"tags": [
"shopee",
"vn"
],
"notes": "",
"proxy": {
"id": 81,
"address": "1.2.3.4:8080",
"country": "VN"
},
"fingerprint": {
"platform": "windows",
"platform_version": "10.0.0",
"brand": "Chrome",
"user_agent_version": null,
"timezone": null,
"language": null,
"cpu_cores": 8,
"memory_gb": 8,
"gpu": null,
"screen": {
"width": 1920,
"height": 1080
},
"seed": 123456
},
"created_at": "2026-10-05T08:30:00.000Z",
"updated_at": "2026-10-05T08:30:00.000Z",
"last_started_at": "2026-10-05T08:30:00.000Z",
"running_on": []
}DELETE /profiles/{id}
Move a profile to trash. Restore it, or delete it for good, in the app.
Returns 200:
json
{
"id": "abc123",
"deleted": true,
"message": ""
}GET /tags
Tags in use.
Returns 200:
json
{
"data": [
{
"name": "shop-01",
"profile_count": 12
}
]
}Run
POST /profiles/{id}/start
Start a profile. Starts the browser on a device and waits until it is up. Calling it again while the profile is running on that device returns the same cdp_url with already_running: true.
| Field | Type | |
|---|---|---|
device_id | string | Required only when several of your devices are online |
timeout | integer | Seconds to wait for the browser Default 120. |
Returns 200:
json
{
"id": "40df428e",
"status": "running",
"already_running": false,
"device_id": "5yp3n9wx04",
"pid": 5120,
"debug_port": 49821,
"cdp_url": "http://127.0.0.1:49821",
"ws_endpoint": null,
"started_at": "2026-10-05T08:30:00.000Z"
}Returns 202: Still starting; poll GET /profiles/{id}/status.
POST /profiles/{id}/stop
Stop a profile. Closes the browser on every device where the profile is running and saves the profile.
Returns 200:
json
{
"id": "abc123",
"status": "ready"
}GET /profiles/{id}/status
Where a profile is running.
Returns 200:
json
{
"id": "abc123",
"status": "ready",
"running_on": []
}POST /profiles/{id}/check-proxy
Check the profile's proxy. Looks up the exit IP through the profile's proxy, from the device.
Returns 200:
json
{
"id": "abc123",
"alive": true,
"ip": "",
"country": "VN",
"latency_ms": 1,
"error": ""
}Returns 202: The device is still checking.
Trash
GET /trash
Profiles in the trash.
| Query | Type | |
|---|---|---|
page | integer | |
per_page | integer | |
search | string |
Returns 200:
json
{
"data": [
{
"id": "abc123",
"name": "shop-01",
"device_id": "abc123",
"group_id": 1,
"browser": "chrome",
"deleted_at": "2026-10-05T08:30:00.000Z",
"deleted_by": 1
}
],
"page": 1,
"per_page": 1,
"total": 12
}POST /trash/{id}/restore
Restore a profile from the trash. Deleting for good is only possible in the app.
Returns 200:
json
{
"id": "abc123",
"restored": true
}Automation
GET /automations
Automations (scripts). Scripts are built in the app. The API lists them, runs them and reads their results.
Returns 200:
json
{
"data": [
{
"id": 1,
"name": "shop-01",
"block_count": 12,
"created_at": "2026-10-05T08:30:00.000Z",
"updated_at": "2026-10-05T08:30:00.000Z",
"last_run_at": "2026-10-05T08:30:00.000Z",
"running_profiles": 1
}
]
}POST /automations/{id}/run
Run an automation on profiles. Returns at once with a run_id; poll GET /automations/{id}/runs. The device's AresLogin app must be open.
| Field | Type | |
|---|---|---|
profile_ids | string[] | Required. |
device_id | string | |
concurrency | integer | Default 2. |
no_images | boolean | |
mode | extension | Run through the helper extension (Chrome engine, profile must be closed) for sites that block automation tools. |
json
{
"profile_ids": [
"40df428e"
]
}Returns 202:
json
{
"automation_id": 1,
"run_id": "abc123",
"profiles": 1,
"status": ""
}GET /automations/{id}/runs
Progress of a run. Without run_id: the most recent run.
| Query | Type | |
|---|---|---|
run_id | string |
Returns 200:
json
{
"automation_id": 1,
"run_id": "abc123",
"data": [
{
"profile_id": "abc123",
"profile_name": "shop-01",
"device_id": "abc123",
"status": "queued",
"error": "",
"started_at": "2026-10-05T08:30:00.000Z",
"finished_at": "2026-10-05T08:30:00.000Z"
}
]
}POST /automations/{id}/stop
Stop a run.
| Field | Type | |
|---|---|---|
run_id | string | Required. |
Returns 200:
json
{
"automation_id": 1,
"run_id": "abc123",
"status": ""
}GET /automations/{id}/results
Rows written by the Save result block. The newest 200 rows; all=1 returns up to 20,000.
| Query | Type | |
|---|---|---|
all | 1 |
Returns 200:
json
{
"automation_id": 1,
"columns": [
""
],
"total": 12,
"data": [
{
"id": 1,
"profile_name": "shop-01",
"created_at": "2026-10-05T08:30:00.000Z",
"values": {}
}
]
}Tasks
GET /tasks
Tasks. A task = which automations, on which profiles, when. Each device runs one task at a time; later ones queue.
Returns 200:
json
{
"data": [
{
"id": 1,
"name": "shop-01",
"profile_ids": [
""
],
"automations": [
{
"id": 1,
"name": "shop-01"
}
],
"order": "sequential",
"type": "regular",
"schedule": {
"enabled": true,
"times": [
""
],
"weekdays": [
1
],
"random_delay_minutes": 1
},
"priority": true,
"no_images": true,
"device_id": "abc123",
"concurrency": 1,
"created_at": "2026-10-05T08:30:00.000Z",
"run_count": 12,
"last_run": {
"id": 1,
"status": "queued",
"started_at": "2026-10-05T08:30:00.000Z",
"finished_at": "2026-10-05T08:30:00.000Z"
}
}
]
}POST /tasks
Create a task.
| Field | Type | |
|---|---|---|
name | string | Required. |
profile_ids | string[] | Required. |
automation_ids | integer[] | Required. |
order | sequential, random | Default sequential. |
schedule | object | Give it to make a scheduled task. Times are HH:MM in Vietnam time (UTC+7); weekdays 1 = Monday … 7 = Sunday. |
priority | boolean | Jump to the front of the device's queue (does not interrupt the running task). |
no_images | boolean | |
device_id | string | Device that runs the task. Optional when exactly one of your devices is online. |
concurrency | integer | Default 2. |
run_now | boolean | Regular tasks only: queue a run right after creating. |
json
{
"name": "daily-warmup",
"profile_ids": [
"40df428e"
],
"automation_ids": [
12
],
"schedule": {
"times": [
"08:30"
]
}
}Returns 201:
json
{
"id": 1,
"name": "shop-01",
"profile_ids": [
""
],
"automations": [
{
"id": 1,
"name": "shop-01"
}
],
"order": "sequential",
"type": "regular",
"schedule": {
"enabled": true,
"times": [
""
],
"weekdays": [
1
],
"random_delay_minutes": 1
},
"priority": true,
"no_images": true,
"device_id": "abc123",
"concurrency": 1,
"created_at": "2026-10-05T08:30:00.000Z",
"run_count": 12,
"last_run": {
"id": 1,
"status": "queued",
"started_at": "2026-10-05T08:30:00.000Z",
"finished_at": "2026-10-05T08:30:00.000Z"
},
"started_run_id": 1
}DELETE /tasks/{id}
Delete a task. Logs of past runs are kept.
Returns 200:
json
{
"id": 1,
"deleted": true
}POST /tasks/{id}/run
Queue a run of a task.
| Field | Type | |
|---|---|---|
device_id | string |
Returns 202:
json
{
"task_id": 1,
"task_run_id": 1,
"status": ""
}GET /task-runs
Task run log.
| Query | Type | |
|---|---|---|
search | string | |
status | queued, running, done, failed, stopped |
Returns 200:
json
{
"data": [
{
"id": 1,
"task_id": 1,
"name": "shop-01",
"automations": [
{
"id": 1,
"name": "shop-01"
}
],
"profile_count": 12,
"status": "queued",
"error": "",
"counts": {
"done": 1,
"failed": 1,
"stopped": 1
},
"source": "manual",
"queued_at": "2026-10-05T08:30:00.000Z",
"started_at": "2026-10-05T08:30:00.000Z",
"finished_at": "2026-10-05T08:30:00.000Z"
}
]
}GET /task-runs/{id}
One task run, profile by profile.
Returns 200:
json
{
"id": 1,
"task_id": 1,
"name": "shop-01",
"automations": [
{
"id": 1,
"name": "shop-01"
}
],
"profile_count": 12,
"status": "queued",
"error": "",
"counts": {
"done": 1,
"failed": 1,
"stopped": 1
},
"source": "manual",
"queued_at": "2026-10-05T08:30:00.000Z",
"started_at": "2026-10-05T08:30:00.000Z",
"finished_at": "2026-10-05T08:30:00.000Z",
"profiles": [
{
"automation_id": 1,
"automation_name": "shop-01",
"profile_name": "shop-01",
"status": "queued",
"error": "",
"started_at": "2026-10-05T08:30:00.000Z",
"finished_at": "2026-10-05T08:30:00.000Z"
}
]
}POST /task-runs/{id}/stop
Stop a task run. A queued run is removed from the queue; a running one is asked to stop.
Returns 200:
json
{
"id": 1,
"status": ""
}Objects
Fingerprint
Fields you leave out are generated.
| Field | Type | |
|---|---|---|
platform | windows, macos, linux | |
platform_version | string | Example 10.0.0. |
brand | Chrome, Edge, Opera, Vivaldi | |
user_agent_version | string | Example 153.0.8010.52. |
timezone | string | Example Asia/Ho_Chi_Minh. |
language | string | Example vi-VN. |
cpu_cores | integer | |
memory_gb | 2, 4, 8, 16, 32 | |
gpu | string | |
screen | object | |
do_not_track | boolean | |
seed | integer |
ProxyInput
A saved proxy id, a string such as http://user:pass@host:port or host:port:user:pass, or an object. null removes the proxy.