# Warble > An IoT backend for creators, builders and startup teams: point any device that can send a packet at Warble over HTTP, MQTT, TCP or UDP, attach a small decoder script, and get named fields on a dashboard. Those tiny packets are called warblets. You choose the security level, from open to signed — and Enforce TLS is a separate per-device flag, because who is talking and whether the wire is readable are two different questions. Everything the web portal does is also available to an agent or a script through one account API key — REST, WebSocket tail, and an MCP server. **Warble was formerly called ChirpIoT (also written Chirp IoT).** Same product, same account, same API. The rename is brand-only: every hostname below is still on `chirpiot.com`, and the wire protocol keeps its `CHIRP` tokens and `X-Chirp-*` headers. If you have older notes under either name, they still apply. Warble exists because getting a homemade board's bytes onto a chart should not require a certificate authority, a broker cluster, or an IAM policy. A device is anything that can send a packet. A blank ESP32 can be flashed, provisioned and claimed from a browser tab in one session; equally, a Python script on a Raspberry Pi or a C firmware you already wrote is a first-class device. Decoders and routines are short scripts in Starlark (Python-like) that you own, run in a sandbox, and can dry-run before saving. A routine's `specId` sets its trigger scope: bound to a spec, only messages from that spec's devices evaluate it — reads are unaffected, `state.get()` sees every device in the account either way. A routine may also call `ai(question, choices)` to have Claude make one judgement per evaluation, on your own Anthropic key. REST base: `https://api.chirpiot.com/v1` — JSON, and every endpoint accepts `Authorization: Bearer chk_…` (an account API key from the portal's Settings page) or a Clerk session JWT. Errors are always `{"error":{"code":"not_found|unauthorized|invalid|throttled|unavailable|upstream","message":"…"}}`. MCP endpoint: `https://api.chirpiot.com/mcp` — streamable HTTP, same key. Connect Claude Code with: `claude mcp add --transport http chirpiot https://api.chirpiot.com/mcp --header "Authorization: Bearer chk_YOUR_KEY"` The MCP tools cover devices, claim codes, specs, decoders, routines and alerts. They deliberately cannot delete anything, manage API keys, or write secrets. ## Docs - [Docs index](https://chirpiot.com/docs): every page below, grouped by what you are trying to do. - [Send your first packet](https://chirpiot.com/docs/first-packet): the bring-your-own-firmware quickstart — a one-line snippet per transport, what `202 {"status":"unclaimed"}` means, the 72h sighting expiry, the ≥4-character suffix search rule, and search-and-claim (binds at L0, so the device's next tokenless packet still works). - [Connect your agent](https://chirpiot.com/docs/agents): API keys, the MCP tool catalogue, curl equivalents, and a downloadable Claude Code skill. - [Security levels](https://chirpiot.com/docs/security): the L0–L2 auth ladder, the independent Enforce TLS flag, and how to choose. - [L0 Open](https://chirpiot.com/docs/security/level-0): hardware id only, no token. Bench experiments, and the "verify an HMAC in your own decoder" pattern. - [L1 Token](https://chirpiot.com/docs/security/level-1): a per-device token on every message. - [L2 Signed](https://chirpiot.com/docs/security/level-2): token plus an HMAC of each payload, on every transport. - [Enforce TLS](https://chirpiot.com/docs/security/enforce-tls): the transport axis, and NOT a level. Per-device `enforceTls` (off by default) is armable at L0, L1 or L2 and is the only thing that rejects plaintext — confidentiality is enforced, and claimed, only when it is on; until then the platform shows what arrives without going dark. There is no L3 (contract v0.19): "L3" was L2 plus this flag, and only `https.` of the five ingest links can carry TLS at all. `/docs/security/level-3` redirects here. - [Provisioning over USB](https://chirpiot.com/docs/provisioning): CHIRP-PROV v1.5, the four-line UART protocol (ordered Wi-Fi list, Thread datasets, merge-pushes, the board's own `radios=` announce, and v1.5's optional `key` — the base64 HMAC signing key, pushed down the same cable as the token — plus `sig=1` in the announce for firmware that signs), with MicroPython and Arduino reference implementations. ## Tools and pages - [Browser flasher](https://chirpiot.com/flash): flash MicroPython or your own binary to an ESP32 over Web Serial, or a `.bin` to an STM32 over WebUSB DFU (the ROM bootloader, entered with BOOT0), then provision Wi-Fi and a claim code. Nothing to install. STM32F1 has no USB DFU in ROM and is not reachable this way. - [Claude Code skill](https://chirpiot.com/skills/chirpiot/SKILL.md): the Warble workflow as a skill file — install at `~/.claude/skills/chirpiot/SKILL.md`. - [Portal](https://chirpiot.com/app): a dashboard card per device — live fields, sparklines, image and audio frames, and whatever switches its spec declares — plus devices, specs, decoders, routines, alerts and settings. - [Terms of use](https://chirpiot.com/terms) ## Device ingest hosts - `https://https.chirpiot.com/ingest/{hwId}`: HTTP ingest over TLS. POST raw payload bytes; `GET /ingest/{hwId}/down` polls for downlink. (Every endpoint is named for its transport — v0.12. The old `ingest.` name is RETIRED and no longer serves: it has no certificate, so a request to it dies in the TLS handshake.) - `http://http.chirpiot.com/ingest/{hwId}`: the same thing on port 80 with **no TLS**, for devices without a TLS stack. Use this host rather than sending plain HTTP to `https.` — that one redirects to TLS and naive firmware loses the data. - `mqtt.chirpiot.com:1883`: publish `chirp/{hwId}/up`, subscribe `chirp/{hwId}/down`. Username = hardware id, password = token or claim code. Plaintext — no MQTTS listener exists yet, so MQTT devices top out at L2; HTTPS is the only TLS path today. - `tcp.chirpiot.com:7700`: newline-framed. Hello line `CHIRP1 {hwId} {token}`, then one payload per line (`b64:` prefix for binary). - `udp.chirpiot.com:7701`: datagram prefix `CHIRP1 {hwId} {token} ` followed by raw payload bytes. No downlink. ## Optional - [How it works](https://chirpiot.com/#how) - [Pricing](https://chirpiot.com/#pricing)