Skip to content

Rest API

Achraf Jalleli edited this page Mar 4, 2026 · 11 revisions

REST API /api/v2

The panel behaves like any other NetworkManager-managed linux and is able to either receive an IP-Address over DHCP or a statically defined one. Where the static IP is most likely the easiest to work with.

  • Base URL: https://IP_ADDRESS

Schema note: This documentation intentionally stays light on field details beyond what is shown in the examples. For the exact datatypes and complete payload shapes, refer to the corresponding Rust types (linked below).


Authentication

The panel performs Basic-Auth authentication. For EVERY request made over HTTPS, Basic Auth is required.

To set the password on the Panel for Basic Auth, do the following:

  1. Open a Terminal
  2. cd /home/qitech/control
  3. ./credentials.sh

The credentials.sh script sets and prints the username and password for the api ONCE in the console. Afterwards its accessible in machine_password in /tmp/ until the machine shuts down. If you ever forget your password you can simply run ./credentials.sh again, resetting the password used, however the username will always be machine

Example request with curl:

# username=machine
# password=VoMZKZK4K4ZIvON+OU2ZcCXy
# With -k you can ignore curl's self signed certificate error
curl https://192.168.130.195/api/v2/machine -k -u machine:VoMZKZK4K4ZIvON+OU2ZcCXy

Handling Self signed Certificate Warnings

For HTTPS we use self-signed certificates. These are untrusted by default in browsers,tools like curl and https libraries.

For most programs you can either ignore this warning or you can manually trust the certificate on your system. How these are installed depends on your system.

On the panel pc, the root Certificate is located at: /var/lib/caddy/.local/share/caddy/pki/authorities/local/root.crt

You need to copy this file to an usb drive or copy it some other way and add it as a trusted root certificate in your OS.

Please refer to your OS' documentation or search the Internet about how to install a trusted SSL certificate.

Bypassing HTTPS and Authentication

If you have an isolated network and don't wish to perform Authentication, then you can achieve this by:

1. On the HMI panel

cd control
sudo nano nixos/os/configuration.nix

Find:

networking.firewall.allowedTCPPorts = [ 443 ];

Change to:

networking.firewall.allowedTCPPorts = [ 3001 ];

Save and exit.


2. Apply the configuration and reboot

sudo nixos-rebuild switch --flake .#nixos --impure
sudo reboot

3. Verify the server is running

systemctl status qitech-control-server --no-pager
ss -ltnp | grep 3001

The service should be listening on 0.0.0.0:3001.


4. Take note of the Panel IP

hostname -I

Example:

192.168.130.195

5. Test from Windows

Replace <PANEL_IP> with IP from previous step.

Test-NetConnection -ComputerName <PANEL_IP> -Port 3001

REST API test:

curl.exe "http://<PANEL_IP>:3001/api/v2/machine"

Again, you should only ever do this if you have your own reverse proxy with authentication or you have an isolated network.


List machines GET /api/v2/machine

Returns the set of machines currently known/connected to the panel.

Machines are identified by:

  • slug: the machine type / model identifier (string)
  • serial: the specific machine instance identifier (int)

Each machine also includes a legacy_id to support older v1 workflows. If a machine reports an issue, the error field may be present and non-null (containing an error message).

Example request

curl -X GET "https://IP_ADDRESS/api/v2/machine" -u machine:YOUR_PASSWORD

Example response

{
  "machines": [
    {
      "legacy_id": {
        "machine_identification": {
          "vendor": 1,
          "machine": 7
        },
        "serial": 57922
      },
      "serial": 57922,
      "vendor": "QiTech",
      "slug": "mock",
      "error": null
    },
    {
      "legacy_id": {
        "machine_identification": {
          "vendor": 1,
          "machine": 4
        },
        "serial": 57922
      },
      "serial": 57922,
      "vendor": "QiTech",
      "slug": "extruder_v1",
      "error": null
    },
    {
      "legacy_id": {
        "machine_identification": {
          "vendor": 1,
          "machine": 2
        },
        "serial": 57922
      },
      "serial": 57922,
      "vendor": "QiTech",
      "slug": "winder_v1",
      "error": null
    },
    {
      "legacy_id": {
        "machine_identification": {
          "vendor": 1,
          "machine": 10
        },
        "serial": 48879
      },
      "serial": 48879,
      "vendor": "QiTech",
      "slug": "wago_power_v1",
      "error": null
    }
  ]
}

Get current values GET /api/v2/machine/<slug>/<serial>

Returns all currently known values for a single machine.

Values are categorized into two groups:

  • State: requested/commanded values (these typically change only after a state-change request, or if another controller updates them)
  • Live Values: measured/observed values coming from the machine and potentially changing quickly

This REST endpoint returns only the current snapshot, not a stream of live values. To receive continuous updates (via WebSockets), subscribe to the machine namespace (see WebSockets below).

Example request (mock machine)

curl -X GET "https://IP_ADDRESS/api/v2/machine/mock/57922" -u machine:YOUR_PASSWORD

Example response

{
  "machine": {
    "legacy_id": {
      "machine_identification": {
        "vendor": 1,
        "machine": 7
      },
      "serial": 57922
    },
    "serial": 57922,
    "vendor": "QiTech",
    "slug": "mock",
    "error": null
  },
  "state": {
    "frequency1": 100.0,
    "frequency2": 200.0,
    "frequency3": 500.0,
    "is_default_state": false,
    "mode_state": {
      "mode": "Running"
    }
  },
  "live_values": {
    "amplitude1": -0.03438523433309566,
    "amplitude2": -0.06872980145477608,
    "amplitude3": -0.1711138370170743,
    "amplitude_sum": -0.27422887280494607
  }
}

Change machine state POST /api/v1/machine/<slug>/<serial>

State changes are submitted as mutations. The mutation payload is defined per machine type in Rust. Conceptually, each item in the mutation list represents a setter-style operation that is applied by the real-time control loop.

The API does not return the newly-applied state in the POST response. The panel runs a real-time loop and generally won’t block waiting for the physical system to converge. Instead:

  • Submit the mutation via POST
  • Poll GET /api/v2/machine/<slug>/<serial> to observe the updated state and/or any reported errors

Example request (mock machine)

curl -X POST \
  -d  \
  -H "Content-Type: application/json" \
  "https://IP_ADDRESS/api/v1/machine/mock/57922" -u machine:YOUR_PASSWORD

Example response

null

WebSockets

For continuous updates, subscribe to a machine-specific namespace derived from its legacy_id:

  • Namespace: /machine/<vendor>/<id>/<serial>

The stream emits events for:

  • state changes (StateEvent)
  • live value updates (LiveValuesEvent)

Both event payloads use the same machine-specific schema as the /api/v2 REST responses.


List of all machines

Below is a template you can fill with links to the relevant Rust types (mutations + state/live structs). For each machine, link to:

  • Mutations: the request payload type used by POST /api/v1/machine/<slug>/<serial>
  • State / Live Values: the response payload types returned by GET /api/v2/machine/<slug>/<serial>

Machines

Clone this wiki locally