Ingest API
Publish data with a plain HTTPS POST. No MQTT client, no library — if it can make a web request, it can put data on your dashboard.
https://ingest.ohioiot.com.When to reach for this
MQTT is the right tool for a device that stays connected. But plenty of things that produce data aren't that: a shell script on a cron, a serverless function, a PLC that only speaks HTTP, a webhook from another service, a quick test from your laptop. For all of those, opening and maintaining an MQTT connection is overkill. One HTTPS POST does the job.
Auth keys
Every request carries an auth key you generate in your account settings. The same key works across the HTTP surfaces — ingest, data, and OTA. Pass it as a header (preferred):
x-auth-key: YOUR_AUTH_KEYor as a query parameter, when setting a header is awkward:
https://ingest.ohioiot.com/dev01/numb/temperature/temp?auth_key=YOUR_AUTH_KEYYou can keep up to three keys active at once, which makes rotation painless: add a new one, move your clients over, delete the old one.
The path is the topic
The platform builds the MQTT topic from your account ID plus the path segments you POST to. You never type your account ID — it's derived from your auth key:
POST /dev01/numb/temperature/temp
-> topic: <your_account_id>/dev01/numb/temperature/tempThat's the same five-segment shape used everywhere else on the platform: deviceID / type / graphName / seriesName, with the account prefix filled in for you. The type is one of numb, bool, status, or config (see Data Types & Routing). You can POST to shorter paths too, down to just a device ID, and move the rest of the structure into the body — see Topic Flexibility.
What goes in the body
The body is accepted as JSON, plain text, or form-encoded. How it's interpreted depends on how deep your path is:
- Deepest path (down to a series/field name) — the body is a single scalar. Plain text and numbers pass through as-is; a JSON object is expected to carry a
valuefield. - Shorter paths — the whole body becomes the payload. Strings pass through; objects are sent as JSON.
Examples
A single reading:
curl -H "x-auth-key: YOUR_KEY" -H "Content-Type: text/plain" \
-d "23.5" \
https://ingest.ohioiot.com/dev01/numb/temperature/tempSeveral fields on one graph, in one request:
curl -H "x-auth-key: YOUR_KEY" -H "Content-Type: application/json" \
-d '{"temp": 23.5, "hum": 61}' \
https://ingest.ohioiot.com/dev01/numb/envA status value for the device card:
curl -H "x-auth-key: YOUR_KEY" -H "Content-Type: text/plain" \
-d "online" \
https://ingest.ohioiot.com/dev01/statusFrom Python:
import os, requests
requests.post(
"https://ingest.ohioiot.com/dev01/numb/temperature/temp",
headers={"x-auth-key": os.environ["OHIOIOT_KEY"]},
data="23.5",
)Fire-and-forget
A successful response means the message was accepted and handed to the broker — not that a device received it. The publish is fire-and-forget, the same as any MQTT publish. If you need confirmation that a device acted on something, that's what command feedback is for (see Commands).
Errors
200— accepted.401— auth key missing or invalid.404— too many path segments (the topic can't be more than the five-segment shape).500— backend error. Retry; if it persists, get in touch.
/info. Hit https://ingest.ohioiot.com/info in a browser for the live endpoint list — no auth key required.