Skip to content

API

The central server exposes a RESTful API for managing scales, settings, fetching historical data, current status, and more. The web interface uses the browser to access the API endpoints, any other service can also execute the same requests.

Most API endpoints have the following request prefix: /api/v1/

The full API endpoint description and documentation can be found on any running instance of the server at /scalar, for example http://localhost:7080/scalar. The API description it shows requires authentication, so log in to the web interface in the same browser first.

For example the endpoint /api/v1/activated (e.g. GET http://localhost:7080/api/v1/activated) returns a JSON encoded boolean value of whether the license is active or not. This endpoint is one of the first things the web interface checks to request a license to be entered.

GET /api/v1/version returns the server version as a JSON string, e.g. "1.0.0". Neither endpoint requires authentication.

The examples below use Host: localhost. Send the requests to the address and port the server listens on, 7080 by default.

Authentication

With some exceptions, nearly all API requests must be authenticated using valid credentials, and all API requests except the version and license checks require an active license. Each API request may be authenticated using one of the 2 following ways:

  • Using a valid HTTP-only session cookie (used by the web interface, stored in the browser)
  • Using a valid access token in the request header (retrieved by using the login endpoint)

The second method is recommended for network services that want to integrate with the central server.

Creating the first account

First, you must ensure that an account exists. This can be done through the web interface or by using the API endpoint to create a user. On initial startup the web interface prompts for the default admin account creation, which is the same as executing a request at this endpoint:

POST /api/v1/users/admin HTTP/1.1
Host: localhost
Content-Type: application/json

{"username":"<username>","password":"<password>"}

This request fails with 401 Unauthorized if an account already exists.

Logging in

To obtain the authentication token, you must use the /api/v1/users/login endpoint.

Note the useCookies=false parameter to prevent the server from setting a session cookie, and return an access token response instead. If set to true, the server returns an HTTP cookie intended for browsers instead.

POST /api/v1/users/login?useCookies=false HTTP/1.1
Host: localhost
Content-Type: application/json

{"username":"<username>","password":"<password>"}

The response will be of the following format:

{
    "tokenType": "Bearer",
    "accessToken": "<access token>",
    "expiresIn": 3600,
    "refreshToken": "<refresh token>"
}

Make sure to store both the accessToken and refreshToken values somewhere secure.

The string under accessToken represents the secure token that must be used in the Authorization header of every authenticated request. This token expires after 1 hour (expiresIn is in seconds).

A wrong username or password is answered with 401. After 5 failed attempts the account is locked for 5 minutes; while it is locked, the response is 400 and the errors.endDate field holds the time the lock ends.

Refreshing the access token

In order to avoid having to log in again after 1 hour, call the /api/v1/users/refresh endpoint with the previously received refreshToken, as such:

POST /api/v1/users/refresh HTTP/1.1
Host: localhost
Content-Type: application/json

{"refreshToken":"<refresh token>"}

The response is the same as for the login request. You will receive a new accessToken which expires in 1 hour and a new refreshToken which expires in 14 days. An expired or invalid refresh token is answered with 401; log in again in that case.

If the user is updated (e.g. a new password or roles) or deleted in the meantime, the refresh token is invalidated. You will be able to keep using the access token until it expires for endpoints that have nothing to do with user-specific information.

With a cookie type session, the server automatically renews the cookie when it is close to the expiration time, by returning the cookie along with a response to any API call where the cookie was passed, which the browser will know to replace.

Making authenticated requests

Let's say that you want to get the current status of all devices known by the server. For the request to go through, you need to include the Authorization header with the accessToken you received from the login or refresh token request.

The value of the Authorization header is the token type (Bearer) followed by a space and the accessToken value.

GET /api/v1/devices/states HTTP/1.1
Host: localhost
Authorization: Bearer <access token>

Example response:

{
    "01997046-fe18-78bf-8895-fed35b18b997": {
        "connectionStatus": 4,
        "observingWeight": true,
        "weight": {
            "statusBits": 112,
            "alibiText": null,
            "deviceId": "01997046-fe18-78bf-8895-fed35b18b997",
            "significantDigits": 1,
            "protocol": 1,
            "status": 0,
            "unit": 0,
            "net": 93,
            "gross": 161.6,
            "tare": 68.600006,
            "stable": true,
            "inZeroRange": false,
            "time": "2025-09-30T12:37:23.9714247+00:00"
        }
    }
}

Enumerations are sent as numbers:

Field Values
connectionStatus 0 disconnected, 1 error, 2 pending (waiting to reconnect), 3 connecting, 4 connected
protocol, deviceProtocol 0 RedBox, 1 ASCII
unit 0 kg, 1 lb
status 0 OK, any other value is an error code reported by the scale

Permissions and errors

Endpoints that change data or send commands to scales require the Manager or Admin role; managing accounts and the license requires the Admin role. See Roles and accounts.

Errors are returned as JSON problem details, with the following status codes:

Status Meaning
400 Invalid input
401 Not authenticated, or wrong credentials
403 Not permitted: the account lacks the required role, the license does not cover the function, or the ASCII command is not allowed
404 The scale (or other resource) was not found
409 Conflict, e.g. an RDC weight that was already uploaded
422 The scale answered, but the result cannot be used: the weight is not stable, or the scale reported an error status
504 The scale did not answer in time

Scale management using the API

Most endpoints allowing you to get current scale status, historical data, update scales, require the use of the scale ID. This is a unique identifier the server randomly generates for each scale, and cannot be customized.

Therefore, the first step will usually be to list the available scales using the /api/v1/devices endpoint.

GET /api/v1/devices HTTP/1.1
Host: localhost
Authorization: Bearer <access token>

The response will enumerate all available scales, except deleted ones:

[
    {
        "id": "01997046-fe18-78bf-8895-fed35b18b997",
        "uidName": "6CCE8D",
        "customId": "103",
        "customName": null,
        "networkLocation": "192.168.0.100",
        "lastConnected": "2025-09-30T12:37:42.46625+00:00",
        "updatedAt": "2025-09-22T07:15:24.824767+00:00",
        "locationValid": true,
        "managed": true,
        "deleted": false,
        "deviceProtocol": 1
    },
    {
        "id": "01997047-2089-7f3b-9526-d8b8de694dbe",
        "uidName": "14F290",
        "customId": null,
        "customName": null,
        "networkLocation": "192.168.0.101",
        "lastConnected": "2025-09-30T13:24:18.035218+00:00",
        "updatedAt": "2025-09-22T07:15:33.641574+00:00",
        "locationValid": true,
        "managed": false,
        "deleted": false,
        "deviceProtocol": 0
    }
]

About scale fields & names

The scale uidName (Scale unique name in the web interface) is the unique name of the scale as it was fetched from the scale using its respective protocol. It is also unique and cannot be changed.

The requirement for having and using a random unique id is because scales may also be added manually without ever having to connect to them, as such for these scales the uidName will always be null (e.g. scales intended to be used for RDC).

Scales can also be assigned a customName, which is nothing more than a user-defined name for the scale, for convenience. It appears in the web interface of the central server to more easily identify scales. This name does not have to be unique and may be changed at any time, no APIs require it to be sent.

Lastly, scales may also be assigned a customId which will be elaborated upon below.

locationValid is false when another scale has since been found at the same networkLocation. Weight requests and commands to a scale whose location is not valid are answered with 404.

Requesting weights

One of the most common use cases for the central server is to provide unified access to scales. The only prerequisite to access a scale using the API is that the scale is known by the server, either because it was auto-discovered or was added manually, and that the license includes the scale management feature. After obtaining the scale's id, you can request the current weight, regardless of protocol (ASCII/RedBox), using the endpoint /api/v1/devices/{id}/weight.

GET /api/v1/devices/01997046-fe18-78bf-8895-fed35b18b997/weight HTTP/1.1
Host: localhost
Authorization: Bearer <access token>

The central server weight response includes all known weighing information in one message, with data on how to display the given weight. The exact format varies slightly between protocols. The RedBox weight response includes much more information: scale interval index, X/Y angles, totalization data, weigh in motion progress and some extra flags.

The RedBox protocol response includes everything in the ASCII response + additional fields, with the exception that the alibiText field is now the alibiNr: the alibi is always a number in the RedBox, while for ASCII it is possible to have any string, though it is usually numerical.

ASCII example:

{
    "statusBits": 112,
    "alibiText": null,
    "deviceId": "01997046-fe18-78bf-8895-fed35b18b997",
    "significantDigits": 1,
    "protocol": 1,
    "status": 0,
    "unit": 0,
    "net": 93,
    "gross": 161.6,
    "tare": 68.600006,
    "stable": true,
    "inZeroRange": false,
    "time": "2025-09-30T14:34:31.3197938+00:00"
}

RedBox example:

{
    "scaleNumber": 0,
    "alibiNr": 0,
    "wiMProgress": 0,
    "canBeShown": true,
    "safetyCriticalError": false,
    "xAngle": -0.5827853,
    "yAngle": 0.45657697,
    "totalFinalized": false,
    "totalNeedToSeeZero": false,
    "totalBiggestScaleIntervalIndex": 0,
    "totalNumberOfWeighings": 0,
    "totalNet": 0,
    "totalGross": 0,
    "deviceId": "01997047-2089-7f3b-9526-d8b8de694dbe",
    "significantDigits": 1,
    "protocol": 0,
    "status": 0,
    "unit": 0,
    "net": 1,
    "gross": 1,
    "tare": 0,
    "stable": true,
    "inZeroRange": false,
    "time": "2025-09-30T14:46:11.8676344+00:00"
}

POST /api/v1/devices/{id}/save-current-weight (requires the Manager role) reads the current weight in the same way and stores it as a saved weight. It fails with 422 if the weight is not stable or the scale reports an error status.

Scale commands

Common commands

The following commands are supported for both ASCII and RedBox protocols. They require the Manager role and the scale management feature:

  • Set Zero: POST /api/v1/devices/{id}/zero

    empty body

  • Automatic Tare: POST /api/v1/devices/{id}/auto-tare

    empty body

  • Manual tare: POST /api/v1/devices/{id}/manual-tare

    body containing a JSON encoded floating point number, e.g. 12.5

If the scale answers with an error code, the request fails with 422.

Note about scale commands and weight requests

If the requested device is managed, the request is immediately processed using the active connection. If the device is not connected at that moment, the request waits for about 2 seconds before failing with 504.

If the device is not managed, the central server attempts to establish a connection to the device, then processes the request. Here the server waits at most 30 seconds for the connection to be established before failing with 504.

After the request is completed, the scale remains connected for another 30 seconds, with each subsequent request resetting this timer. The connection is closed when no request is made for 30 seconds.

ASCII specific commands

Devices using the ASCII protocol have the following additional commands:

  • ASCII Command: POST /api/v1/devices/{id}/ascii-command

    body containing the command name as a JSON string (e.g. "GG"), allowed values are: GG, GN, GT, SZ, RZ, SR, RS, GP, GA, MN, MG, AN, AG. Other commands are refused with 403. The response is the scale's answer.

  • Reconfigure: POST /api/v1/devices/{id}/ascii-reconfigure

    empty body. This command re-fetches and saves the updated ASCII parameters from the scale. This is useful if scale parameters like the unit label change. Unlike with RedBox devices, the central server cannot detect these changes normally, and regularly fetching ASCII parameters may cause performance issues with the scale.

Weight history

The saved weights and weight updates can be read page by page:

  • GET /api/v1/devices/saved-weights: saved weights, requires the RDC or the data collection feature
  • GET /api/v1/devices/weight-changes: weight updates, requires the data collection feature

Both return at most 1000 records per request. The /export variants (/api/v1/devices/saved-weights/export, /api/v1/devices/weight-changes/export) return the records as a CSV file, at most 100 000 per request. The filters (scales, time range, status, source and others) are query parameters, described at /scalar.

Uploading weights

Weights weighed elsewhere can be uploaded to the server and are stored as saved weights. These routes require the RDC feature. Whether they require authentication depends on the Require authentication for legacy routes setting (see Security).

  • POST /api/v1/devices/save-weight
  • POST /api/v1/devices/save-weight/redbox: the same, with the additional RedBox fields inZeroRange, scaleNumber, totalNumberOfWeighings, totalNet, totalGross, xAngle and yAngle
POST /api/v1/devices/save-weight HTTP/1.1
Host: localhost
Authorization: Bearer <access token>
Content-Type: application/json

{
    "deviceId": "01997046-fe18-78bf-8895-fed35b18b997",
    "alibi": "1234",
    "significantDigits": 1,
    "status": 0,
    "unit": 0,
    "net": 93,
    "gross": 161.6,
    "tare": 68.6,
    "time": "2025-09-30T14:34:31+00:00",
    "customFields": {"Product": "A12"}
}

deviceId is the scale's id. A status other than 0 is refused with 400, an unknown deviceId with 404. Without time, the time of receipt is used.

The RDC HTTP upload route is described under Legacy API.

Application settings

The application settings can be read with GET /api/v1/settings and changed with POST /api/v1/settings (requires the Manager role). The body contains only the settings to change; the response contains all settings. Settings the license does not allow are reset in the response.

POST /api/v1/settings HTTP/1.1
Host: localhost
Authorization: Bearer <access token>
Content-Type: application/json

{"broadcastSelf": false}
Setting In the web interface
receiveRdc, receiveRdcPort RDC server
discoverRedBoxes Discover RedBox scales
discoverAscii Discover ASCII scales
broadcastSelf not shown, see Server discovery responder
noMessageTimeoutMs Disconnect timeout
reconnectLinearIntervalStepMs Reconnection time step
maximumReconnectIntervalMs Reconnection maximum time
enableDataCollection Data collection
collectDeviceWeights Collect weight updates
collectAppDeviceLogs Collect device-related application logs
collectDeviceLogs Collect RedBox device logs
logsRetentionTimeSeconds Application and device logs retention time
weightRetentionTimeSeconds Device weight retention time
requireAuthForScaleManagement Require authentication for legacy routes

Unknown settings and values out of range are refused with 422.

Legacy API

Each scale may be assigned a Custom ID. This is a user-defined value that must be either null or unique. This identifier also appears next to the device name in the UI (preceded by a hash sign).

This can be used as a way to identify scales similar to customName (with the unique requirement), but it mainly exists for what we call the legacy APIs. These APIs match the requests and responses of the old RAVAS Integration Server (RIS) and RAVAS Data Collector (RDC):

  • POST /rest/scale/weight: upload a weight, as the RDC did over HTTP
  • GET /rest/scale/{customId}/weight/gross: Get current gross weight
  • GET /rest/scale/{customId}/weight/net: Get current net weight
  • GET /rest/scale/{customId}/weight-alibi-nr/gross: Get gross with alibi
  • GET /rest/scale/{customId}/weight-alibi-nr/net: Get net with alibi

Whether these routes require authentication depends on the Require authentication for legacy routes setting (see Security), enabled by default. When enabled, authenticate as for any other request.

Reading weights

The GET routes require the scale management feature. They only work with ASCII scales, found by their Custom ID, whose location is valid; any other scale is answered with 404. The weight/gross and weight/net routes accept a noMotion=true query parameter, which sends the scale's no-motion command (MG or MN instead of GG or GN). The alibi routes send AG or AN.

Example request and response

GET /rest/scale/103/weight/gross?noMotion=true HTTP/1.1
Host: localhost
Authorization: Bearer <access token>
{
    "timestamp": "2025-09-30 15:43:56.419",
    "alias": "103",
    "type": "GROSS_WEIGHT_NO_MOTION",
    "weight": 162.4
}

The timestamp is the server's local time. The type field depends on the route:

Route type
weight/gross GROSS_WEIGHT, or GROSS_WEIGHT_NO_MOTION with noMotion=true
weight/net NET_WEIGHT, or NET_WEIGHT_NO_MOTION with noMotion=true
weight-alibi-nr/gross GROSS_WEIGHT_NO_MOTION_WITH_ALIBI
weight-alibi-nr/net NET_WEIGHT_NO_MOTION_WITH_ALIBI

The alibi routes add the alibi number in an alibiNr field. If the scale answers with an error, or with something that cannot be read as a weight, the request fails with 422; if it does not answer in time, with 504.

Uploading weights over HTTP

POST /rest/scale/weight requires the RDC feature and stores the weight like a record received by the RDC service.

POST /rest/scale/weight HTTP/1.1
Host: localhost
Authorization: Bearer <access token>
Content-Type: application/json

{
    "scaleId": "103",
    "operatorId": "7",
    "sequenceNr": 15,
    "weightUnit": "kg",
    "grossWeight": 161.6,
    "netWeight": 93,
    "tareWeight": 68.6,
    "alibiNumber": "1234",
    "weighingDate": "2025-09-30",
    "weighingTime": "15:43",
    "totalWeighing": 0,
    "totalWeight": 0,
    "productId1": "",
    "productId2": "A12",
    "productId3": "",
    "productId4": ""
}
  • scaleId, grossWeight, netWeight and tareWeight are required.
  • scaleId is matched against the scale's Custom ID, Scale unique name or id.
  • weightUnit is kg or lb; anything other than lb is stored as kg.
  • weighingDate may be yyyy-MM-dd, dd-MM-yyyy or MM-dd-yyyy (a date that fits both of the last two is read as dd-MM-yyyy), weighingTime is HH:mm, both in the server's time zone. If they cannot be read, the time of receipt is used.
  • productId1 to productId4 are stored as Field #1 to Field #4, skipping empty ones; in the example, A12 is stored as Field #2.

A successful upload is answered with:

{"statuscode": 200, "statusmessage": "OK"}

An unknown scaleId is answered with 404. A weight with the same sequenceNr and alibiNumber as one already stored for the scale is answered with 409 and not stored again.