Using Knockbox

Anything that can make one HTTP request can push a message to your iPhone — home automation, a price watcher, a script you wrote, or your own coding agent.

A send address looks like this
url
1https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>
Once you join, you get this same page with the token filled in, and every example gains a “Send this one” button.
Go to the join page

Joining

Install the app, scan the code

Download Knockbox and scan the QR code on the join page. No sign-up, no password — once you scan you have your own inbox and a first channel. No account also means losing every device loses the identity; to add a device, generate a code in the app that is already connected.

One channel per thing

Each channel has its own send address, sound, interruption level and mute switch. Give “home” and “deliveries” one each, and only the first will wake you at night. In the app, open a channel → “…” at the top right → Channel settings to get back to its send page.

Sending

The simplest one

The whole body is the message; nothing to configure. It arrives as a plain text notification.

bash
1curl -d "The laundry is done" https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>

With a title

The title is the first line of the notification, the body sits under it. Plain GET works too, for places that can only build a URL.

bash
1curl "https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>?title=Parcel arrived&text=Locker A12 downstairs"

markdown

Tables, lists, quotes and code blocks (with line numbers and highlighting) all render. The body is not part of the push itself — the app fetches it separately — so it can be long.

bash
1curl -H 'Content-Type: application/json' -d '{
2 "type": "markdown",
3 "title": "This week's spending",
4 "body": "**$86** this week.\n\n| Category | Amount |\n|---|---|\n| Food | $43 |\n| Transport | $18 |\n\n> $10 more than last week."
5}' https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>

Lists and checklists

Bulleted, numbered and checkable lists all work — good for “what is still left”.

bash
1curl -H 'Content-Type: application/json' -d '{
2 "type": "markdown",
3 "title": "Before leaving",
4 "body": "- [x] Air conditioning off\n- [x] Balcony door locked\n- [ ] Take the bins out"
5}' https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>

Card

An ordered set of key-value pairs — tighter than a table, good for “a few facts about one thing”. style can be ok / warn / error / muted and only colours the value on the right.

bash
1curl -H 'Content-Type: application/json' -d '{
2 "type": "card",
3 "title": "This month's phone bill is out",
4 "items": [
5 {"k": "Amount", "v": "$8.30"},
6 {"k": "Status", "v": "Paid automatically", "style": "ok"}
7 ]
8}' https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>

With an image

The app icon on the notification is replaced by the image itself, and expanding shows it full size. Images are scaled to a long edge of 1600; the original is not kept.

bash
1curl -F "title=Electricity use was high yesterday" -F "text=14.2 kWh, about 60% above normal" -F "image=@chart.png" https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>

A notification that updates itself

A new notification carrying the same collapse_id replaces the old one, so the notification centre only ever holds the latest — good for progress and status. Press this button a few times to see it. There is also idem_key for idempotency: a retry carrying the same value does not push twice.

bash
1curl -H 'Content-Type: application/json' -d '{
2 "title": "Parcel out for delivery",
3 "body": "Three stops away",
4 "collapse_id": "sf-1234567890"
5}' https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>

Hand it to an AI agent

Paste one block into it

Copy the whole block into Claude Code or any other agent that can run commands. The address is already in it; nothing needs changing.

prompt
1I have a Knockbox push service that delivers messages to my iPhone.
2
3The send address (this is my channel — use it directly, nothing to replace):
4 https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>
5
6Four forms all work:
7 curl -d "the message body" https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>
8 curl "https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>?title=Title&text=Body"
9 curl -F "title=Title" -F "text=Body" -F "image=@chart.png" https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>
10 curl -H 'Content-Type: application/json' -d '{"type":"markdown","title":"Title","body":"Body"}' https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>
11
12Fields:
13 type text | markdown | image | link | card, defaults to text
14 title the first line of the notification
15 body the message; it can be long. markdown supports code blocks, tables, lists and quotes
16 link attach a link the notification can open directly
17 items key-value array for type=card, [{"k":"Branch","v":"main","style":"ok"}], order is kept
18 idem_key idempotency key; a retry carrying the same value does not push twice
19 collapse_id collapse key; a new notification with the same value replaces the old one, good for progress
20 reply ask for an answer (below). The answer does not come back on this connection —
21 it is POSTed to a URL you provide
22
23Use it whenever you need to tell me something: a task finished, something broke, a decision is needed.
24Put what happened in the title and the detail in the body; for several parallel results use a markdown table or a card.
25
26Asking for an answer:
27 curl "https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>?title=Deploy to production?&choices=Deploy,Hold&reply_webhook=https://your-host/hook"
28
29 Or as an object:
30 curl -H 'Content-Type: application/json' -d '{
31 "title": "Deploy 1.1.0 to production?",
32 "reply": {"type":"choice","options":["Deploy","Hold"],"webhook":"https://your-host/hook"}
33 }' https://knockbox.miramiao.com/api/v1/send/<YOUR_TOKEN>
34
35 type choice: buttons, one tap. multi: checkboxes then submit. number: a slider. text: a field
36 options the labels for choice and multi, 2 to 10, up to 40 characters each
37 min max required for type=number; step defaults to 1, unit is shown after the number (°C / minutes)
38 timeout seconds until the answer is no longer accepted. Omit for no limit — only set it when
39 something happens by itself once the time is up
40 webhook required. Once I answer, the server POSTs it to this URL
41
42 What you receive: {"uid":"…","channel":"…","title":"…","reply":"Hold","replied_at":1726…}
43 reply is a string for choice and text, an array of strings for multi, a number for number.
44 Signed with X-Knockbox-Signature: sha256=<HMAC-SHA256(body, channel token)> so you can verify it.
45
46 If you have no endpoint that can receive a POST, leave reply out: say in the message that you
47 are waiting, then stop and wait.

Or connect it as an MCP server

The same address also speaks MCP over streamable HTTP, with a single tool that sends one notification — for a client that cannot run commands, and so the block above does not have to be pasted into every project. Add it in whichever form your client takes: hand the first block to an assistant and it configures itself, paste the JSON into a config file, or run the command in Claude Code. The endpoint carries exactly the permission of the send address: post to this channel, read nothing.

1Please add an MCP server for me:
2- Name: knockbox
3- Transport: Streamable HTTP (remote http)
4- URL: https://knockbox.miramiao.com/mcp/<YOUR_TOKEN>
5It has one tool, knock, which sends a notification to my phone.
6Once it is added, call it to send me a test notification.

Other

Limits

  • At most 20 channels
  • At most 500 messages per 24 hours (a rolling window, not a daily reset)
  • Messages are kept for 30 days, then cleared automatically
  • Going over returns a clear 429 saying when it recovers — messages are never dropped silently

Run your own

The server is open source — one binary and one SQLite file, with the messages entirely on your own machine. Joining works exactly as it does here, only the address is yours.

A send address is the permission to post to that channel, so do not publish it. If it leaks, rotate it once in the channel settings; the channel and its history are untouched.