Docs/curl
Examples

curl

The whole loop from a shell, with jq.

View as Markdown

Set the key and host once:

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

Start a task

bash
SESSION=$(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}' \
  | jq -r .sessionId)
echo "$SESSION"

Poll until done

bash
CURSOR=""
while :; do
  RESP=$(curl -s "$SAI_API_URL/v1/agents/events?sessionId=$SESSION&since=$CURSOR&wait=30" \
    -H "Authorization: Bearer $SAI_API_KEY")
  CURSOR=$(echo "$RESP" | jq -r .cursor)
  STATUS=$(echo "$RESP" | jq -r .status)
  echo "$RESP" | jq -c '.events[] | select(.type=="data-progress") | .data.text'
  case "$STATUS" in
    running) ;;
    needs_approval)
      echo "$RESP" | jq '.events[] | select(.type=="data-approval-request") | .data'
      break ;;
    idle)
      echo "$RESP" | jq -r .text
      break ;;
    error)
      echo "$RESP" | jq '.events[] | select(.type=="error")'
      break ;;
  esac
done

An empty since on the first call is the same as omitting it.

Answer an approval

When the loop prints an approval with "isLinkOnly": false:

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"}'

When it prints "isLinkOnly": true, open the approvalUrl in a browser. Then run the poll loop again with the same SESSION and CURSOR.

The poll response also carries the blocking approval as a top-level approval field, so jq .approval works when the event has already scrolled past.

Attach a file

bash
ATTACHMENT=$(curl -s "$SAI_API_URL/v1/agents/upload" \
  -H "Authorization: Bearer $SAI_API_KEY" \
  -H "x-filename: report.pdf" \
  --data-binary @./report.pdf)

curl -s "$SAI_API_URL/v1/agents/message" \
  -H "Authorization: Bearer $SAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --argjson a "$ATTACHMENT" \
    '{message:"Summarise the attached PDF in five bullets", wait:false, attachments:[$a]}')"

Stop a task

bash
curl -s "$SAI_API_URL/v1/agents/abort" \
  -H "Authorization: Bearer $SAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"sessionId\":\"$SESSION\"}"

Stream instead

Leave wait out and read the SSE frames as they arrive:

bash
curl -N "$SAI_API_URL/v1/agents/message" \
  -H "Authorization: Bearer $SAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message":"What is on the screen right now?"}'