REST Interface¶
The REST API is the primary interface to configure and control the sensor. It is JSON over HTTP on port 80, or port 443 with HTTPS.
Base URL and JSON Envelope¶
Every response uses the same envelope. header.status = 0 means success:
The example is the response to GET /api/LocationName. The key inside data always matches the endpoint name exactly, including capitalization.
Reading vs. Writing¶
Reading vs. Writing: operation, method, and authentication.
| Operation | Method | Authentication |
|---|---|---|
| Read a parameter | GET /api/<Variable> |
None |
| Write a parameter | POST /api/<Variable> |
Challenge-response |
| Call a protected method (reboot, defaults, teach-in, …) | POST /api/<Method> |
Challenge-response |
| Binary file transfer (backup, firmware) | GET/PUT /api/parameterbackup, PUT /api/update where supported |
Session token where required by firmware |
A POST to a parameter changes only the working copy in RAM. The change is lost at the next power cycle unless you persist it:
RebootDevice also persists RAM to EEPROM before it reboots. SoftReset and a power cycle discard unsaved changes. See Checksums for how this shows in MD5Parameters.
User Levels¶
Writes require an enabled user level. At the factory, only Service is enabled:
User Levels: level and factory default.
| Level | Factory default |
|---|---|
| Maintenance | Disabled |
| Authorized Client | Disabled |
| Service | Enabled |
Change passwords with changePassword and enable other levels with EnableUserLevel. See User Levels.
Authentication¶
Authentication: method, use case, and reference.
| Method | Use case | Reference |
|---|---|---|
| Challenge-response | Every POST: parameter writes and method calls |
Challenge-response |
| Session token | Binary file transfer: configuration backup and firmware upload | Session token |
Challenge-Response Authentication¶
Protected POST requests use challenge-response authentication. The client
proves that it knows the password with a SHA-256 hash chain; the password
itself is never sent. getChallenge and some credential-check endpoints are
exceptions because they start or test the authentication flow.
For a Python implementation and usage examples, see sick_scan_rest_client. The client handles challenge-response authentication for protected REST requests.
-
Request a challenge for the user level that will send the request. The challenge is returned in the top-level
challengeobject, not indata:{ "header": { "status": 0, "message": "Ok" }, "challenge": { "realm": "SICK Sensor", "nonce": "e03caead8342067f4b91fefab37cb4fea551ab3adbd1739785657baf54a598ca", "opaque": "9ec7f4b6f6a26b11c4b4257c1feee26e1a7511d3f9d806d5b2b64fe9868062cc", "salt": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] } } -
Compute the response hash.
endpointis the path without/api/, for exampleLocationName:hash1 = SHA256("<user>:<realm>:<password>:" + salt_bytes) # with salt hash1 = SHA256("<user>:<realm>:<password>") # without salt hash2 = SHA256("POST:<endpoint>") response = SHA256("<hash1>:<nonce>:<hash2>")salt_bytesare the raw byte values of thesaltarray, appended after the colon, not the JSON text of the array. If the challenge contains asaltfield, use the salted form; an unsaltedhash1is rejected withheader.status4 (Access Denied). All hashes are lowercase hex strings.import hashlib def challenge_response(user, password, challenge, endpoint): secret = f"{user}:{challenge['realm']}:{password}".encode() if challenge.get("salt") is not None: secret += b":" + bytes(challenge["salt"]) hash1 = hashlib.sha256(secret).hexdigest() hash2 = hashlib.sha256(f"POST:{endpoint}".encode()).hexdigest() return hashlib.sha256(f"{hash1}:{challenge['nonce']}:{hash2}".encode()).hexdigest() -
Send the request with the authentication fields in
header:
Fetch a new challenge immediately before every protected POST and use it for
that one request only; do not cache or share challenges. Requesting a challenge
for a different user level invalidates the pending challenge, and a request
that still uses it fails with header.status 10 (Invalid Challenge). If
several clients or threads write to the same sensor, serialize the
challenge-and-POST sequence, and retry once with a new challenge on status 10.
The Postman pre-request script is a complete, working implementation of this algorithm.
Session Token Authentication¶
Binary file transfers such as configuration backup and firmware upload can use
a session token instead of the JSON header object. Check the matching OpenAPI
file for the exact file-transfer authentication required by your firmware.
- Create a token with
POST /api/CreateSessionTokenat Service level. The response containsdata.tokenand its lifetime indata.timeToLive. - Send the token in the
X-Session-Tokenheader of eachGET/PUTfile transfer. - Reuse the token for several transfers until it expires.
See Backup & Restore and Firmware Update for complete sequences.
Status Codes and Errors¶
The REST API answers every request with HTTP 200 OK, including failed requests. Check header.status in the JSON response: only 0 means success.
Status Codes and Errors: status, message, typical cause, and fix.
| Status | Message | Typical cause | Fix |
|---|---|---|---|
| 0 | Ok | Request succeeded | - |
| 1 | Parsing Failed | Body is not valid JSON, or a required data field is missing |
Compare the body with the OpenAPI schema |
| 2 | Invalid Data | The data key does not match the endpoint name (case-sensitive), or a value has the wrong type |
Use the endpoint name as data key |
| 3 | Internal Server Error | For example, getChallenge with an unknown user name |
Use Service, Maintenance, or AuthorizedClient |
| 4 | Access Denied | Wrong password, missing or wrong header, hash computed for another endpoint, user level not enabled, or authentication temporarily locked |
Check the password, the user level, and the hash; see the lock below |
| 5 | Not Found | Unknown endpoint, or wrong HTTP method, for example GET on a method |
Check the endpoint name and method in the OpenAPI file |
| 6 | Out Of Range | Value outside the allowed range | Check the limits in the OpenAPI file |
| 7 | Out Of Bounds | Value outside the allowed bounds, for example the user name Authorized Client with a space |
Check the allowed values |
| 8 | Read Only | Write to a read-only variable | Only read the variable |
| 9 | Illegal Value | Value not in the allowed set, for example an undefined enum value | Use a value listed in the OpenAPI file |
| 10 | Invalid Challenge | The challenge was invalidated by a challenge for another user level | Fetch a new challenge and retry once |
| 11 | Out Of Connections | Too many simultaneous connections | Close idle connections and retry |
After five failed logins in a row, the device locks authentication for 30 seconds. During the lock, getChallenge itself answers with header.status 4, so even the correct password fails. Bursts of many getChallenge requests in a short time are rejected in the same way for a few seconds. Wait at least 30 seconds before retrying instead of retrying immediately.
Real HTTP error codes occur only for binary file transfers:
Status Codes and Errors: HTTP status, cause, and fix.
| HTTP status | Cause | Fix |
|---|---|---|
| 403 | GET or PUT /api/parameterbackup without a valid X-Session-Token |
Create a new session token |
| 404 | GET /api/parameterbackup before a backup file has been created |
Call CreateParameterBackup first |
OpenAPI¶
OpenAPI (formerly Swagger) is a machine-readable description of every REST endpoint: paths, parameters, and request and response schemas. Use it to generate a typed client in almost any language, or import it into a REST client.
SICK publishes an OpenAPI file for each firmware. Download it from the SICK product page under Software, or use the files in this guide:
- picoScan100 REST API reference
- multiScan100 REST API reference
- multiScan200 REST API reference
- LRS4000 REST API reference
The OpenAPI file does not describe the challenge-response authentication. Configure your client to compute it, or use Insomnia or Postman with the prepared SICK plug-in or script.
Related Articles¶
How to use the OpenAPI file with Insomnia.