Skip to content

Send readings over HTTP

POST a device reading to the ingest service with a device token. Payload, validation rules, error codes and rate limits.

One device sends its own readings to its own endpoint, with its own token. One device, one token, one call: each request carries one reading for one device, never more than one device at a time.

The request#

HTTP request
POST https://ingest.logable.app/ingest/<DEVICE_ID>
Authorization: Bearer <DEVICE_TOKEN>
Content-Type: application/json

<DEVICE_ID> is the device's UUID. <DEVICE_TOKEN> is the token Logable showed once when you created the device. Both are on the device's Connection tab.

The body#

Device reading payload
FieldTypeRequiredDescription
timestampstringNoISO 8601. Omit it and the server uses its own clock. Rejected if it is more than one hour from server time.
statusonline | offline | errorNoThe device reporting its own state. Omit it unless the device knows something the reading does not show.
dataobjectYesThe reading itself: field name to number, string or boolean.
metadataobjectNoAnything else you want stored with the reading, for example a firmware version.

A complete body:

Request body
{
  "timestamp": "2026-07-01T10:00:00.000Z",
  "status": "online",
  "data": {
    "weight": 18750.5,
    "status": "filling"
  }
}

The field names inside data come from the device type. See Device types for the exact list per type, with an example payload for each.

A reading may carry any subset of the type's fields. A missing field is not an error, so a device can report one value at a time.

Custom fields#

Any key in data that the device type does not declare is a custom data point. Logable stores it and shows it on a widget when you turn on Show custom data.

Custom data points never drive an alert, a trigger or a forecast. If you need a value to raise an alert, it has to be a field the device type declares.

A custom key must start with a letter and contain only letters, digits or underscores. The limits below cap how many a payload may carry and how long a key or a string value may be.

Custom key limits
LimitValueDescription
custom keys20Maximum number of custom (unregistered) keys in one payload.
key length64Maximum characters in a custom key.
string value length256Maximum characters in a custom key's string value.

The response#

Response
{
  "acknowledged": true,
  "timestamp": "2026-07-01T10:00:00.123Z",
  "deviceId": "0d9f7f52-3a1c-4a6e-9b2d-1f4e5a6b7c8d"
}

The timestamp in the response is the time Logable stored the reading, which is not always the time you sent in the body.

Code samples#

These are generated from the same registry the platform validates against, so they cannot drift from what the service accepts. Replace the placeholder id and token with the values from the device's Connection tab.

# Raw Meal Silo - Quick Test (curl)
# Device Type: silo | Device ID: <DEVICE_ID>
#
# The "data" fields shown are this device type's registered metrics.
# Optionally add your OWN custom fields to "data" (e.g. "totalizer": 1284300.0).
# Custom keys: start with a letter; letters/digits/underscores; max 64 chars.
# Up to 20 custom fields; values: number, string (max 256 chars) or boolean.
# Custom values appear on dashboards via a widget's "Show Custom Data" option.

curl -X POST "https://ingest.logable.app/ingest/<DEVICE_ID>" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <DEVICE_TOKEN>" \
  -d '{"timestamp":"2026-07-01T10:00:00.000Z","status":"online","data":{"weight":18750.5,"status":"filling"}}'

Payload limits#

These bound the whole payload, whether a key is a declared field or a custom one.

Transport payload limits
LimitValueDescription
data keys100Maximum number of keys in the data object.
key length100Maximum characters in any data or metadata key.
string value length1000Maximum characters in a string value.
metadata keys50Maximum number of keys in the metadata object.
metadata size16 KBMaximum serialised size of the metadata object.
nesting depth32Maximum object nesting Logable walks before it rejects the payload.

Errors#

Every error carries a JSON body with an error message and, in most cases, a code.

Error responses
StatusCodeDescription
400VALIDATION_ERRORThe body broke the schema, a limit, or the device type's own field rules.
401UNAUTHORIZEDThe Authorization header is missing, or the token does not belong to this device.
403INGESTION_BLOCKEDIngestion is blocked for this device's organization. Contact the organization owner.
404NOT_FOUNDNo route matches this path or method. Check the URL.
429RATE_LIMIT_EXCEEDEDThis device sent too many requests. The body carries a retryAfter of 1 second.
500INTERNAL_ERRORSomething failed inside Logable. Details are deliberately omitted.

A 429 body:

{
  "error": "Too many requests",
  "code": "RATE_LIMIT_EXCEEDED",
  "details": {
    "message": "Rate limit: 10 requests per 1000ms per device",
    "retryAfter": 1
  }
}

A second body, with per organization in the message, means the organization's combined rate is over its ceiling.

Rate limits#

Logable applies four limits, in two services: three in ingest, one in the API. They are not interchangeable.

Rate limits by service
ServiceLimitDescription
Ingest over HTTP10 per secondPer device or per stream. Over the limit, the request gets a 429 with retryAfter.
Ingest over MQTT10 per secondPer device or per stream. Over the limit, the message is dropped without a reply. The device log shows the drop.
Ingest, per organization200 per secondAcross every device and stream the organization owns, on both transports. A gateway that fronts many devices counts against its organization, not against an address.
Logable API100 per minutePer signed-in user. The web and mobile apps stay under it. Devices never touch it.

Streams#

A stream carries data that is not a device: a spreadsheet export, a line from another system, a manual reading. Streams have their own endpoint, their own token, and a body with no status field. Everything else on this page applies to them unchanged.

Search the docs

Find a guide, an integration page, or a device type.