The HTTP API
Anything that can make an HTTP request can send readings to a General crate. Find your crate ID, API key and both URLs under Send data in the crate.
Send one reading
POST https://data.carroted.com/api/v2/ingest/{crate_id}
Headers:
X-API-Key: your_api_keyContent-Type: application/json
Body:
{
"device": "greenhouse-1",
"metric": "temperature",
"value": 22.5
}
Reply:
{ "status": "Data received and queued", "device": "greenhouse-1", "count": 1 }
count is the number of readings stored from your request.
Send several metrics at once
Instead of metric and value, you can put each metric in as its own key. Every numeric key becomes a reading with that key as the metric:
{
"device": "greenhouse-1",
"temperature": 22.5,
"humidity": 61,
"battery": 3.92
}
This stores three readings and replies with "count": 3. You can mix both styles in one body.
Send a batch
POST https://data.carroted.com/api/v2/ingest/{crate_id}/batch
The body is a JSON array. Each item is one reading, or one device with several metrics, as above:
[
{ "device": "greenhouse-1", "metric": "temperature", "value": 22.5 },
{ "device": "greenhouse-2", "temperature": 19.8, "humidity": 70 }
]
A batch can hold up to 100 readings on Free and 250 on Maker, counted after the metrics are split out. Bigger batches are refused with 400 Batch size limit exceeded. Batches have their own rate limit, see Limits and errors.
The fields
| Field | Required | What it is |
|---|---|---|
device | Yes | The device. Any text, 1 to 100 characters: a serial number, a hostname, kitchen-sensor. |
metric | With value | The metric. Any text, 1 to 100 characters: temperature, cpu_usage. |
value | With metric | A number. Numbers sent as text ("22.5") work too. |
time | No | When the reading was taken, as an RFC 3339 timestamp in UTC. |
Older scripts and Lighthouse send ship_id and cargo_id instead of device and metric. Both spellings are accepted.
Values must be numbers. Text and true/false are ignored. If nothing in a request is a number, you get 400 No valid data found.
Timestamps
Leave time out and the reading is stamped with the time it arrives, in UTC.
To send readings you took earlier (from a logger, or after a device was offline), add time:
{ "device": "logger-3", "metric": "temperature", "value": 18.2, "time": "2026-10-21T06:00:00Z" }
Use the full RFC 3339 form with a time zone: 2026-10-21T06:00:00Z or 2026-10-21T08:00:00+02:00.
A time that can't be read is not an error: the reading is stored with the time it arrived instead. If old readings show up as "now", check the format.
Readings older than your plan keeps (1 day on Free, 90 days on Maker) are removed by the retention policy.
Location data
Send latitude and longitude as two metrics named latitude and longitude, in the same request so they share one timestamp. The dashboard made for you puts devices with these metrics on a map.
{ "device": "van-05", "latitude": 52.3702, "longitude": 4.8952, "speed_kmh": 45.2 }
Duplicates
A reading with the same device, metric and time as one already stored is dropped. Sending the same batch twice doesn't double your data.