Point anything that speaks JSON at one URL and get a live dashboard.

Microcontroller→ JSON→ API→ Dashboard

No account, no API key, no setup. Generate a device ID and a write key below, POST your first measurement, and every sensor you send becomes a chart automatically.

Publish a measurement Browse the dashboard

Beta, and public. Every dashboard on this instance is readable by anyone who knows the device ID β€” there are no private dashboards yet. Anonymous devices and all their measurements are deleted after 48 hours without a successful write. Don't publish anything here you would mind other people reading, and don't rely on this as your only copy of the data.

On this instance right now

Devices
4
4 live now
Measurements
3,280
3,280 stored now
Projects
2
2 live now

The large number is the all-time total β€” it includes devices and measurements that have since expired, and only ever goes up. The line beneath it is what exists right now.

1. Generate your two identifiers

A device is identified by a device ID and owned by a write key. The first request to use an unclaimed device ID claims it; every later write to that device must present the same write key. Both are generated here in your browser and neither is sent anywhere until your device makes its first measurement.

…or generate them individually below. Already have a device? Type its ID in and the examples will use it.

Device ID

Public, like a username. It appears in your dashboard URL, so anyone who has it can read your charts. Use letters, digits, hyphens, and underscores β€” or take a random one.

Write key

Secret, like a password β€” it is the only thing stopping someone else writing to your device. Generated locally with crypto.getRandomValues, about 187 bits of entropy.

Save it now. We store only a hash of your write key, so it cannot be shown to you again, reset, or recovered. Lose it and your only options are a different device ID or waiting 48 hours for the device to expire.

2. Send a measurement

One POST to /sensor/measurement. Each entry in sensors becomes a chart named after its key β€” send a new one whenever you like and it appears on its own.

curl
curl -X POST https://diy-sensor.org/sensor/measurement \
  -H 'content-type: application/json' \
  -d '{
        "device_id": "YOUR-DEVICE-ID",
        "write_key": "YOUR-WRITE-KEY",
        "project": "balcony",
        "name": "Basil #3",
        "sensors": {
          "temperature": {"value": 21.4, "unit": "C"},
          "humidity": 51,
          "pump_running": false
        }
      }'

project groups devices onto a shared dashboard and name is a display label; both are optional. A sensor value may be a bare number or an object with value, unit, and plot (gauge or line).

Python
import requests

requests.post(
    "https://diy-sensor.org/sensor/measurement",
    json={
        "device_id": "YOUR-DEVICE-ID",
        "write_key": "YOUR-WRITE-KEY",
        "sensors": {"temperature": 21.4, "humidity": 51},
    },
    timeout=10,
).raise_for_status()
ESP32 / Arduino
#include <WiFi.h>
#include <HTTPClient.h>

const char *INGEST_URL = "https://diy-sensor.org/sensor/measurement";
const char *DEVICE_ID  = "YOUR-DEVICE-ID";
const char *WRITE_KEY  = "YOUR-WRITE-KEY";   // keep out of public repos

void publish(float temperature, float humidity) {
  if (WiFi.status() != WL_CONNECTED) return;

  HTTPClient http;
  http.begin(INGEST_URL);
  http.addHeader("Content-Type", "application/json");

  char body[256];
  snprintf(body, sizeof(body),
           "{\"device_id\":\"%s\",\"write_key\":\"%s\","
           "\"sensors\":{\"temperature\":%.2f,\"humidity\":%.2f}}",
           DEVICE_ID, WRITE_KEY, temperature, humidity);

  int status = http.POST(body);
  // 201 = device claimed, 200 = measurement appended.
  // 429/503 mean "slow down": back off, don't retry in a tight loop.
  Serial.printf("ingest -> %d\n", status);
  http.end();
}

Your dashboard is then at /dashboard/device/YOUR-DEVICE-ID.

3. Look after your key

What happens to your data

Limits

Deliberately tight while this is in beta; they will be loosened as real usage shows what normal looks like. Rate-limited responses carry a Retry-After header.

LimitAnonymous
Data retention48 hours without a successful write
Request body16 KB
Sensor fields per request16
Distinct sensors per device16
Device ID length64 characters
Sensor name length64 characters
Requests per minute (per IP)30
Requests per day (per IP)1,000
Writes per minute (per device)12
New devices per hour (per IP)5
Active devices (per IP)10

Errors

StatusCodeMeaning
400 missing_device_id / invalid_device_id No device_id, or one with characters outside A–Z a–z 0–9 _ -
400 missing_sensors / empty_sensors No sensors object, or an empty one
400 invalid_value A value that is not a number, boolean, short string, or null β€” NaN and infinity included
400 unknown_field A field the endpoint does not accept, including timestamp
401 missing_write_key The device has a write key and the request did not present it
401 api_key_required The device ID is claimed by a keyless API-key device
403 invalid_write_key The write key was wrong
413 payload_too_large The request body is over the size limit
429 …_rate_limited / …_limit A rate or quota limit; retry after the seconds in Retry-After
503 storage_full / …_over_budget The platform is shedding load or out of storage; retry later

Every error response is JSON with an error message and a stable code. A successful write returns 201 when it claimed the device and 200 when it appended to one.