Skip to content

Tutorial: REST API and Web UI

Run the PyStator API server and (optionally) the web UI to validate configs, run process, and manage machines.

Overview

You will:

  1. Install the API extra and start the server.
  2. Call the health and validate endpoints.
  3. Call the process endpoint to compute a transition.
  4. (Optional) Build and serve the UI, and use it to point at the API.

Prerequisites

  • Python 3.11+
  • pip install pystator[api]

For the UI: Node.js and npm, and a built UI (see Step 4).

Step 1: Start the API server

pystator api

Or with uvicorn:

uvicorn pystator.api.main:app --reload --port 8000

Default URL: http://localhost:8000. OpenAPI docs: http://localhost:8000/docs.

Step 2: Health and validate

Health:

curl http://localhost:8000/health

Expect something like: {"status":"healthy","version":"0.0.1"}.

Validate a config:

curl -X POST http://localhost:8000/api/v1/validate \
  -H "Content-Type: application/json" \
  -d '{
    "config": {
      "meta": {"version": "1.0.0", "machine_name": "test", "strict_mode": true},
      "states": [
        {"name": "A", "type": "initial"},
        {"name": "B", "type": "stable"},
        {"name": "C", "type": "terminal"}
      ],
      "transitions": [
        {"trigger": "go", "source": "A", "dest": "B"},
        {"trigger": "done", "source": "B", "dest": "C"}
      ]
    }
  }'

A valid config returns 200 and validation result; invalid returns 422 with error details.

Step 3: Process an event

Process (compute next state for one event):

curl -X POST http://localhost:8000/api/v1/process \
  -H "Content-Type: application/json" \
  -d '{
    "config": {
      "meta": {"version": "1.0.0", "machine_name": "test", "strict_mode": true},
      "states": [
        {"name": "A", "type": "initial"},
        {"name": "B", "type": "stable"},
        {"name": "C", "type": "terminal"}
      ],
      "transitions": [
        {"trigger": "go", "source": "A", "dest": "B"},
        {"trigger": "done", "source": "B", "dest": "C"}
      ]
    },
    "current_state": "A",
    "trigger": "go",
    "context": {}
  }'

Response includes success, source_state, target_state, actions, etc. If auth is enabled, include Authorization: Bearer <token> (obtain token via POST /api/v1/auth/login).

Step 4: (Optional) Web UI

The UI is a Next.js app that can be built and served separately, or served by a small Python server that proxies to the API.

From source (development):

cd src/pystator/ui
npm install
npm run build
# From project root:
pystator ui serve

Then open the URL shown (e.g. http://127.0.0.1:3000). In Settings you can set the API base URL (default: http://localhost:8000). Use the UI to:

  • Validate FSM configs
  • Run process with custom state/trigger/context
  • (If the API has machine storage) List and manage stored machines

Auth: If the API has auth enabled, the UI will show a login page and use Bearer tokens for requests. When the API is unreachable, an “API server not connected” banner appears; you can still navigate and adjust Settings.

What you learned

  • The API exposes /health, /api/v1/validate, and /api/v1/process for quick validation and transition computation.
  • Optional auth: login via /api/v1/auth/login, then send Bearer token on protected routes.
  • The UI talks to the API using the base URL you configure; it mirrors the same concepts (validate, process, machines).

Next steps