Screenshot analysis quickstart

Build a complete local workflow: exchange a launch token, capture a window, stream an answer and clean up.

Updated 29 July 2026Local API · v1 contract

Before you start

This walkthrough assumes OpenSS is already running and that the local launch flow has provided a one-time launch token. The token is intentionally not generated by this documentation or by a remote service.

Terminal
openss gui --no-open
# Copy the local URL printed by OpenSS, then keep this process running.

Set local variables

Shell
BASE_URL="http://127.0.0.1:PORT"
LAUNCH_TOKEN="the-token-from-the-local-launch-flow"

curl --fail-with-body "$BASE_URL/api/version"

Exchange the launch token

The version check is public only in the narrow sense that it does not require a session. The exchange endpoint accepts the launch token once and returns a session token. Do not put either token in source control, logs or a URL you share.

Shell
SESSION_TOKEN=$(curl --fail-with-body -sS \
  -X POST "$BASE_URL/api/session/exchange" \
  -H "Content-Type: application/json" \
  -d "{\"launchToken\":\"$LAUNCH_TOKEN\"}" \
  | jq -r .sessionToken)

export BASE_URL SESSION_TOKEN

Capture a supported window

The capture service runs locally and returns OCR plus a temporary ID. Use target values such as chrome, powerpoint or word when you want deterministic selection; omit target to let the local capture rules decide. fullSlide applies to PowerPoint slide-show capture.

Shell
CAPTURE=$(curl --fail-with-body -sS \n  -X POST "$BASE_URL/api/screenshots/capture" \n  -H "X-OpenSS-Session: $SESSION_TOKEN" \n  -H "Content-Type: application/json" \n  -d "{\"target\":\"chrome\",\"fullSlide\":false}")\n\nSCREENSHOT_ID=$(jq -r .screenshotId <<< "$CAPTURE")\njq . <<< "$CAPTURE"

Stream the analysis

The request body uses source: capture to tell the engine that a screenshot is required. The response is an SSE stream, even though the request method is POST. Each data line contains one JSON object.

Shell
curl --no-buffer --fail-with-body -sS \
  -X POST "$BASE_URL/api/chat/stream" \
  -H "X-OpenSS-Session: $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"source\":\"capture\",\"screenshotId\":\"$SCREENSHOT_ID\",\"message\":\"Summarise the important information and list the next actions.\"}"

Delete the temporary capture

Shell
curl --fail-with-body -sS \
  -X DELETE "$BASE_URL/api/screenshots/$SCREENSHOT_ID" \
  -H "X-OpenSS-Session: $SESSION_TOKEN"

# Expected response
{"deleted":true}

The same flow in Python

Python
import json
import os
import requests

base_url = os.environ["OPENSS_BASE_URL"].rstrip("/")
launch_token = os.environ["OPENSS_LAUNCH_TOKEN"]

version = requests.get(base_url + "/api/version", timeout=5)
version.raise_for_status()

exchange = requests.post(
    base_url + "/api/session/exchange",
    json={"launchToken": launch_token},
    timeout=5,
)
exchange.raise_for_status()
session = exchange.json()["sessionToken"]
headers = {"X-OpenSS-Session": session}

capture = requests.post(
    base_url + "/api/screenshots/capture",
    headers=headers,
    json={"target": "chrome", "fullSlide": False},
    timeout=60,
)
capture.raise_for_status()
screenshot_id = capture.json()["screenshotId"]

try:
    with requests.post(
        base_url + "/api/chat/stream",
        headers=headers,
        json={
            "source": "capture",
            "screenshotId": screenshot_id,
            "message": "Summarise the important information and list the next actions.",
        },
        stream=True,
        timeout=120,
    ) as response:
        response.raise_for_status()
        for line in response.iter_lines(decode_unicode=True):
            if not line or not line.startswith("data: "):
                continue
            event = json.loads(line[6:])
            if "delta" in event:
                print(event["delta"], end="", flush=True)
            elif event.get("done"):
                print()
            elif "error" in event:
                raise RuntimeError(event["error"])
finally:
    requests.delete(
        base_url + "/api/screenshots/" + screenshot_id,
        headers=headers,
        timeout=5,
    ).raise_for_status()
Contract source: OpenSS/src/openss/gui/server.py and schemas.py.