-

Please Enter Your Search
search icon
Nothing found for your search
Search results from other manuals
Nothing found for your search

1 Connect and authenticate

The API lives at https://<device>/api/. Authentication is a session cookie obtained by posting your web-interface credentials to /api/login. There is no API key and no bearer token.

1.1 Switch on remote access

A new Kilobaser answers on its touchscreen only. Remote access has to be enabled once, by hand, at the machine — the manual calls this the visibility of the device, and the setting is described in Remote web interface in Preparation.

On the touchscreen, open Settings → Security and turn on device visibility / HTTPS access. The Kilobaser generates a certificate for itself and starts listening. Until then, requests to port 443 are refused and plain HTTP redirects to a page explaining that remote access is off.

The same settings sections are reachable from a browser once HTTPS is on, though the HTTPS switch itself lives at the Kilobaser:

The settings menu on the device, listing network, security, system, users and cartridge sections

Network, security and users are admin-only; a user account sees a shorter list.

em CAUTION
Enabling remote access makes the Kilobaser reachable by anyone who can route to it. It has no rate limiting and no lockout on failed logins. Put it on a network where that is acceptable.

1.2 The certificate

The certificate the device generates is self-signed, so nothing will trust it out of the box. Every example in this guide passes --insecure (curl) or verify=False (Python) for that reason.

That is fine while you are finding your feet and not fine in production, because it disables the check that you are talking to the machine you think you are. Two better options:

Pin the device's own certificate. Fetch it once, keep it with your code, and check against it:

openssl s_client -connect kilobaser.lab.example.org:443 -showcerts </dev/null 2>/dev/null \
  | openssl x509 > kilobaser.pem

curl --cacert kilobaser.pem https://kilobaser.lab.example.org/api/status

The device replaces its certificate before it expires, so this needs re-fetching about once a year.

Install your own certificate. If your site issues certificates, upload one with POST /api/settingsUser/sslFiles and the problem goes away permanently. This needs an admin account.

1.3 Log in

The device login screen in a browser

curl --insecure -c cookies.txt \
  -X POST https://kilobaser.lab.example.org/api/login \
  -H 'Content-Type: application/json' \
  -d '{"username": "apibot", "password": "..."}'
{
  "id": "55d56ae5-6484-44f2-9f60-2b75fa3f0b96",
  "expiresAt": "2026-09-09T22:08:26.625789374Z",
  "user": { "id": "admin", "name": "Administrator", "role": "admin" }
}

The response carries a Set-Cookie header:

set-cookie: session=55d56ae5-6484-44f2-9f60-2b75fa3f0b96; Expires=Wed, 09 Sep 2026 22:08:26 GMT; HttpOnly

Send that cookie on every subsequent request. Any HTTP client with a cookie jar does this for you; if yours does not, the session id is also in the response body as id, so you can build the header yourself:

curl --insecure -H 'Cookie: session=55d56ae5-6484-44f2-9f60-2b75fa3f0b96' \
  https://kilobaser.lab.example.org/api/status

Note that username is the account id, which is not always what the interface displays. The account shown as "Administrator" logs in as admin.

PUT /api/logout ends a session. You do not have to call it — sessions expire on their own after a month — but a long-running service that reconnects should, rather than accumulating sessions.

1.4 Sessions do not survive a restart

Sessions are kept in the device's memory. When the Kilobaser reboots, or its software is updated, every session is gone, regardless of the expiry date it advertised.

Any client that runs longer than a few minutes has to handle this. The symptom is a request suddenly failing with:

{"error": "{\"code\": \"2-1-4\", \"message\": \"Session cookie was not provided\"}"}

Note the status code: 400, not 401. Nothing in this API returns 401, so a client that watches for it will loop forever instead of logging back in. Branch on the error code instead. kb_client.py does exactly this — it logs in again and retries once, and then gives up so a genuine credentials problem does not become an infinite loop.

1.5 Roles

Every account has one of two roles that matter here.

user admin
Queue, start, answer, cancel runs yes yes
Read status, consumables, oligo yield yes yes
Handle errors yes yes
Manage accounts (/api/users) no yes
Security and network settings no yes

em CAUTION
Two admin-only calls are destructive and easy to trigger by accident. POST /api/users takes the entire list of accounts and deletes any account missing from it, so always read the list, change one entry, and send the whole thing back. PUT /api/settingsUser/security carries a factoryReset field which, if set true, wipes the Kilobaser.

Give your integration a user account unless it genuinely needs to manage the device. Everything in this guide except managing accounts works with one. Create a dedicated account rather than reusing a person's, so the run history shows which submissions came from your system.

A request made with insufficient rights returns 403 and code 2-1-5.

There are also dev and clientdev roles used by Kilobaser for development and servicing. They cannot log in at all unless the device has been put into developer mode, and nothing in this guide requires them.

1.6 Request rules

Anything with a body must declare it as JSON. Omitting the header gets you a 415 whose message does not mention the header you forgot:

{"error": "Bad Content-Type or charset, expected 'application/json'"}

Errors arrive double-wrapped. The body is an object whose error field is itself a JSON document, as a string:

{
  "error": "{\n  \"code\": \"2-16-2\",\n  \"message\": \"user/password combination not found\"\n}"
}

So reading the code out means parsing twice:

import json
detail = json.loads(response.json()["error"])
print(detail["code"], detail["message"])

Branch on code, which is stable, rather than on message, which is prose and may be reworded. A few errors — the 415 above among them — put a plain string in error instead, so parse defensively. See error codes for the full list.

Identifiers contain colons. Queue entries and runs are identified by strings like 2026-08-09T22:05:25Z-0be17442. They are opaque: do not parse them, and do remember to URL-encode them if your HTTP library does not.

Listings are paged at 15. GET /api/processRuns and GET /api/processRuns/queue take from and limit. The convenient alternative is GET /api/init, which returns the whole current queue in one go; see live state.

1.7 Check that it works

curl --insecure -b cookies.txt https://kilobaser.lab.example.org/api/settingsUser/systemInformation
{
  "serialNr": "KS000000",
  "firmwareVersion": "1.5.2",
  "softwareVersion": "1.5.2",
  "userTimezone": "Europe/Vienna",
  "recommendedCartridgeType": "2",
  "recommendedChipKind": "2"
}

If that returns, you are connected and authenticated. Quote serialNr and softwareVersion in any support request.