Send your first packet

You already have firmware — a C project, a Python script on a Pi, a gateway you cannot reprogram at all. You do not need our client, our flasher, or an SDK. Send bytes to one of five endpoints and the device shows up here.

1. Pick a hardware id

The hardware id is the board’s name on the wire: it travels in the URL path, the MQTT topic or the hello line, and every packet arrives under it. Anything free-form works — a MAC, a serial number, a word — as long as it has no spaces and no /, ? or #, because it goes into a web address.

Use whatever the hardware already calls itself. If it is a fixed MAC printed on the board, that is the right answer: it is the one string you will still be able to find the device by in six months.

2. Send bytes

Every endpoint is named for its transport, and the payload is raw bytes — no envelope, no JSON wrapper, no content-type we care about. What those bytes mean is your decoder’s business, later.

EndpointHow to sendTLS
https.chirpiot.comPOST /ingest/{hwId}, body = payloadyes
http.chirpiot.com:80the same POST, for a chip with no TLS stackno
mqtt.chirpiot.com:1883publish chirp/{hwId}/upno
tcp.chirpiot.com:7700hello line, then one payload per lineno
udp.chirpiot.com:7701one datagram: prefix, then payload bytesno

HTTPS is the only TLS path today. There is no MQTTS listener and no TLS-wrapped TCP — if you see port 8883 suggested anywhere, it is wrong and your packets will die in the handshake. That also caps the other four at L2: they can be signed, they cannot be encrypted.

Here is each one as a single line you can paste into a terminal right now. Replace my-board with your id.

# HTTPS — the default. Any bytes; two here that decode to 21.4 °C.
curl -X POST https://https.chirpiot.com/ingest/my-board --data-binary $'\x00\xd6'

# Plain HTTP — same request, no TLS. Use THIS host, not https. with http://:
# https.chirpiot.com redirects, and naive firmware loses the body on a redirect.
curl -X POST http://http.chirpiot.com/ingest/my-board --data-binary $'\x00\xd6'

# MQTT — username is the hardware id, password empty until it is claimed.
mosquitto_pub -h mqtt.chirpiot.com -p 1883 -u my-board -P "" \
  -t chirp/my-board/up -m hello

# TCP — hello line first, then one payload per line. "-" is the no-token field.
printf 'CHIRP1 my-board -\nhello\n' | nc tcp.chirpiot.com 7700

# UDP — one datagram: "CHIRP1 {hwId} {token} " then the raw payload bytes.
printf 'CHIRP1 my-board - hello' | nc -u -w1 udp.chirpiot.com 7701

On TCP and UDP the third field is the token and - means “I don’t have one”. On MQTT that is an empty password. On HTTP it is simply the absence of the X-Chirp-Token header. Once the device is claimed, that field is where its token goes — nothing else about the framing changes. Binary on TCP rides as one line prefixed b64:; everywhere else it is the raw bytes.

3. Read the answer

A first packet from an id nobody owns comes back 202 {"status":"unclaimed"}. That is a success, and it is the specific success you want: the bytes were accepted and the platform has recorded a sighting — the id, the transport, a sample of the payload, and when it arrived. Nothing is stored against an account yet, because there is no account attached to it yet.

A plain 202 with no body means the device is already claimed and its message is stored. The other two answers worth knowing: 401 is a bad or missing token on a device that HAS one, and 429 is throttling — it carries Retry-After in seconds, and the correct response is to wait that long, not to retry harder.

Sightings expire after 72 hours.

An unclaimed sighting is swept 72 hours after the device last warbled. If you send one packet on a Friday and come looking on Tuesday, the search will be empty and nothing is broken — power the board on, let it send again, and search once it has. A device that reports on a schedule keeps its own sighting alive.

4. Find it and claim it

Sightings are not browsable: an inbox anyone could page through would let anyone enumerate every device in the world. You look yours up by its id, on Devices Already sending? Find it.

  1. 1Search the id, or at least its last four characters. Four is a hard floor — a shorter suffix is refused, because a two-character search is a fishing net. The whole id works too; it is its own tail.
  2. 2Claim it. The device moves into your account, keeps its history, and a token is minted and shown to you once.

Claiming does not change what your firmware has to send. A searched claim binds the device at L0 — the level of the sighting it was built on — so the very next tokenless packet, which is the same packet that produced the sighting, is still accepted. This is the whole point of the path: it exists for hardware you cannot reprogram, and a claim that demanded a token would kill exactly that hardware, silently.

The token is real and it is yours whenever you want it. Put it on the board and the device climbs to L1 on the first message that carries it — by itself, with no gap. Attaching a spec whose design is higher does not force anything either: the design is a target the device walks up to on evidence. See Moving up without going dark.

Empty searches back off, hard.

Consecutive empty searches and failed claims shrink your rate budget exponentially — it is the defence against someone walking the id space. One or two misses while you get the id right costs you nothing. A script that retries in a loop will lock itself out of the endpoint it is trying to use, and the fix is to stop and check the id, not to keep going.

5. Then: name the bytes

A claimed device stores raw payloads and shows them as hex. To get named fields on a chart, the device needs a spec with a decoder on it — a short function in Starlark (Python-like) that turns your bytes into a flat dict. The device page has a Decode its bytes button that makes the spec, attaches it and opens the editor with your device’s own last payload already loaded.

  • Sending on a long period? Save the decoder anyway — it runs on the next message that arrives, not on the ones already stored.
  • Two bytes, big-endian, tenths of a degree is the built-in example: 0x00 0xD621.4. It is there so you can see the whole loop work before writing your own.
  • Ready for more than L0? Security levels is the ladder, and provisioning over USB is how the portal puts a token or a signing key on a board without you retyping either.