CompanyFlowHQ API
あらゆるウェブサイトやアプリからリードを送信し、自社のツールからSNSに投稿し、Webhookで出来事をリアルタイムに受け取れます。Growth、Pro、Social Agencyプランに含まれています。
はじめに
- CompanyFlowHQで設定 → 開発者を開き、APIキーを作成します。必要な権限だけにチェックを入れてください。
- キーはすぐにコピーしてください。キーは
cfhq_live_で始まり、一度しか表示されません。 - APIは必ずサーバーから呼び出してください(顧客が見られるウェブページやアプリからは絶対に呼び出さないでください)。
ベースURL:https://companyflowhq.com/api/v1。リクエストとレスポンスはJSON(UTF-8)です。日時はUTCのISO 8601形式です。金額は最小単位(GBPの場合はペンス)で表します。
認証
キーはAuthorizationヘッダーで送信します:
curl https://companyflowhq.com/api/v1/leads -H "Authorization: Bearer cfhq_live_YOUR_KEY"
権限(スコープ):
| スコープ | キーでできること |
|---|---|
leads:read | リードの読み取り |
leads:write | リードの追加・更新、メモの追加 |
social:read | SNSアカウントと投稿の読み取り |
social:write | SNS投稿の作成と画像のアップロード |
bookings:read | 予約の読み取り |
invoices:read | 請求書の読み取り |
ads:read | Facebook・Instagram広告キャンペーンと結果の読み取り |
webhooks:manage | Webhookの管理 |
hooks:manage | Zapier/Makeのリアルタイムトリガー |
deals:read | 商談の読み取り |
deals:write | 商談の追加 |
invoices:write | 下書き請求書の作成 |
messages:send | メール、SMS、WhatsAppメッセージの送信 |
tickets:write | サポートリクエストの作成 |
キーはいつでも無効化でき、有効期限を設定することもできます。当社が保存するのは各キーのフィンガープリント(SHA-256)のみです。
エンドポイント
| メソッド | パス | スコープ | 内容 |
|---|---|---|---|
| GET | /api/v1/leads | leads:read | リードを新しい順に一覧表示します。フィルター:stage、email、updated_since。 |
| POST | /api/v1/leads | leads:write | リードを追加します(ウェブサイトのフォームと同じ重複チェックと自動返信が適用されます)。 |
| GET | /api/v1/leads/{id} | leads:read | 1件のリード。 |
| PATCH | /api/v1/leads/{id} | leads:write | 詳細、ステージ、優先度を変更します。 |
| POST | /api/v1/leads/{id}/notes | leads:write | リードのタイムラインにメモを追加します。 |
| GET | /api/v1/social/accounts | social:read | 接続済みのSNSアカウント。 |
| POST | /api/v1/social/posts | social:write | 1つ以上のアカウント向けに投稿を作成します:今すぐ、指定日時、次のキュー枠、または下書きとして。 |
| GET | /api/v1/social/posts/{id} | social:read | 投稿のステータスと、各SNSでの結果。 |
| POST | /api/v1/media | social:write | 画像をアップロードします(JPEG、PNG、WebP、GIF、最大20 MB)。そのidを返します。 |
| GET | /api/v1/bookings | bookings:read | 予約。フィルター:from、to、status。 |
| GET | /api/v1/invoices | invoices:read | 送信済みの請求書、見積書、クレジットノート。フィルター:status、kind。 |
| POST | /api/v1/leads/upsert | leads:write | メールアドレスまたは電話番号でリードを検索して更新します。新しい場合は追加します。 |
| GET | /api/v1/leads/search | leads:read | ?email=または?phone=でリードを検索します。 |
| POST | /api/v1/leads/{id}/tasks | leads:write | タスクを追加します(title、due_at、assign_to_email)。 |
| POST | /api/v1/leads/{id}/sequences | leads:write | 自動フォローアップシーケンスを開始します({ sequence_id })。 |
| GET | /api/v1/sequences | leads:read | フォローアップシーケンスの一覧。 |
| POST | /api/v1/messages | messages:send | リードにメール、SMS、WhatsAppを送信します。同意、配信停止、送信停止時間帯が考慮されます。 |
| POST | /api/v1/invoices | invoices:write | 下書きの請求書または見積書を作成します(自動で送信されることはありません)。 |
| GET | /api/v1/invoices/search | invoices:read | ?number=で請求書を検索します。 |
| GET / POST | /api/v1/deals | deals:read / deals:write | 商談を一覧表示または追加します。 |
| GET | /api/v1/deals/pipelines | deals:read | 商談パイプラインとそのステージ。 |
| POST | /api/v1/tickets | tickets:write | サポートリクエストを作成します。 |
| GET | /api/v1/me | any | ワークスペースとキーの所有者(接続テスト)。 |
| POST / DELETE | /api/v1/hooks, /api/v1/hooks/{id} | hooks:manage | RESTフック:URLを1つのイベントに購読、または購読解除します(ZapierとMakeで使用)。 |
| GET | /api/v1/triggers/{event} | hooks:manage | イベントの最新項目を、配信時と同じ形式で返します(?limit=3)。 |
| GET / POST | /api/v1/webhooks | webhooks:manage | Webhookを一覧表示または追加します。 |
| PATCH / DELETE | /api/v1/webhooks/{id} | webhooks:manage | Webhookを変更、オフ、または削除します。 |
リードの例
リードを追加(curl)
curl -X POST https://companyflowhq.com/api/v1/leads \
-H "Authorization: Bearer cfhq_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: form-2026-09-27-000123" \
-d '{
"first_name": "Amara",
"last_name": "Perera",
"email": "amara@example.com",
"phone": "+44 7700 900123",
"requirement": "MSc Data Science, January intake",
"consent_marketing": true
}'
201と{ "data": { …lead } }を返します。その人がすでにワークスペースに登録されている場合(メールアドレスまたは電話番号が同じ場合)は、200と"duplicate": true、既存のリードが返されます。同じIdempotency-Keyを2回送信しても、リードが2件作成されることはありません。
リードを次のステージへ進める(JavaScript)
const res = await fetch("https://companyflowhq.com/api/v1/leads/LEAD_ID", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.CFHQ_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ stage: "qualified", priority: "hot" }),
});
if (!res.ok) {
const { error } = await res.json();
throw new Error(`${error.code}: ${error.message}`);
}
const { data: lead } = await res.json();
SNS投稿の例
まず画像をアップロードし(任意)、次に投稿を作成します。アカウントごとに別のテキストを設定できます。
# 1. Upload a picture
curl -X POST https://companyflowhq.com/api/v1/media \
-H "Authorization: Bearer cfhq_live_YOUR_KEY" \
-F "file=@open-day.jpg"
# → { "data": { "id": "MEDIA_ID", ... } }
# 2. Schedule the post
curl -X POST https://companyflowhq.com/api/v1/social/posts \
-H "Authorization: Bearer cfhq_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Open day this Saturday, 10am to 2pm. Everyone welcome!",
"media_ids": ["MEDIA_ID"],
"accounts": [
{ "account_id": "FACEBOOK_ACCOUNT_ID" },
{ "account_id": "LINKEDIN_ACCOUNT_ID", "text": "Join our open day this Saturday (10:00–14:00)." }
],
"schedule": { "mode": "at", "at": "2026-10-03T08:00:00Z" }
}'
schedule.modeにはnow、at、queue(次の空き枠)、draftのいずれかを指定します。"require_approval": trueを追加すると、代わりにCompanyFlowHQで承認依頼に回されます。投稿には、代理店向けのクライアント承認を含め、アプリと同じルールが適用されます。進捗はGET /api/v1/social/posts/{id}で確認できます。resultsには、各SNSのステータス、リンク、エラーが表示されます。
ページネーション
リストは新しい順に最大limit件(初期値25件、最大100件)を返します:
{ "data": [ … ], "has_more": true, "next_cursor": "WyIyMDI2LTA5…" }
次のページを取得するには、next_cursorの値を?cursor=に指定します。has_moreがfalseになったら終了です。
Webhook
設定 → 開発者(またはAPI)でWebhookを追加します。イベントが発生すると、指定したHTTPSのURLにJSONをPOSTします:
| イベント | 発生するタイミング |
|---|---|
lead.created | 新しいリードが届いたとき |
lead.updated | リードの詳細またはステージが変わったとき |
booking.created | 予約が入ったとき |
invoice.paid | 請求書が全額支払われたとき |
social.post.published | SNS投稿が公開されたとき |
social.post.failed | SNS投稿が失敗したとき |
social.post.milestone | SNS投稿の閲覧数が節目(1,000、2,500、5,000…)を超えたとき |
chat.lead_created | ウェブサイトのチャットがリードになったとき |
lead.stage_changed | リードが別のステージに移ったとき |
lead.won | リードが受注としてマークされたとき |
booking.cancelled | 予約がキャンセルされたとき |
quote.accepted | 顧客が見積書を承諾したとき |
deal.won | 商談を受注したとき |
deal.stage_changed | 商談が別のステージに移ったとき |
form.response | 誰かがフォームまたはアンケートに回答したとき |
ticket.created | 新しいサポートリクエストが届いたとき |
review.feedback | 顧客が非公開のフィードバックを残したとき |
message.received | 受信トレイに新しいメッセージが届いたとき |
POST /your-webhook
Content-Type: application/json
X-CompanyFlow-Event: lead.created
X-CompanyFlow-Delivery: 5f0c…
X-CompanyFlow-Signature: t=1790000000,v1=6b1f…
{ "id": "evt_…", "type": "lead.created", "created": "2026-09-27T10:00:00.000Z",
"data": { "lead": { "id": "…", "first_name": "Amara", … }, "source": "Website" } }
10秒以内に2xxのステータスで応答してください。それ以外は失敗とみなされ、1分後、5分後、30分後、2時間後、12時間後に再試行します。20回連続で失敗するとWebhookはオフになり、オーナーにメールでお知らせします。リダイレクトは追跡せず、URLは公開されたものである必要があります(プライベートネットワークやローカルネットワークは不可)。同じイベントがまれに2回届くことがあるため、idを使って重複を無視してください。
ZapierとMake
Xero、QuickBooks、Slack、Googleスプレッドシートなど、7,000以上のアプリとCompanyFlowHQをノーコードで連携できます。
- 設定 → 開発者でZapierキーを作成(またはMakeキーを作成)を押し、キーをコピーします。
- ZapierではCompanyFlowHQアプリを選び、求められたらキーを貼り付けます。MakeではCompanyFlowHQアプリを追加します(または、ヘッダー
Authorization: Bearer cfhq_live_…を指定してHTTPモジュールを使います)。 - 新しいリード、請求書の支払い完了、商談の受注などのトリガーを選び、もう一方のアプリでのアクションを設定します。
トリガーはリアルタイムです。Zapをオンにすると、ZapierがPOST /api/v1/hooks { "event": "lead.created", "target_url": "https://hooks.zapier.com/…" }で購読し、オフにするとDELETE /api/v1/hooks/{id}で購読を解除します。配信の形式、署名、再試行はWebhookと同じです。410 Goneで応答すると購読が削除されます。有効なトリガーは「設定 → 開発者」で確認・削除できます。
署名の検証
すべてのメッセージは、Webhookのシークレット(whsec_で始まります)で署名されています。署名は<t>.<raw body>のHMAC-SHA256です。必ず署名を検証し、5分より古いメッセージは拒否してください。
Node.js(Express)
import crypto from "node:crypto";
import express from "express";
const app = express();
app.post("/companyflow-webhook", express.raw({ type: "application/json" }), (req, res) => {
const header = req.get("X-CompanyFlow-Signature") ?? "";
const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const expected = crypto
.createHmac("sha256", process.env.CFHQ_WEBHOOK_SECRET)
.update(`${t}.${req.body}`)
.digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300;
const ok =
fresh && v1 && v1.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
if (!ok) return res.status(400).send("Bad signature");
const event = JSON.parse(req.body);
// … handle event.type / event.data …
res.sendStatus(200);
});
Cloudflare Workers/Deno/ブラウザー(Web Crypto)
async function verify(secret, header, rawBody) {
const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const key = await crypto.subtle.importKey(
"raw", new TextEncoder().encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
const sig = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(`${t}.${rawBody}`));
const hex = [...new Uint8Array(sig)].map((b) => b.toString(16).padStart(2, "0")).join("");
return hex === v1; // use a constant-time compare in production
}
レート制限
各キーは1分あたり120件のリクエストを送信できます。すべてのレスポンスにはX-RateLimit-LimitとX-Request-Idが含まれます。上限を超えると、Retry-Afterヘッダー付きで429が返されます。指定された秒数待ってから、もう一度お試しください。
エラー
エラーは常に同じ形式で返されます:
{ "error": { "code": "insufficient_scope", "message": "This API key doesn't have the “leads:write” permission." } }
| ステータス | コード | 意味 |
|---|---|---|
| 400 | invalid_request / invalid_json / invalid_cursor | リクエストに修正が必要な箇所があります。メッセージに内容が表示されます。 |
| 401 | unauthorized / revoked / expired | キーがない、間違っている、無効化されている、または期限切れです。 |
| 402 | plan_required | ワークスペースのプランにAPIが含まれていません。 |
| 403 | insufficient_scope / key_owner_inactive | キーに権限がないか、キーを作成した人がすでにいません。 |
| 404 | not_found | そのidに該当するものがワークスペースにありません。 |
| 409 | conflict | 現在は変更できません(すでに公開された投稿など)。 |
| 413 | payload_too_large | JSONの本文は256 KB未満、画像は20 MB未満にしてください。 |
| 415 | unsupported_media_type | JPEG、PNG、WebP、GIFのいずれかをアップロードしてください。 |
| 429 | rate_limited | 1分あたり120件を超えるリクエストです。Retry-Afterの秒数だけ待ってください。 |
| 500 | server_error | 当社側の問題です。もう一度お試しください。繰り返し発生する場合はX-Request-Idをお知らせください。 |
ご質問はsupport@companyflowhq.comまでメールでお問い合わせください。
