API Documentation

Authentication

All API requests require authentication via an API key. Include your key in the X-API-Key header.

Header Authentication
X-API-Key: ao_live_your_api_key_here

Alternatively, pass the API key in the request body:

{
  "apiKey": "ao_live_your_api_key_here",
  "company": "Stripe"
}

Run Agent

Start an agent run. The job is queued and processed asynchronously. Use the returned job_id to check status.

curl -X POST https://applyoperator.com/api/v1/agents/company-intel/run \
  -H "X-API-Key: ao_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "company": "Monzo",
    "domain": "monzo.com",
    "depth": "standard"
  }'

Response

{
  "success": true,
  "job_id": "ci_abc123xyz",
  "status": "queued",
  "estimated_time": "30-120 seconds"
}

Jobs

Check job status and retrieve results.

POST /api/v1/jobs/getJob

Get job status and results.

Request
{ "job_id": "ci_abc123xyz" }
Response (completed)
{
  "success": true,
  "job": {
    "id": "ci_abc123xyz",
    "agent": "company-intel",
    "status": "completed",
    "progress": 100,
    "results": { "..." },
    "cost": { "amount": 1.00, "currency": "USD" },
    "created_at": "2026-01-15T10:30:00Z",
    "completed_at": "2026-01-15T10:31:23Z"
  }
}

Webhooks

Register a webhook URL to receive notifications when jobs complete or fail.

POST /api/v1/webhooks/register

Register a webhook endpoint.

{
  "url": "https://your-app.com/webhook",
  "events": ["job.completed", "job.failed"]
}

Account

POST /api/v1/account/getBalance

Check your current credit balance.

POST /api/v1/account/getUsage

Get usage history and spending breakdown.

Tool Code

Every marketplace tool exports an async function handler(input, api). The platform calls this function inside a sandboxed Linux namespace with no direct network access.

Handler Signature

async function handler(input, api) {
  // input  — JSON object sent by the caller
  // api    — sandbox API: fetch, log, memory, storage
  // return — any JSON-serializable value (sent back as job output)

  api.log('Starting agent run');

  const res = await api.fetch('https://api.example.com/data', {
    method: 'POST',
    headers: { 'Authorization': 'Bearer ...' },
    body: JSON.stringify({ query: input.query })
  });

  const prev = await api.memory.read();
  await api.memory.write(prev + '\n' + new Date().toISOString());

  return { status: res.status, data: res.body };
}

Important: The handler function must be defined at the top level. It receives input (the JSON payload from the API call) and api (the sandbox API object). The return value becomes the job result.

Sandbox API

The api object provides controlled access to the outside world from inside the sandbox.

api.fetch(url, options)

Make HTTP requests to external services. All requests are proxied through a bridge socket — the sandbox has no direct network.

Option Description
methodHTTP method (GET, POST, PUT, PATCH, DELETE). Default: GET
headersObject of request headers
bodyRequest body (string or object, auto-serialized to JSON)

Returns: { status, statusText, headers, body, text }

Restrictions: HTTPS only, no private/localhost IPs, 15s timeout, 1 MB max response size. body is auto-parsed as JSON when possible, text is always the raw string.

api.log(message)

Capture log messages visible in job results. Messages are truncated to 10,000 characters. Logs are returned alongside the agent output when the job completes.

api.memory

Persistent markdown-based memory stored in SQLite. Two scopes are available:

Method Description Limit
api.memory.read()Read agent-specific memory64 KB
api.memory.write(content)Write agent-specific memory (string)64 KB
api.memory.global.read()Read memory shared across all your agents128 KB
api.memory.global.write(content)Write shared memory (string)128 KB

Memory persists across runs. Agent memory is scoped to the specific agent slug; global memory is shared across all agents for the same user.

api.storage

Paid disk storage for files. Requires an active storage subscription (see Dashboard → Storage).

Method Description
api.storage.list()List files — returns [{file_path, size_bytes, ...}]
api.storage.read(path)Read file content (returns string)
api.storage.write(path, content)Write file (10 MB max per write)
api.storage.delete(path)Delete a file

Path rules: Relative paths only — no .., no leading /, max 500 characters. Files are scoped to the agent slug within the user's storage directory. During grace period, storage is read-only.

api.getCredentials()

Agent tools often need user-specific secrets such as login emails, passwords, or API keys. Instead of hardcoding these values, users save credentials once in the Agent Tools page. Saved credentials are automatically injected at runtime.

In your tool's input_schema, add "credential": true to any property that contains sensitive data. The platform uses this flag to identify which fields should be saved separately and never sent to the LLM.

input_schema example
{
  "type": "object",
  "properties": {
    "email": { "type": "string", "description": "Login email", "credential": true },
    "password": { "type": "string", "description": "Login password", "credential": true },
    "date_range": { "type": "string", "description": "Date range to download" }
  }
}

Fields marked credential: true appear in the Agent Tools configuration form and can be saved by the user. Non-credential fields (like date_range above) are passed as regular input each time the tool runs.

Returns: { configured, credentials }

Field Type Description
configuredbooleantrue if the user has saved credentials for this slug
credentialsobjectKey-value pairs of saved credential fields (empty {} when not configured)
async function handler(input, api) {
  const creds = await api.getCredentials();
  if (!creds.configured) {
    return { error: 'Credentials not configured. Save them in the Agent Tools page.' };
  }

  const { email, password } = creds.credentials;

  // Use credentials to authenticate
  const res = await api.fetch('https://example.com/api/login', {
    method: 'POST',
    body: JSON.stringify({ email, password })
  });

  return { status: 'ok', data: res.body };
}

Security: Credential values are stored per-user, never logged, and never sent to the LLM. The operator only sees field names (via the get_credentials tool) to confirm they exist — actual values stay server-side and are only accessible inside the sandbox.

Users save credentials in Dashboard → Agent Tools. Values are stored per-user, scoped to the tool slug. At runtime, api.getCredentials() returns the actual values inside the sandbox. Credential fields are also auto-injected into the tool's input when called by the operator.

Sandbox Limits

Agents run inside isolated Linux namespaces with the following resource constraints:

Resource Limit
Memory (cgroup)128 MB
Processes (PID limit)32
Execution timeout30 seconds
Stdout capture5 MB
Fetch response1 MB per request
Fetch timeout15 seconds per request
Storage write10 MB per write
Agent memory64 KB
Global memory128 KB
NetworkHTTPS only via bridge (no direct access)
FilesystemRead-only (Alpine rootfs), writable /tmp

Telegram Integration

Connect a Telegram bot to receive notifications and chat with your AI operator agents directly from Telegram.

Prerequisites

  • A Telegram account
  • A Telegram bot created via @BotFather

Setup Steps

1

Create a Telegram bot

Open Telegram, search for @BotFather, send /newbot, and follow the prompts. Copy the bot token (e.g. 123456789:ABCdefGhIjKlmNoPqRsTuVwXyZ).

2

Add the bot token

Go to Settings → Integrations → Telegram, paste the token, and click Save. The system will verify the token and set up a webhook.

3

Activate the bot

Open Telegram, find your bot by username, and send /start. This links your Telegram chat to your ApplyOperator account.

4

Link an agent session (optional)

To chat with an agent via Telegram, select a running operator session from the dropdown in the Telegram card and click Link. Messages you send to the bot will be forwarded to the agent, and its responses sent back to you.

Supported Notifications

  • Job completed / failed
  • Low credits warning / credits depleted
  • Agent marketplace approval

Configure which notifications are sent via Telegram in Notification Preferences.

Bidirectional Chat

When sessions are linked, you can send messages to the bot and the operator agent will process them and respond. The agent has full access to its configured tools (web search, email, etc.).

Multi-Session Chat

You can link multiple agent sessions to your Telegram bot and switch between them using commands:

Command Description
/agentsList all linked sessions with active indicator
/listSame as /agents
/<name>Switch to a session (e.g. /otis)
/helpShow available commands

All regular messages (not starting with /) are sent to the currently active session. Switch between agents at any time.

Note: Linked sessions must be in a "running" state. If a session is stopped, the bot will inform you and ask you to restart it or switch to another.

WhatsApp Integration

Connect WhatsApp to receive notifications and chat with your AI operator agents directly from your phone.

Prerequisites

  • A WhatsApp account with an active phone number
  • WhatsApp installed on your phone

Setup Steps

1

Start the connection

Go to Settings → Integrations → WhatsApp and click Connect WhatsApp.

2

Scan the QR code

A QR code will appear on screen. Open WhatsApp on your phone, go to Settings → Linked Devices → Link a Device, and scan the QR code.

3

Connection confirmed

Once scanned, the status will change to "Connected" and your phone number will be displayed. You'll start receiving notifications.

4

Link agent sessions (optional)

Add one or more running operator sessions to enable bidirectional agent chat via WhatsApp. You can link multiple sessions and switch between them.

Supported Notifications

  • Job completed / failed
  • Low credits warning / credits depleted
  • Agent marketplace approval

Configure which notifications are sent via WhatsApp in Notification Preferences.

Multi-Session Chat

You can link multiple agent sessions and switch between them using commands:

Command Description
/agentsList all linked sessions with active indicator
/listSame as /agents
/<name>Switch to a session (e.g. /otis)
/helpShow available commands

All regular messages are sent to the currently active session. Switch between agents at any time.

Troubleshooting

QR code expired

QR codes expire after a short time. Click Connect WhatsApp again to generate a new one.

Session disconnected

WhatsApp Web sessions may disconnect if your phone loses internet or if you log out from the linked devices menu. Reconnect by clicking Connect WhatsApp and scanning a new QR code.

Agent not responding

Ensure the linked operator session is in a "running" state. Check the dashboard to verify the session status and restart it if needed.

Storage Sync (WebDAV)

Sync your agent storage files between your local computer and ApplyOperator using the WebDAV protocol. Mount your storage as a native folder, use bidirectional sync, or automate backups — works on Windows, Linux, and macOS.

Prerequisites

Authentication

The WebDAV endpoint uses HTTP Basic Auth. Set your username to anything (e.g. your email) and use your API key as the password:

WebDAV Credentials
URL:      https://applyoperator.com/webdav/
Username: your-email@example.com   (any value)
Password: ao_live_your_api_key_here

Quick Start with rclone

rclone is a free, open-source tool for syncing files with cloud storage. It supports WebDAV and runs on all major operating systems.

1

Install rclone

Download from rclone.org/install — available for Windows, macOS, and Linux.

2

Configure the remote

Run rclone config and create a new remote with these settings:

Type:     webdav
URL:      https://applyoperator.com/webdav/
Vendor:   other
User:     your-email@example.com
Password: ao_live_your_api_key_here
3

Sync your files

Use any of these commands (assuming your remote is named ao):

# Download remote files to local folder
rclone sync ao: ~/ao-storage/

# Upload local files to remote
rclone sync ~/ao-storage/ ao:

# Bidirectional sync (keeps both sides up to date)
rclone bisync ~/ao-storage/ ao:

# List remote files
rclone ls ao:

Native OS Mounting

You can also connect directly from your OS file manager without installing rclone:

macOS

Finder → Go → Connect to Server → https://applyoperator.com/webdav/

Windows

File Explorer → right-click This PC → Map Network Drive → https://applyoperator.com/webdav/

Linux

File manager → Connect to Server → davs://applyoperator.com/webdav/

curl Examples

You can also interact with the WebDAV endpoint directly using curl:

# List files (PROPFIND)
curl -X PROPFIND https://applyoperator.com/webdav/ \
  -u "user:ao_live_your_key" \
  -H "Depth: 1"

# Create a directory
curl -X MKCOL https://applyoperator.com/webdav/my-agent/ \
  -u "user:ao_live_your_key"

# Upload a file
curl -X PUT https://applyoperator.com/webdav/my-agent/data.json \
  -u "user:ao_live_your_key" \
  -d '{"key": "value"}'

# Download a file
curl https://applyoperator.com/webdav/my-agent/data.json \
  -u "user:ao_live_your_key"

# Delete a file
curl -X DELETE https://applyoperator.com/webdav/my-agent/data.json \
  -u "user:ao_live_your_key"

Access Control

Subscription required: WebDAV access requires an active storage subscription. With an active subscription you have full read/write access. During a grace period, storage is read-only. With no subscription or an expired one, WebDAV access is denied.

File structure: Your WebDAV root shows agent folders at the top level. Each agent folder contains that agent's storage files. The structure mirrors what you see in Dashboard → Storage.