The ingest API is one endpoint, POST /v1/ingest. Anything that can make an HTTPS request can use it: scripts, edge gateways, PLC bridges, cloud functions and integration tools.
Set up
- Create the site and machines
Create them in the app or with
POST /v1/sitesandPOST /v1/machines. Set each machine'sexternalIdto the name your source uses (for exampleB-101), so messages can address it without knowing InduQT ids. - Create an API key
In Settings → API keys, create a key with the
ingestscope, limited to the site the data belongs to. See site-scoped keys. - Send a reading
Name the machine by id or
externalIdand send numeric values by signal key.
curl -X POST "https://api.induqt.ai/v1/ingest" \
-H "Authorization: Bearer $INDUQT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"machine": "B-101",
"siteId": "6f1c2c0e-4b1a-4c55-9d0e-1f2a3b4c5d6e",
"ts": "2026-10-27T03:12:09Z",
"values": {
"steam_pressure": 112.4,
"steam_flow": 2.1,
"flue_o2": 3.2,
"stack_temp": 410
}
}'{
"accepted": 4,
"rejected": 0,
"machines": [
"0b7d9a12-7c3e-4f10-a2b4-c5d6e7f8a9b0"
]
}Body fields
| Name | Type | Description |
|---|---|---|
machine | string | Machine id or its externalId. Required unless each reading names its machine. |
siteId | string | Needed to resolve an externalId when the key is not tied to one site. |
ts | ISO 8601 string | epoch milliseconds | Reading time. Default: time received. |
values | object of number | boolean | Signal key → value. Keys: letters, digits, _ . - (max 64). Booleans become 0/1; numeric strings are parsed. |
readings | array | Batch form: [{ machine?, ts?, values }]. |
autoCreate | boolean | Create a machine (family "other") for an unknown externalId at the site. Counts towards the plan. |
- Use a key with the ingest scope. A site-scoped key can only write to that site.
- Unknown machines are counted in rejected with a reason in errors[]; if nothing is accepted the response is 400.
- Readings for the same machine, signal and timestamp overwrite each other, so retries are safe.
- Rate limit: 600 requests a minute per key. Batch when sending more than a few readings a second.
Batches
To send several readings, or several machines, in one request use readings. Each reading can name its own machine and time; ts takes ISO 8601 or epoch milliseconds.
{
"siteId": "6f1c2c0e-4b1a-4c55-9d0e-1f2a3b4c5d6e",
"readings": [
{
"machine": "B-101",
"ts": "2026-10-27T03:12:00Z",
"values": {
"steam_pressure": 112.1,
"steam_flow": 2.08
}
},
{
"machine": "B-101",
"ts": "2026-10-27T03:12:05Z",
"values": {
"steam_pressure": 112.4,
"steam_flow": 2.1
}
},
{
"machine": "B-102",
"ts": 1793070725000,
"values": {
"steam_pressure": 98.7,
"burner_on": 1
}
}
]
}Examples
import os, requests
r = requests.post(
"https://api.induqt.ai/v1/ingest",
headers={"Authorization": f"Bearer {os.environ['INDUQT_API_KEY']}"},
json={"machine": "B-101", "values": {"steam_pressure": 112.4, "steam_flow": 2.1}},
timeout=10,
)
r.raise_for_status()
print(r.json()) # {'accepted': 2, 'rejected': 0, ...}const res = await fetch('https://api.induqt.ai/v1/ingest', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.INDUQT_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ machine: 'B-101', values: { steam_pressure: 112.4, steam_flow: 2.1 } }),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());Ignition, Kepware, AWS IoT and webhooks
These have no dedicated connector; they send the same ingest body over HTTPS.
Ignition
Run a gateway timer script (for example every 5 s) that reads tags and posts them. Keep the key out of project exports.
paths = ["[default]Boiler/B-101/SteamPressure", "[default]Boiler/B-101/SteamFlow"]
keys = ["steam_pressure", "steam_flow"]
qvs = system.tag.readBlocking(paths)
values = dict((k, qv.value) for k, qv in zip(keys, qvs) if qv.quality.isGood())
client = system.net.httpClient()
client.post("https://api.induqt.ai/v1/ingest",
data={"machine": "B-101", "values": values},
headers={"Authorization": "Bearer " + system.tag.readBlocking(["[default]Config/InduQTKey"])[0].value})Kepware
Use the IoT Gateway REST client agent pointed at https://api.induqt.ai/v1/ingest with an Authorization: Bearer header, and a message template that produces { "machine": …, "values": { … } }. Where a custom template is not available, read Kepware with Node-RED or OPC UA instead.
AWS IoT Core
Add a rule (for example SELECT * FROM 'plant/+/telemetry') whose action invokes a small Lambda function that reshapes the message and posts it to the ingest API with the key from Secrets Manager.
Webhooks and integration tools
Zapier, Make, Power Automate, n8n or a vendor webhook: send a POST to https://api.induqt.ai/v1/ingest with the bearer header and the JSON body above.
Troubleshooting
| Symptom | Likely cause and fix |
|---|---|
| 401 Unauthorized | The header is missing or the key was revoked. The header must be exactly Authorization: Bearer iq_live_… |
| 403 Forbidden | The key lacks the ingest scope, or is limited to a different site than the machine. |
| Readings rejected or machine not found | The externalId is not known at the site. Check the spelling, send siteId (or use a site-scoped key), or set autoCreate: true. |
| Values missing | Only numbers (and booleans, stored as 0/1) are kept. Strings such as "112.4 psig" are rejected: send 112.4. |
| Times look shifted | A ts without a zone is ambiguous. Send UTC with Z, an explicit offset, or epoch milliseconds. |
| 429 Too Many Requests | More than the rate limit. Buffer and send batches, and see retries. |