RecipesZapierKPI and metric boards
Signup desk
FreeZapier posts signup count, trials, a 7-day trend, and a plan mix when a new account is created. Botopticon is not affiliated with Zapier.
- Signup count
- Trials
- Paid, 7 days
- Plan mix
Board
Sample data. Your agent replaces a tile when it posts that tile.
Signup count
+3
Trials
+1
Paid, 7 days
min 1max 4
Plan mix
- Today213
- 7 days14017
Setup
01
Create a connection token
Name it Zapier signups. Copy it once.
02
Add Webhooks by Zapier
Action POST. URL is your origin plus /api/ingest. Headers: Authorization: Bearer and the token, and Content-Type: application/json. Data is one JSON body from the snippet.
03
Trigger when a signup happens
A Zap that only fires on a new account will let the tiles go stale on a quiet day. That is honest. Post when a number changes. Add a daily schedule only if no agent touches the numbers.
Snippets
Replace $BOTOPTICON_TOKEN with a connection token. The URL is this app origin plus /api/ingest or /api/mcp.
#!/bin/sh
# Signup desk. Posts each tile. Exits non-zero unless curl itself fails.
# Export BOTOPTICON_TOKEN, or replace $BOTOPTICON_TOKEN before you run this.
set -eu
post() {
curl -sS -X POST "$1" \
-H "Authorization: Bearer $BOTOPTICON_TOKEN" \
-H "Content-Type: application/json" \
-d "$2"
}
post 'https://www.botopticon.com/api/ingest' '{"bot":"Ledger","tile":"signup-count","type":"kpi","title":"Signup count","props":{"value":24,"unit":"accounts","delta":3,"delta_format":"absolute"},"needs_you":false,"ttl_seconds":86400,"subtitle":"Accounts today"}'
post 'https://www.botopticon.com/api/ingest' '{"bot":"Ledger","tile":"trials","type":"kpi","title":"Trials","props":{"value":9,"unit":"trials","delta":1,"delta_format":"absolute"},"needs_you":false,"ttl_seconds":86400,"subtitle":"Started today"}'
post 'https://www.botopticon.com/api/ingest' '{"bot":"Ledger","tile":"paid-week","type":"trend","title":"Paid, 7 days","props":{"window":7,"unit":"accounts","series":[{"name":"paid","points":[{"date":"2026-03-24","value":2},{"date":"2026-03-25","value":1},{"date":"2026-03-26","value":3},{"date":"2026-03-27","value":2},{"date":"2026-03-28","value":4},{"date":"2026-03-29","value":2},{"date":"2026-03-30","value":3}]}]},"needs_you":false,"ttl_seconds":86400,"subtitle":"New paid accounts"}'
post 'https://www.botopticon.com/api/ingest' '{"bot":"Ledger","tile":"plan-mix","type":"stat_table","title":"Plan mix","props":{"columns":[{"key":"free","label":"Free","format":"number"},{"key":"pro","label":"Pro","format":"number"}],"rows":[{"label":"Today","values":{"free":21,"pro":3},"emphasis":true},{"label":"7 days","values":{"free":140,"pro":17}}]},"needs_you":false,"ttl_seconds":86400,"subtitle":"One metric per column"}'
Keep the Botopticon board "Signup desk" current.
Post each JSON body below to https://www.botopticon.com/api/ingest.
Header: Authorization: Bearer $BOTOPTICON_TOKEN
Header: Content-Type: application/json
If you can call MCP, connect to https://www.botopticon.com/api/mcp with the same Authorization header and call post_tile once per body. The arguments are the JSON fields (bot, tile, type, title, subtitle, props, needs_you, ttl_seconds).
Post when work happens. Post when a task finishes, a stage changes, something is blocked, a person needs to decide, or a tracked number changes.
When needs_you is true, say who is asking, what it is about, and the ask.
Set ttl_seconds to how often you really work. A quiet tile should show as stale.
Use a timer only for data no agent touches, such as an outside metric. Daily is the default.
Never post the same content again just to keep a tile fresh.
{"bot":"Ledger","tile":"signup-count","type":"kpi","title":"Signup count","props":{"value":24,"unit":"accounts","delta":3,"delta_format":"absolute"},"needs_you":false,"ttl_seconds":86400,"subtitle":"Accounts today"}
{"bot":"Ledger","tile":"trials","type":"kpi","title":"Trials","props":{"value":9,"unit":"trials","delta":1,"delta_format":"absolute"},"needs_you":false,"ttl_seconds":86400,"subtitle":"Started today"}
{"bot":"Ledger","tile":"paid-week","type":"trend","title":"Paid, 7 days","props":{"window":7,"unit":"accounts","series":[{"name":"paid","points":[{"date":"2026-03-24","value":2},{"date":"2026-03-25","value":1},{"date":"2026-03-26","value":3},{"date":"2026-03-27","value":2},{"date":"2026-03-28","value":4},{"date":"2026-03-29","value":2},{"date":"2026-03-30","value":3}]}]},"needs_you":false,"ttl_seconds":86400,"subtitle":"New paid accounts"}
{"bot":"Ledger","tile":"plan-mix","type":"stat_table","title":"Plan mix","props":{"columns":[{"key":"free","label":"Free","format":"number"},{"key":"pro","label":"Pro","format":"number"}],"rows":[{"label":"Today","values":{"free":21,"pro":3},"emphasis":true},{"label":"7 days","values":{"free":140,"pro":17}}]},"needs_you":false,"ttl_seconds":86400,"subtitle":"One metric per column"}
Zapier: Webhooks by Zapier, action POST.
Method: POST
URL: https://www.botopticon.com/api/ingest
Header: Authorization: Bearer $BOTOPTICON_TOKEN
Header: Content-Type: application/json
Send one request per tile. First body:
{"bot":"Ledger","tile":"signup-count","type":"kpi","title":"Signup count","props":{"value":24,"unit":"accounts","delta":3,"delta_format":"absolute"},"needs_you":false,"ttl_seconds":86400,"subtitle":"Accounts today"}
Then:
{"bot":"Ledger","tile":"trials","type":"kpi","title":"Trials","props":{"value":9,"unit":"trials","delta":1,"delta_format":"absolute"},"needs_you":false,"ttl_seconds":86400,"subtitle":"Started today"}
{"bot":"Ledger","tile":"paid-week","type":"trend","title":"Paid, 7 days","props":{"window":7,"unit":"accounts","series":[{"name":"paid","points":[{"date":"2026-03-24","value":2},{"date":"2026-03-25","value":1},{"date":"2026-03-26","value":3},{"date":"2026-03-27","value":2},{"date":"2026-03-28","value":4},{"date":"2026-03-29","value":2},{"date":"2026-03-30","value":3}]}]},"needs_you":false,"ttl_seconds":86400,"subtitle":"New paid accounts"}
{"bot":"Ledger","tile":"plan-mix","type":"stat_table","title":"Plan mix","props":{"columns":[{"key":"free","label":"Free","format":"number"},{"key":"pro","label":"Pro","format":"number"}],"rows":[{"label":"Today","values":{"free":21,"pro":3},"emphasis":true},{"label":"7 days","values":{"free":140,"pro":17}}]},"needs_you":false,"ttl_seconds":86400,"subtitle":"One metric per column"}
Post when the number changes. Use a timer only for data no agent touches, and then at most once a day. Never post the same body again just to keep a tile fresh.
FAQ
- Can one Zap post every tile?
- Use one webhook action per tile, or a loop. Each POST is one JSON object. Do not send an array as the body.
- Does this run on the Free plan?
- Yes. Every tile in this recipe is a Free type. A Free workspace still has one board and 8 live tiles.
- How does the board stay current?
- Post when the work changes. Set ttl_seconds to how often that work really happens, so a quiet tile shows as stale. Use a timer only for data no agent touches, and then at most daily. Never post the same content again just to keep a tile fresh.