使い方
アプリで発行した URL に HTTP POST するだけです。このページでは payload の書き方・送信例と、URL が途絶えたら知らせる「途絶監視」を説明します。
$TODOKI_URL は、アプリの URL 一覧からコピーしたあなたの Webhook URL(https://hook.todoki.dev/hook/<id> 形式)に置き換えてください。URL 末尾の id が秘密鍵の役割を果たすため、URL は公開リポジトリ等に書かず、CI の secret として扱ってください。
最小の例
curl -X POST "$TODOKI_URL" \
-H 'content-type: application/json' \
-d '{"title":"デプロイ完了","body":"v1.2.3 を本番反映"}'
# => 202 {"ok":true}
JSON を組み立てるのも面倒なら、プレーンテキストを投げるだけでも通知になります(叩くだけモード):
curl -X POST "$TODOKI_URL" -H 'content-type: text/plain' -d 'ビルド終わったよ'
payload フィールド
JSON で送る場合、以下のフィールドが使えます。すべて省略可能です。
| フィールド | 意味 | 例 |
|---|---|---|
title | 通知タイトル | "ビルド失敗" |
body | 本文 | "main ブランチ" |
priority | 優先度。time-sensitive(即時)/ normal / low | "time-sensitive" |
click | 通知タップ時に開く URL | "https://example.com/build/123" |
適用の優先順位は「payload の明示フィールド > URL に設定したテンプレート > 既定値」です。
タップで URL を開く
curl -X POST "$TODOKI_URL" -H 'content-type: application/json' \
-d '{"title":"CI 失敗","body":"ログを開く","click":"https://example.com/ci/run/123"}'
緊急度を上げる
curl -X POST "$TODOKI_URL" -H 'content-type: application/json' \
-d '{"title":"アラート","body":"CPU 90%","priority":"time-sensitive"}'
言語・ツール別の送信例
ただの HTTP POST なので、HTTP を送れるものなら何からでも通知できます。下のタブで言語を切り替えてください。$TODOKI_URL はあなたの Webhook URL に置き換えます(curl・JavaScript・Python はアプリの「テスト送信」から、その URL 入りのスニペットをそのままコピーできます)。
curl -X POST "$TODOKI_URL" \
-H 'content-type: application/json' \
-d '{"title":"デプロイ完了","body":"v1.2.3 を本番反映"}'
JSON すら不要なら、プレーンテキストを投げるだけでも通知になります(叩くだけモード):
curl -X POST "$TODOKI_URL" -H 'content-type: text/plain' -d 'ビルド終わったよ'
ブラウザ / Deno / Bun / Node 18+(標準の fetch)
fetch("$TODOKI_URL", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ title: "デプロイ完了", body: "v1.2.3 を本番反映" }),
});
requests を使う場合
import requests
requests.post("$TODOKI_URL", json={"title": "デプロイ完了", "body": "v1.2.3 を本番反映"})
標準ライブラリだけ(依存なし)
from urllib.request import urlopen, Request
import json
body = json.dumps({"title": "デプロイ完了", "body": "v1.2.3 を本番反映"}).encode()
urlopen(Request("$TODOKI_URL", data=body, headers={"content-type": "application/json"}))
標準 https モジュール(依存なし)
const https = require("https");
const data = JSON.stringify({ title: "デプロイ完了", body: "v1.2.3 を本番反映" });
const req = https.request("$TODOKI_URL", {
method: "POST",
headers: { "content-type": "application/json", "content-length": data.length },
});
req.write(data); req.end();
package main
import ("net/http"; "strings")
func main() {
body := `{"title":"デプロイ完了","body":"v1.2.3 を本番反映"}`
http.Post("$TODOKI_URL", "application/json", strings.NewReader(body))
}
require "net/http"; require "json"
uri = URI("$TODOKI_URL")
Net::HTTP.post(uri, {title: "デプロイ完了", body: "v1.2.3 を本番反映"}.to_json,
"content-type" => "application/json")
Invoke-RestMethod -Uri "$TODOKI_URL" -Method Post -ContentType "application/json" `
-Body '{"title":"デプロイ完了","body":"v1.2.3 を本番反映"}'
http POST "$TODOKI_URL" title="デプロイ完了" body="v1.2.3 を本番反映"
JSON すら不要なら、どの言語でもプレーンテキストを本文に投げるだけで通知になります(content-type: text/plain)。
URL ごとのテンプレート
送信側のサービスが決まった形の JSON を送ってくる場合(例: {"repo":"...","msg":"..."})、URL 側にテンプレートを設定しておけば、送信側は生の JSON を送るだけで整形された通知になります。※ テンプレートの登録 UI はアプリで今後対応予定です(下記はその際の書き方)。
# URL に設定したテンプレート: {"title":"{{repo}}","body":"{{msg}}"}
curl -X POST "$TODOKI_URL" -H 'content-type: application/json' \
-d '{"repo":"todoki/backend","msg":"build passed"}'
# => 通知: タイトル「todoki/backend」 本文「build passed」
{{a.b}} のようなドット記法でネストした値も参照できます。
CI からの利用例
GitHub Actions
# Webhook URL はリポジトリの Secrets に TODOKI_URL として登録しておく
- name: Notify
if: always()
run: |
curl -sf -X POST "${{ secrets.TODOKI_URL }}" \
-H 'content-type: application/json' \
-d "{\"title\":\"${{ github.repository }}\",\"body\":\"${{ job.status }}: ${{ github.workflow }}\"}"
シェルスクリプト(長時間処理の完了通知)
./long-running-job.sh; \
curl -X POST "$TODOKI_URL" -H 'content-type: text/plain' \
-d "job finished: exit=$?"
途絶監視(ハートビート)
todoki はふだん「届いた通知」を知らせますが、途絶監視はその逆 —— 来るはずの通知が来なくなったこと(沈黙)そのものを知らせます。毎朝動くはずのバッチ、定期送信のセンサー、cron が止まったことに気づくための死活監視(dead man's switch)です。
設定する
途絶監視は URL ごとに、アプリの URL 詳細画面から設定します。
- アプリで対象の URL を開き、「途絶を監視」を ON にします。
- 監視間隔を選びます(
15分/1時間/6時間/1日/1週間から。既定は1日)。
「この間隔より長くその URL が叩かれなかったら」途絶とみなして通知します。
途絶通知を出さないようにするには
答えはシンプルで、監視間隔の内に、最低 1 回その URL へ POST し続けることです。todoki はその URL への POST を「生存の合図(心拍)」として扱い、POST が届くたびにタイマーをリセットします。間隔を超えて沈黙が続いたときだけ、途絶として通知します。
1日)。ジョブが落ちて POST が届かなければ、間隔超過で途絶通知が届きます。
# 毎日 6:00 に動くジョブ。成功したら todoki に POST(この POST が心拍になる)
0 6 * * * /path/to/job.sh && curl -fsS -X POST "$TODOKI_URL" \
-H 'content-type: text/plain' -d 'daily job ok' >/dev/null
途絶すると、何回通知が来るのか
鳴り続けません。1 回の途絶につき最大 4 通(途絶 1 + 追い通知 2 + 復帰 1)で打ち止めです。
-
1 / 3
途絶を検知 — 「『ラベル』からの通知が途絶えています。」を 1 回。 設定間隔を過ぎた直後(約 5 分おきに見張っているため、タイミングは最大 5 分ほど前後します)
-
2 / 3
追い通知 — 「まだ途絶えています。」 最初の検知から約 6 時間後
-
3 / 3
追い通知(最後) — 「まだ途絶えています。」 最初の検知から約 24 時間後。これ以降は復帰まで沈黙します
-
復帰
復帰をお知らせ — URL が再び叩かれたら「『ラベル』が復帰しました。」を 1 回送り、監視は通常状態に戻ります。次に途絶すれば、また 1/3 から数え直します。
※ ミュート中の URL では、途絶通知も届きません(アプリ内の「途絶」バッジだけが付きます)。
レスポンス
| 状況 | コード | body |
|---|---|---|
| 受け付けた | 202 | {"ok":true} |
| URL が失効済み | 410 | {"error":"url revoked"} |
| URL が存在しない | 404 | {"error":"url not found"} |
セキュリティ上の理由から、応答には配信の詳細(端末への到達結果やミュート状態など)を含めません。202 は「受け付けた」ことを意味します。
URL の管理
- 失効 — URL が漏れた疑いがあるときは、アプリからワンタップで失効。旧 URL は即座に
410になります。新しい URL を発行して送信元を差し替えてください(設定をそのまま引き継ぐ「再発行」はアプリで今後対応予定)。 - ミュート — URL ごとに通知の ON/OFF を切り替えられます(アプリの「通知を受け取る」)。送信側にはミュートを悟られません(
202のまま)。 - 複数 URL — 用途・サービスごとに URL を分けるのがおすすめです。ラベルを付けて管理できます。
複数の端末で受け取る(端末リンク)
iPhone と Android スマホなど、自分の複数のスマホで同じ URL の通知を受け取れます。アプリ内で端末どうしを QR コードでリンクすると、両方の端末の URL がひとつに合算され、以後はどちらの端末にも同じ通知が届きます(同期)。送信側の Webhook URL は変わりません。
リンクのしかた
- 端末 A(すでに使っている方)で「設定 → 端末をリンク → この端末のコードを表示」を開きます(QR が表示されます)。
- 端末 B(追加したい方)で「設定 → 端末をリンク → QR を読み取って参加」を開き、A の QR を読み取ります。
- A 側に「追加しますか?」と出るので 「追加する」を押すと統合完了。両方の端末で同じ URL の通知を受け取れます。
端末を外す(紛失・売却時)
「設定 → 端末をリンク → リンクした端末」から、特定の端末を解除できます。解除した端末は、以後その URL の通知を受信できなくなり、アカウントの操作(一覧の閲覧・失効・発行)もできなくなります。端末を紛失・売却したときの遮断に使ってください。
410)し、新しい URL を発行し直してください。
※ 通知履歴は端末ごとに保存され、合算されません(各端末には、その端末で受け取った分だけが残ります)。アカウント全体の引き継ぎ(ログイン)は今後対応予定です。