Timothe AI(ティモシーAI)

2026年8月5日 制定

Growth Calendar から自分のエンドポイントへ記事を送る

サイトが対応 CMS のどれでもない場合、完成した記事を自分で用意したアドレスへ POST できます。受け取ったあとどうするかは受け側の自由です。リポジトリにコミットする、自前のデータベースに書き込む、静的サイトジェネレーターに渡す、といった使い方ができます。

記事は Markdown で送られるので、受け側で HTML から戻す作業は発生しません。

設定はワークスペースにひとつです。 Growth Calendar 右上の CMS から開きます。

必要なもの

https で POST を受け付けるエンドポイントと、自分で決めるシークレットです。シークレットは毎回のリクエストに付いて送られるので、 URL を知っただけの第三者と Growth Calendar を区別できます。

接続する

  1. Growth Calendar 右上の CMS を開き、Webhook を選びます。
  2. エンドポイントの URL をパスまで含めて入力します。例: https://example.com/api/articles
  3. シークレットを入力して 接続する を選びます。

接続時にテストリクエストが 1 回送られるので、受け側は先にデプロイしておいてください。テストは次のボディを持つ POST です。

{ "event": "ping" }

2xx を返せば通ります。ボディを一切見ない受け側でも接続できます。

URL は https である必要があり、クエリ文字列と標準以外のポートは使えません。末尾のスラッシュは削られるので、https://example.com/api/articles/https://example.com/api/articles として保存されます。フレームワークがこの 2 つを別のルートとして扱う場合は、スラッシュなしの方を登録してください。

送られる内容

記事は次のヘッダーを持つ POST で届きます。

Authorization: Bearer <シークレット>
Content-Type: application/json

ボディはこの形です。

{
  "event": "article.publish",
  "articleId": "trk_abc:2026-08-05",
  "trackId": "trk_abc",
  "date": "2026-08-05",
  "status": "published",
  "title": "SEO の基本",
  "slug": "seo-basics",
  "description": "検索対策をどこから始めるか。",
  "markdown": "# SEO の基本\n\n[キーワード調査](https://example.com/blog/keyword-research)も参照。",
  "imageUrls": ["https://cdn.timothe.ai/…/a.webp"],
  "url": "https://example.com/blog/seo-basics"
}
フィールド内容
eventarticle.publish または article.draft。どちらで送ったかに対応します
articleId同じ記事を再送しても変わりません。受け側のキーとして使ってください
trackId記事が属するトラック
dateカレンダー上でその記事が割り当てられた日
statuspublished または draft
title記事タイトル
slug記事に割り当てられた URL スラッグ
descriptionメタディスクリプション
markdown記事本文。内部リンクは解決済みです
imageUrls記事内で使われている画像のアドレス
url公開後に記事が置かれるアドレス。公開サイトの URL を設定している場合のみ入ります

フィールドは今後追加されることがあります。既存のフィールド名が変わったり消えたりすることはありません。

受け側で必要な対応

保存に成功したときだけ 2xx を返してください。 2xx は成功として扱われ、記事は送信済みになります。受け取ったあとで保存に失敗しても、 Growth Calendar 側からは分かりません。

同じ articleId は同じ記事として扱ってください。 記事を修正して送り直すと同じ id が使われるので、無条件に挿入する実装では重複が増えていきます。

ボディを返すかどうかは任意です。 次のような JSON を返すと、どちらの値も使われます。

{ "id": "your-own-id", "url": "https://example.com/blog/seo-basics" }

id はこの記事の次回以降のリクエストで articleId の代わりに送られるキーになり、url は記事の所在として記録されます。何も返さなくても問題ありません。

公開サイトの URL を設定する

受け側に記事の所在を尋ねる仕組みはないため、設定しない限り Growth Calendar はアドレスを知りません。同じ設定画面の 公開サイトの URLhttps://example.com/blog のように入力すると、記事はそのアドレスにスラッグをつないだ場所にあるものとして扱われます。

設定しない場合、 webhook 経由で送った記事は他の記事からリンクされません。次の節を参照してください。

送り方を選ぶ

接続すると、同じ画面で 3 つから選べます。

設定動作
手動自動では送られません。「 CMS に投稿」を選んだときだけ送られます。
下書きとして送る完成した記事が毎回 status: "draft" で送られます。
自動で公開する完成した記事が毎回 status: "published" で送られます。

下書きが何を意味するかは受け側次第です。 Growth Calendar はどちらで送ったかを伝えるだけです。

記事を 1 本だけ送る

記事の右上にある CMS に投稿 を使います。隣のコントロールで、下書きとして送るか公開として送るかを切り替えられます。

内部リンクについて

Growth Calendar は同じクラスタ内の記事同士をリンクします。記事を送るとき、すでにアドレスが決まっている記事へのリンクは実際の URL に置き換わります。それ以外はリンクを外してテキストだけにします。存在しないアドレスへのリンクは読者をエラーページへ送ってしまうためです。

webhook の場合、記事のアドレスが決まるのは公開サイトの URL を設定したときです。設定していないと、この方法で送った記事が他の記事からリンクされることはありません。

画像について

画像は imageUrls と Markdown の両方で Timothe 側のアドレスのままです。どこかにアップロードされることはありません。このアドレスに依存したくない場合は、受け側で自分のストレージへコピーしてください。

うまくいかないとき

「エンドポイントに到達できませんでした」

そのアドレスから応答がありません。受け側がデプロイ済みでインターネットから到達できること、 URL に誤りがないことを確認してください。プライベートネットワークや内部アドレスに解決されるアドレスは拒否されます。

「エンドポイントがシークレットを受け付けませんでした」

受け側が 401 か 403 を返しました。ここで入力したものと同じ値を、Authorization ヘッダーの Bearer <シークレット> という形で照合しているか確認してください。

「その URL では何も待ち受けていません」

受け側が 404 を返しました。ドメインは合っていてパスが違います。ドメインだけでなくエンドポイントのパスまで入力してください。

「そのエンドポイントは POST を受け付けません」

受け側が 405 を返しました。記事はテストリクエストも含めてすべて POST で送られます。

「 https を使用してください」「クエリやフラグメントを含められません」「ポートを指定できません」

エンドポイントは素の https URL である必要があります。受け側がクエリ文字列でトークンを受け取る設計になっている場合は、その値をシークレットに入れて Authorization ヘッダーから読むようにしてください。

「エンドポイントが記事を受け付けませんでした」

記事の送信中に受け側がエラーを返しました。ステータスコードはメッセージに含まれています。その articleId を持つリクエストについて、受け側のログを確認してください。

他の CMS について

WordPress 、 Ghost 、 Shopify 、 Notion は同じ画面から接続できます。これらは自前のコードを介さず直接投稿されます。