開発者向け

CompanyFlowHQ API

あらゆるウェブサイトやアプリからリードを送信し、自社のツールからSNSに投稿し、Webhookで出来事をリアルタイムに受け取れます。Growth、Pro、Social Agencyプランに含まれています。

はじめに

  1. CompanyFlowHQで設定 → 開発者を開き、APIキーを作成します。必要な権限だけにチェックを入れてください。
  2. キーはすぐにコピーしてください。キーはcfhq_live_で始まり、一度しか表示されません。
  3. 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:readSNSアカウントと投稿の読み取り
social:writeSNS投稿の作成と画像のアップロード
bookings:read予約の読み取り
invoices:read請求書の読み取り
ads:readFacebook・Instagram広告キャンペーンと結果の読み取り
webhooks:manageWebhookの管理
hooks:manageZapier/Makeのリアルタイムトリガー
deals:read商談の読み取り
deals:write商談の追加
invoices:write下書き請求書の作成
messages:sendメール、SMS、WhatsAppメッセージの送信
tickets:writeサポートリクエストの作成

キーはいつでも無効化でき、有効期限を設定することもできます。当社が保存するのは各キーのフィンガープリント(SHA-256)のみです。

エンドポイント

メソッドパススコープ内容
GET/api/v1/leadsleads:readリードを新しい順に一覧表示します。フィルター:stage、email、updated_since。
POST/api/v1/leadsleads:writeリードを追加します(ウェブサイトのフォームと同じ重複チェックと自動返信が適用されます)。
GET/api/v1/leads/{id}leads:read1件のリード。
PATCH/api/v1/leads/{id}leads:write詳細、ステージ、優先度を変更します。
POST/api/v1/leads/{id}/notesleads:writeリードのタイムラインにメモを追加します。
GET/api/v1/social/accountssocial:read接続済みのSNSアカウント。
POST/api/v1/social/postssocial:write1つ以上のアカウント向けに投稿を作成します:今すぐ、指定日時、次のキュー枠、または下書きとして。
GET/api/v1/social/posts/{id}social:read投稿のステータスと、各SNSでの結果。
POST/api/v1/mediasocial:write画像をアップロードします(JPEG、PNG、WebP、GIF、最大20 MB)。そのidを返します。
GET/api/v1/bookingsbookings:read予約。フィルター:from、to、status。
GET/api/v1/invoicesinvoices:read送信済みの請求書、見積書、クレジットノート。フィルター:status、kind。
POST/api/v1/leads/upsertleads:writeメールアドレスまたは電話番号でリードを検索して更新します。新しい場合は追加します。
GET/api/v1/leads/searchleads:read?email=または?phone=でリードを検索します。
POST/api/v1/leads/{id}/tasksleads:writeタスクを追加します(title、due_at、assign_to_email)。
POST/api/v1/leads/{id}/sequencesleads:write自動フォローアップシーケンスを開始します({ sequence_id })。
GET/api/v1/sequencesleads:readフォローアップシーケンスの一覧。
POST/api/v1/messagesmessages:sendリードにメール、SMS、WhatsAppを送信します。同意、配信停止、送信停止時間帯が考慮されます。
POST/api/v1/invoicesinvoices:write下書きの請求書または見積書を作成します(自動で送信されることはありません)。
GET/api/v1/invoices/searchinvoices:read?number=で請求書を検索します。
GET / POST/api/v1/dealsdeals:read / deals:write商談を一覧表示または追加します。
GET/api/v1/deals/pipelinesdeals:read商談パイプラインとそのステージ。
POST/api/v1/ticketstickets:writeサポートリクエストを作成します。
GET/api/v1/meanyワークスペースとキーの所有者(接続テスト)。
POST / DELETE/api/v1/hooks, /api/v1/hooks/{id}hooks:manageRESTフック:URLを1つのイベントに購読、または購読解除します(ZapierとMakeで使用)。
GET/api/v1/triggers/{event}hooks:manageイベントの最新項目を、配信時と同じ形式で返します(?limit=3)。
GET / POST/api/v1/webhookswebhooks:manageWebhookを一覧表示または追加します。
PATCH / DELETE/api/v1/webhooks/{id}webhooks:manageWebhookを変更、オフ、または削除します。

リードの例

リードを追加(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.publishedSNS投稿が公開されたとき
social.post.failedSNS投稿が失敗したとき
social.post.milestoneSNS投稿の閲覧数が節目(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をノーコードで連携できます。

  1. 設定 → 開発者でZapierキーを作成(またはMakeキーを作成)を押し、キーをコピーします。
  2. ZapierではCompanyFlowHQアプリを選び、求められたらキーを貼り付けます。MakeではCompanyFlowHQアプリを追加します(または、ヘッダーAuthorization: Bearer cfhq_live_…を指定してHTTPモジュールを使います)。
  3. 新しいリード、請求書の支払い完了、商談の受注などのトリガーを選び、もう一方のアプリでのアクションを設定します。

トリガーはリアルタイムです。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." } }
ステータスコード意味
400invalid_request / invalid_json / invalid_cursorリクエストに修正が必要な箇所があります。メッセージに内容が表示されます。
401unauthorized / revoked / expiredキーがない、間違っている、無効化されている、または期限切れです。
402plan_requiredワークスペースのプランにAPIが含まれていません。
403insufficient_scope / key_owner_inactiveキーに権限がないか、キーを作成した人がすでにいません。
404not_foundそのidに該当するものがワークスペースにありません。
409conflict現在は変更できません(すでに公開された投稿など)。
413payload_too_largeJSONの本文は256 KB未満、画像は20 MB未満にしてください。
415unsupported_media_typeJPEG、PNG、WebP、GIFのいずれかをアップロードしてください。
429rate_limited1分あたり120件を超えるリクエストです。Retry-Afterの秒数だけ待ってください。
500server_error当社側の問題です。もう一度お試しください。繰り返し発生する場合はX-Request-Idをお知らせください。

ご質問はsupport@companyflowhq.comまでメールでお問い合わせください。