Skip to content
Proxus 2.0.0 Proxus 2.0: the largest release in Proxus history Release notes

How-to guide · for Developers, Administrators

Historical import

Send older readings of a device to the Proxus historian in small batches over HTTP, with a key that makes every batch safe to retry.

At the end of this guide, your program sends readings that a device recorded in the past (from a data logger, a CSV export or a machine's own memory) to the Proxus historian. They are stored next to the device's live values and appear in trends, reports and the Telemetry API.

Before you start

You need:

  • The device in Proxus, enabled, on a running edge gateway. Note its ID (the Oid in the REST API) and its Token (shown on the device page).
  • Network access to the gateway's HTTP port, 8083 by default (Server-Port in [Service]).
  • Historical import turned on. It is off in the delivered configuration; see the next section.

Turn historical import on

Set these keys, then restart the hub and the gateways:

WhereKeyValue
Hub and every gateway that receives importsHistoricalImport__Enabledtrue
The gateway that writes the Proxus historian (the hub's SYSTEM gateway in a standard installation)HistoricalImport__StorageEnabledtrue

While import is off, the endpoints answer 503.

Step 1: Send a batch

POST http://<gateway>:8083/api/v1/devices/<device ID>/historical/batches
X-IoT-Token: <device token>
Idempotency-Key: lys-packer-04-2026-10-01-0001
Content-Type: application/json
{
  "records": [
    { "key": "Temperature", "time": "2026-10-01T06:00:00.000Z", "type": "Float", "value": 24.6, "unit": "°C" },
    { "key": "Speed",       "time": "2026-10-01T06:00:00.000Z", "type": "UShort", "value": 82, "unit": "rpm" },
    { "key": "Running",     "time": "2026-10-01T06:00:00.000Z", "type": "Bool", "value": true }
  ]
}
FieldRules
records1 to 50 records.
keyThe tag name, up to 256 characters.
timeISO 8601 with Z or an offset such as +02:00, whole milliseconds at most, not in the future, not before 1900.
typeExactly one of Bool, Short, UShort, Int, UInt, Float, Long, ULong, Double, String, Bytes, DateTime (case matters).
valueA JSON value that fits type: true/false for Bool, a number for the numeric types, a string for String (up to 4096 characters), Base64 text for Bytes, an ISO 8601 string for DateTime. Long and ULong must be within ±9007199254740991.
unitOptional, up to 64 characters.

Other fields in the body are refused. The whole body may be at most 256 KiB.

The Idempotency-Key names the batch: 8 to 128 letters, digits, -, _ or .. Sending the same key with the same body again is safe and returns the first answer. Sending the same key with a different body is refused. Use one key per batch, for example the source file name and a batch number.

Step 2: Read the answer

A new batch is answered with 202 Accepted, a repeated one with 200. The Location header points at the batch.

{
  "jobId": "5b0e6a5c-6f4e-4a0e-9a59-3f8f0f8c2d11",
  "state": "Pending",
  "results": [
    { "index": 0, "state": "Pending" },
    { "index": 1, "state": "Pending" },
    { "index": 2, "state": "Rejected", "error": "InvalidTypeOrValue" }
  ],
  "storageDataset": "DeviceRawData"
}

Each record has its own result, in the order you sent them. Rejected records are not stored; the others are.

Record errorCause
InvalidRecordMissing or too long key, too long unit, or no value.
InvalidTimestamptime missing, in the wrong format, in the future, before 1900 or finer than a millisecond.
InvalidTypeOrValueUnknown type, or a value that does not fit it.
MeasurementConflictThe batch has the same tag and time twice with different values. The same tag, time and value twice is marked Duplicate instead.

Step 3: Follow the batch

GET http://<gateway>:8083/api/v1/devices/<device ID>/historical/batches/<jobId>
X-IoT-Token: <device token>
Batch stateMeaning
PendingAccepted, being written.
CompletedEvery accepted record is stored.
CompletedWithErrorsDone, and at least one record was rejected.
NeedsReconciliationThe storage did not confirm some records. Their result is Uncertain. Send the same batch again later with the same key.

Record states after writing: Stored, Duplicate (the same value for that tag and time is already stored), Rejected or Uncertain.

Answers without a batch

StatusBody or headerMeaning
400{"error":"InvalidIdempotencyKey"}The Idempotency-Key header is missing or not in the allowed form.
400{"error":"InvalidJson"} or {"error":"InvalidBatch"}The body is not JSON, has unknown fields, or has no records or more than 50.
401Missing X-IoT-Token, or the token does not belong to this device ID, or the device is disabled.
404No batch with this ID for this device.
409{"error":"IdempotencyConflict"}This key was used before with a different body.
413The body is larger than 256 KiB.
415Content-Type is not JSON.
429Retry-After: 5The gateway is busy (8 requests at a time), or too many batches are still being written (8 per device, 64 in total). Wait and send again with the same key.
503Import is turned off, or the hub cannot be reached. Send again later with the same key.

Example in Python

import_history.py
import time
import requests

GATEWAY = "http://localhost:8083"
DEVICE_ID = 69
DEVICE_TOKEN = "<the device's token>"


def send_batch(key, records):
    while True:
        response = requests.post(
            f"{GATEWAY}/api/v1/devices/{DEVICE_ID}/historical/batches",
            json={"records": records},
            headers={"X-IoT-Token": DEVICE_TOKEN, "Idempotency-Key": key},
            timeout=30,
        )
        if response.status_code in (429, 503):
            time.sleep(int(response.headers.get("Retry-After", "5")))
            continue
        response.raise_for_status()
        return response.json()


batch = [
    {"key": "Temperature", "time": "2026-10-01T06:00:00.000Z", "type": "Float", "value": 24.6, "unit": "°C"},
    {"key": "Temperature", "time": "2026-10-01T06:01:00.000Z", "type": "Float", "value": 24.9, "unit": "°C"},
]
job = send_batch("lys-packer-04-2026-10-01-0001", batch)
print(job["state"], [r["state"] for r in job["results"]])

What's next

Was this page helpful?

Evaluating Proxus? See it on your own machines in a 30-minute technical session.