# Quickstart

From sign-in to a finished task in one sitting.

## 1. Sign in

Open [platform.simular.ai](https://platform.simular.ai) and sign in with Google.

Free accounts verify a phone number before their first key. The portal asks for it. If it was skipped, key creation returns `403` with `{ "error": "phone_verification_required" }`.

## 2. Create an API key

In the portal, create a key. The key is shown once. Copy it.

```bash
export SAI_API_KEY="sapi_..."
export SAI_API_URL="https://api.simular.ai"
```

Free accounts hold one key. Paid accounts hold up to 20. See [Keys](/documentation/api-reference/keys).

## 3. Check your computers

```bash
curl -s "$SAI_API_URL/v1/agents/machines" \
  -H "Authorization: Bearer $SAI_API_KEY"
```

```json
{
  "machines": [
    {
      "machineId": "free-3fA9kQ2xYz",
      "name": "Sai cloud computer (free)",
      "kind": "cloud",
      "online": false
    }
  ]
}
```

With one computer you can leave `machineId` out of every request that follows.

Optional: check what the account can spend.

```bash
curl -s "$SAI_API_URL/v1/agents/account" \
  -H "Authorization: Bearer $SAI_API_KEY"
```

```json
{
  "userId": "3fA9kQ2xYz",
  "userState": "active_free",
  "plan": { "id": null, "title": "Free", "free": true, "unlimited": false },
  "credits": { "usd": 0.35 },
  "authType": "apiKey"
}
```

## 4. Send the first message

```bash
curl -s "$SAI_API_URL/v1/agents/message" \
  -H "Authorization: Bearer $SAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Open Notepad, type hello, save it to the desktop as hello.txt",
    "wait": false
  }'
```

```json
{ "sessionId": "cs_01HZY", "machineId": "free-3fA9kQ2xYz", "queued": false }
```

> **Note**
>
> A free account's first request can take about two minutes while its computer starts. Keep polling. The session is not stuck.

## 5. Poll for events

```bash
curl -s "$SAI_API_URL/v1/agents/events?sessionId=cs_01HZY&wait=30" \
  -H "Authorization: Bearer $SAI_API_KEY"
```

```json
{
  "events": [
    { "type": "data-progress", "data": { "text": "Opening Notepad", "tool": "computer" } }
  ],
  "cursor": "1790000012345:3",
  "status": "running",
  "text": ""
}
```

Pass the returned `cursor` as `since` on the next call. Repeat while `status` is `running`.

## 6. Handle an approval

When `status` is `needs_approval`, the response carries the pending approval in a top-level `approval` field, and the events array holds the matching `data-approval-request`.

```json
{
  "type": "data-approval-request",
  "data": {
    "approvalId": "ap_7Qw",
    "title": "Command Approval Required",
    "description": "Sai wants to run a command.",
    "approvalType": "exec",
    "isLinkOnly": false,
    "approvalUrl": "https://sai.simular.ai/approval/3fA9kQ2xYz/ap_7Qw?from=api",
    "command": "notepad.exe",
    "cwd": "C:\\Users\\sai"
  }
}
```

`isLinkOnly` is `false`, so answer over the API:

```bash
curl -s "$SAI_API_URL/v1/agents/approve" \
  -H "Authorization: Bearer $SAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "approvalId": "ap_7Qw", "response": "yes" }'
```

If `isLinkOnly` were `true`, you would open `approvalUrl` in a browser instead. See [Approvals](/documentation/concepts/approvals).

## 7. Read the result

Keep polling. When `status` is `idle`, `text` is Sai's answer.

```json
{
  "events": [{ "type": "finish", "finishReason": "stop" }],
  "cursor": "1790000098765:12",
  "status": "idle",
  "text": "Done. hello.txt is on the desktop with the text \"hello\"."
}
```

## Or add Sai to your coding agent

```bash
claude mcp add sai -e SAI_API_KEY=sapi_... -- npx -y @simular-ai/sai-mcp
```

Then ask Claude Code to use Sai to open Notepad and save hello.txt on the desktop. The same server works in [Codex](/documentation/coding-agents/codex) and [Cursor](/documentation/coding-agents/cursor).
