契約の稟議(社内の申請・承認)が承認された。では、誰が契約書を送るのか。ある会社(約90名)では、そこが決まっていなかった。案件の担当者が Slack に「稟議完了」と書いてから、法務が動く。法務は2人いる。2人とも気づいて電子契約を作れば、同じ契約書が先方に2通届く。
法務から相談を受けて、仕組みを作った。TeamSpirit(社内の申請・承認を回すサービス)で稟議が承認されたら、それを合図に Slack に通知を出す。通知の[対応する]を押した人が、その契約の担当になる。画面の設定だけでほぼ作れた。ただ、TeamSpirit から Slack に送る1か所だけは、最初に試した形では Slack に受け付けてもらえず、そこだけ短いプログラムにした。
先に断っておく。本番には入れて動かしているが、通知先はまだテスト用のチャンネルで、法務の人にはまだ使ってもらっていない。事実は2026年11月10日の時点のものだ。設定の名前やプログラムは、後半の「担当者向け」にまとめた。
この記事でわかること
- ▶ 承認を知らせるだけでは、2人で同じ契約書を送るのは防げない理由と、ボタンで担当を決める形
- ▶ 通知に載せたもの・載せなかったもの(金額は載せない)
- ▶ 「コードなしで」のつもりが1か所だけプログラムになった経緯と、どこまでをプログラムにしたか
- ▶ 作る前に決めておくこと(受け口のアドレスの扱い・作業用の権限・持ち主と止め方)と、自分の会社で確かめること
▼作った理由:契約の稟議は月5〜11件。承認のあと、誰が送るかが決まっていない
契約の稟議が承認されたあと、次に誰が動くかが決まっていなかった。法務から聞いた今の流れは次のとおりだ。
法務のチェック → 稟議の申請・承認 → 契約書の発送(紙か電子契約)→ 契約書に署名する役員が署名 → 先方が署名 → 締結
この会社では、契約の稟議の承認は月に5〜11件ある(2026年7〜10月)。困りごとは2つあった。
- ▶ 承認を知るのが、担当者の投稿待ち:案件の担当者が「稟議完了」と書くまで、法務は発送に入れない。一手間かかっている
- ▶ 法務の2人のどちらが動くか決まっていない:2人とも電子契約を作り、2通送ってしまうことが起こりうる
やりたいことは3つに絞った。承認を合図に法務が発送に入れること。2人の作業が重ならないこと。役員への署名の依頼まで、同じ流れの中で出せることだ。
▼仕組み:承認 → Slack に通知 → [対応する]を押した人が担当
この会社の稟議は TeamSpirit(勤怠と社内の申請・承認をまとめて扱うサービス。Salesforce という業務システムの土台の上で動く)で回っている。稟議が承認済みになると、Salesforce の自動処理が Slack の「ワークフロー」に知らせる。ワークフローは、Slack の中でボタンやフォームをコードなしで組める機能だ。
Slack に出るものと、押す人は次の4段になる。
| 段 | Slack に出るもの | 押す人 |
|---|---|---|
| 1 | 専用のチャンネルに通知(件名・会社名・押印の種類・申請者・稟議へのリンク)+[対応する] | 法務のどちらか |
| 2 | スレッドに「◯◯ が対応中です」+[署名依頼] | 担当になった人 |
| 3 | フォームが開き、URL を貼る → スレッドで役員に署名をお願いするメンション(件名・押印の種類・貼った URL)+担当者に締結が済んだら押すよう頼む一文+[締結完了] | 担当になった人 |
| 4 | 先方の署名が済んだら[締結完了]→ スレッドに「締結完了(◯◯)」 | 担当になった人(法務) |
通知に載せたもの・載せなかったもの
| 載せた | 載せなかった |
|---|---|
| 件名、会社名、押印の種類(電子契約か紙か。発送のしかたが分かる)、申請者、稟議へのリンク | 金額、法務の指摘を書く欄、区分、契約期間 |
契約の中身は Slack に流さない。発送に入るのに要るものだけを載せ、中身はリンクから稟議を開いて見る。区分は、依頼者(法務の1人)が要らないと決めた。
最後のボタンは「対応完了」ではなく「締結完了」
最後のボタンの名前は「締結完了」にした。「対応完了」だと、署名を終えた役員が自分の対応が済んだと思って押しかねない。押すのは先方の署名まで見届けた法務の担当者なので、担当者にメンションして、締結が済んだら押すよう頼む文面にした。
押したあとの表示も役に立つ。自分の画面では、[対応する]を押すと、元の通知のボタンが「誰が押したか」の表示に変わった。スレッドを開かなくても、誰が持ったか分かる。ただ、ほかの人の画面でも同じように変わるかは、まだ確かめていない。変わらなければ、2人目も[対応する]を押せてしまうかもしれない。本番のチャンネルで法務の2人に押してもらって確かめる。表示の一部(「clicked」)は英語のままで、変えられるかも分かっていない。
▼判断の分かれ目:欲しいのは通知ではなく「誰が持ったか」が残るボタン。すでにある連携は使わなかった
相談の入り口は、承認の通知だった。目的を聞くと、2人の作業が重ならないようにしたい、ということだった。通知が届くだけなら、2人とも見て、2人とも動く。知らせるだけでは、重複は防げない。要るのは、誰が持ったかが残ることだった。
この会社の Salesforce には、別の用途で Slack に投稿する連携がすでにあった。前例どおりに作れば早い。ただ、その連携が出すのは普通のメッセージで、ボタンは付かない。TeamSpirit 自身にもチャットとの連携の機能が入っていたが、使われていなかった。
そこで、通知は Slack のワークフローで受けることにした。ボタンが付けられ、Slack 側はコードなしで組める。作った自分がいなくなっても、会社の人が文面やボタンを直せる。
あわせて、やらないことも2つ決めた。
- ▶ Slack で押した結果を、Salesforce に書き戻さない:書き戻すと作りが重くなり、TeamSpirit の製品側の部品を触ることになる。誰が持ったか・いつ締結したかは、Slack のスレッドに残る
- ▶ 法務の既存のチャンネルのやりとりに、直接は書き込まない:法務は契約ごとのやりとりを別のチャンネルでしている。そこへの書き込みはワークフローだけではできず、別のプログラムが要る。代わりに専用のチャンネルに通知し、3段目のフォームに URL を貼ってもらう形にした。貼るのは、法務のチャンネルのその契約のやりとりへのリンクに決めた。依頼者からは「流れを法務チャンネルに戻せる」と了承をもらった
「通知が欲しい」と言われたら、通知のあと誰が何をするかまで聞く。担当を決めたいなら、通知ではなくボタンが要る。ここが一番の分かれ目だった。
▼一番引っかかったこと:試したコードなしの送り方は Slack に受け付けられず、送る部分だけプログラムにした
最初は、Salesforce から Slack への送信も、プログラムを書かずに作った。Salesforce にある、設定だけで外に送る仕組み(外部サービス)を使った。ところが、試験環境(本番の設定を写した練習用の環境)で稟議を承認しても、Slack に通知が届かなかった。
調べると、Slack が「その場所は移った」という返事(301)を返して、受け取っていなかった。外部サービスは、送り先を「土台のアドレス」と「その後ろに付ける部分」に分けて書く決まりで、後ろの部分は「/」で始める。土台のほうにアドレスを丸ごと入れたので、最後に「/」が1文字付く形になった。これが原因だと判断した。同じアドレスでも、最後に「/」を付けずに手元から送ったときは、Slack は受け付けていた。
試したのは1つの形だけだ。受け口のアドレス(Slack のワークフローが外から通知を受け取る専用のアドレス)を丸ごと、Salesforce の中の送り先をしまっておく場所(土台のアドレス)に入れる形だ。アドレスを前半と後半に分けて設定すれば「/」は付かないはずだが、試していない。分けると、鍵にあたるアドレスの後半が、しまっておく場所の外に残ってしまう(アドレスを鍵と同じに扱う理由は、後の「始める前に決めておくこと」で書く)。
そこで、送る部分だけを Apex(Salesforce の中で動くプログラム)にした。40行ほどと、動きを確かめるテストが2つだ。どの稟議で通知を出すかの条件と、通知に載せる値の組み立ては、画面の設定のまま残した。プログラムは、直す人が読める量にとどめたかった。
「コードなしで作ってほしい」と頼んでも、相手のサービスがその送り方を受け付けるかは、試すまで分からない。1か所だけプログラムになったら、どこまでをプログラムにするかを決める。そして、会社のシステムにプログラムが増えることは、会社に説明が要る。この会社には、進捗の共有で伝えた。
ほかにも細かいつまずきが2つあった(通知の申請者の欄が空になった件と、Slack 側で受け取る値の名前に日本語が使えない件)。どちらも後半の担当者向けに書いた。
▼かかった期間:相談から本番まで8日。組んだのは2日
| 日付(2026年) | やったこと |
|---|---|
| 11/2 | 法務から相談。TeamSpirit 側の設定を読んで、どこで承認済みになるか、既存の連携が何かを調べた |
| 11/4 | 「ボタン付きの Slack ワークフロー」に決めて、法務に流れを返した。作業用の権限を準備 |
| 11/6 | 依頼者と、通知に載せるもの・ボタンの流れを詰めた |
| 11/9 | Slack 側を組んで、ダミーの通知で最後のボタンまで動くことを確認 |
| 11/9〜10 | 試験環境で Salesforce 側を組み、承認から通知まで通した(301 の切り分けもここ) |
| 11/10 | 本番に入れて有効化(通知先はテスト用のチャンネル) |
試験環境には、本番と同じ承認ルートが入っていた。データは空で、メールも止まっていた。だから役員に頼まなくても、自分で申請から承認まで通して試せた。
▼始める前に決めておくこと:受け口のアドレスの置き場所・作業用の権限・持ち主と止め方
受け口のアドレスは鍵と同じ。置き場所は1つにする
Slack のワークフローには、外から通知を受け取る専用のアドレス(受け口のアドレス)がある。このアドレスを知っていれば、誰でもそのチャンネルに通知を流せる。だから鍵と同じに扱う。
手順書やチャットには書かない。Salesforce の中の、外への送り先をしまっておく場所にだけ置く。プログラムにも、画面の設定にも書かない。差し替えるときは、その1か所を変えるだけで済む。
作業用の権限は、足すものを1つに絞って伝える
自分のアカウントには、その「しまっておく場所」を作る権限がなかった。管理者の権限をまるごと広げてもらう代わりに、その権限だけを入れた作業用の権限のセットを作り、自分に割り当てた。足したことは、進捗の共有で依頼者に伝えた。作業が終わったら外す。外部の立場で自分の権限を足せるなら、何を足したか・いつ外すかを先に決めて伝える。
持ち主と止め方
- ▶ 持ち主:Slack のワークフローの共同管理者に、法務の2人などを入れる(まだ入れていない)。作った自分の契約が切れても止まらないようにする
- ▶ 止め方は2つ:Salesforce 側の自動処理を無効にする。または、Slack のワークフローを非公開にする
- ▶ 失敗しても承認は止まらない:通知は承認のあとに別で動く。Slack が受け付けないときは、Salesforce が数時間のあいだ自動でやり直す(試験環境では4回やり直した)
▼本番の入れ方:通知先をテスト用のまま、本番に入れた
最後に確かめたいのは、実際の承認で動くかだ。試験用の稟議を本番で通すと、承認者である役員に、意味のない承認をお願いすることになる。
そこで、本番に入れて有効にし、通知先だけをテスト用のチャンネルにした。実際の契約の稟議が承認されると、テスト用のチャンネルに通知が届く。月5〜11件あるので、待てば本物で確かめられる。
本番に入れたあと、2つやった。テスト用のチャンネルを非公開にした(本物の件名と会社名が載るため)。本番に入れたことを依頼者に伝え、了承をもらった。
通知が出てはいけない場面は、試験環境で3つ確かめた。別の種類の稟議の承認、契約の稟議の却下、承認済みの稟議の保存し直しだ。どれも通知は出なかった。本番からの試しの送信は Slack に届いている。本物の承認での通知は、次の承認を待っている。
▼まだ終わっていないこと
- ▶ 本番のチャンネルとメンバーを決め、通知先を切り替える:依頼者と決める。法務の人には、まだ使ってもらっていない
- ▶ まだ確かめていないこと:役員へのメンションが届くか(テスト用では名前をただの文字にしている)/ほかの人の画面でもボタンの表示が変わるか/役員が承認したときに権限が足りるか/稟議へのリンクが本番で正しく開くか/失敗したときの知らせのメールが誰に届くか/代わりに稟議を作る運用があると、申請者の欄に別の人の名前が出ないか/署名する役員が法務のチャンネルに入っているか(入っていないと、貼ったリンクを開けない)
- ▶ 持ち主を入れる:Slack のワークフローの共同管理者に、法務の2人などを入れる
- ▶ 法務に渡す運用メモ:ボタンの意味、持ち主、止め方。稟議へのリンクが入った通知には、Slack が本人にだけ「Salesforce に接続しますか?」と出すが、押さなくていいこと
- ▶ 後片付け:作業用の権限を外す。テスト用のワークフローを消す
▼まとめ:自分の会社で確かめること
稟議や申請の承認を、チャットで回したい会社は、担当者(または委託先)に次を確かめてもらえばいい。
- ▶ 承認のあと、誰が次に動くかが決まっているか:「誰かが見て動く」になっていないか
- ▶ 通知を頼むとき、通知のあと誰が何をするかまで決めたか:担当を決めたいなら、ボタンが要る
- ▶ 通知に、契約の中身(金額など)を流していないか:載せるのは動くのに要るものだけ。中身はリンクから見る
- ▶ 作った人がいなくなったら、誰が止め方を知っているか:共同管理者と、止め方のメモがあるか
- ▶ 受け口のアドレスを、手順書やチャットに貼っていないか:置き場所は1つにする
▼担当者向け:設定と手順の詳細
ここからは、実際に設定する人向けに、正式な名前と手順を書く。環境は Salesforce の Enterprise Edition、フローの API バージョンは 62.0、2026年11月時点。
前半の言い方と、実際の名前
| 前半の言い方 | 実際の名前 |
|---|---|
| 稟議が承認済みになる | 稟議オブジェクト teamspirit__AtkApply__c のステータス teamspirit__Status__c が「承認済み」になる(承認プロセスの項目自動更新 teamspirit__AtkApplySetApproved で入る) |
| Salesforce の自動処理 | レコードトリガーフロー(更新時・保存後・非同期パス) |
| コードなしで外部に送る仕組み | 外部サービス(External Services)。フローの HTTP 呼び出しの裏で使われる仕組み。今回はメタデータ API で登録 |
| 外への送り先をしまっておく場所 | 指定ログイン情報(Named Credential)。従来の形・認証なし |
| 作業用の権限のセット | 権限セット(システム権限「指定ログイン情報の管理」だけ) |
| 受け口のアドレス | ワークフロービルダーの Webhook トリガー(https://hooks.slack.com/triggers/...) |
| 送る部分だけのプログラム | Apex の呼び出し可能メソッド(@InvocableMethod) |
フローの開始条件
- ▶ オブジェクトとタイミング:稟議(
teamspirit__AtkApply__c)、レコードの更新時、保存後 - ▶ 条件:ステータスが「承認済み」に変わったときだけ(「レコードが更新されて条件を満たしたときのみ」)AND 稟議の種別の項目=契約の値。この会社の種別の値は「番号+全角スペース+名前」の形(例:
04. 契約)で、1文字違うと条件に合わない。承認ルートの条件と同じ話は同じ会社の TeamSpirit の記事にも書いた - ▶ 承認プロセスの項目自動更新でも動いた:TeamSpirit の承認プロセスは最終承認でステータスを項目自動更新で「承認済み」にする。これでレコードトリガーフローが動くことを試験環境で確かめた
- ▶ 外を呼ぶのは非同期パス:保存後のフローから外部を呼ぶので、非同期パス(Run Asynchronously)に置いた。非同期パスは、承認した人のユーザーで動いた(試験では自分が承認者)
- ▶ 稟議の URL:数式で
LEFT({!$Api.Partner_Server_URL_620}, FIND("/services", {!$Api.Partner_Server_URL_620}) - 1) & "/" & {!$Record.Id}。本番で正しく開くかは未確認 - ▶ 空の項目:「(未入力)」にして送る
301 になった形(外部サービス)
301 で失敗したのは、次の形だ。
- ▶ 指定ログイン情報:従来の形(Legacy)、認証なし(ID の種類「匿名」、認証プロトコル「認証なし」)。URL 欄に Webhook の URL を丸ごと(
https://hooks.slack.com/triggers/XXXX/XXXX/XXXXの形) - ▶ 外部サービス:フロービルダーの画面ではなく、メタデータ API で登録した(
ExternalServiceRegistration、OpenAPI 3.0.1 の仕様。上の指定ログイン情報を参照。パスは/、操作は POST、本文は5つのキーを持つ JSON) - ▶ 呼び方:フローの非同期パスから、その外部サービスのアクションを呼ぶ
- ▶ 結果:フローは失敗。フローの実行記録のエラーは「Moved Permanently」。Apex の匿名実行から同じ外部サービスを呼ぶと、応答の例外の
responseCodeが 301 - ▶ 比べたもの:同じ Webhook の URL に、手元の curl で末尾に
/を付けずに JSON を POST すると 200 で、通知が出た
OpenAPI では、パスは / で始める決まりになっている(OpenAPI 3.0.1 の Paths Object)。URL を丸ごと指定ログイン情報に入れたのでパスは / だけになり、送り先は「指定ログイン情報の URL + /」になる。Slack の Webhook は末尾に / が付いた URL に 301 を返し、Salesforce 側はそれを失敗として扱った、と判断している。根拠は、パスが / だったこと、301 が返ったこと、末尾に / のない curl は 200 だったことの3つで、送られた URL そのものはログで見ていない。なお、フロービルダーで HTTP 呼び出しを作ると外部サービスが自動で作られる、と Salesforce の管理者向けブログにある(Salesforce Admins Blog)。ただ、画面でパスを空にできるかは確かめていないので、画面から作っても同じことが起きるとは言えない。次のことは試していない。
- ▶ 末尾に
/を付けた URL に curl で送り、301 が返るか - ▶ 実際に送られた URL を、デバッグログで目で見ること
- ▶ フロービルダーの「HTTP 呼び出しを作成」の画面から作った場合(裏で外部サービスとして保存されると理解しているが、同じ結果になるかは試していない)
- ▶ 指定ログイン情報を
https://hooks.slack.comまでにして、/triggers/...を外部サービスのパスに書く形(末尾の/は付かないはずだが、Webhook の URL の後半が外部サービスの定義に残る)
外部サービスで作っていたときに気づいたことが2つある。外部サービスの名前は、アンダースコアを入れると「英字で始まり、英数字のみを含む名前を入力してください」で登録できなかった。また、キーのアンダースコアは、生成されるクラスの項目名では x5f に置き換わる(imprint_type が imprintx5ftype になる)。
送る部分だけの Apex
Slack の Webhook には、Apex の HttpRequest で callout: +指定ログイン情報の名前に POST する。URL はコードに書かない。名前は一般化し、空の値を「(未入力)」に置き換える部分は省いて載せる。
- ▶
callout=true:外部を呼ぶ呼び出し可能メソッドに付ける - ▶ 200 以外は例外にする:フローが失敗扱いになり、実行記録に残る。黙って失敗させない
- ▶ キーは Slack のワークフローの変数と同じ名前:
subject・company・imprint_type・applicant・approval_url
テストは2つ。送るキーが合っているかと、Slack が 301 を返したら例外になるかだ。後者の要点は次のとおり。
ほかに引っかかったこと
- ▶ 非同期パスで申請者の名前が空になった:最初は
$Record.CreatedBy.Nameを渡していた。試験環境で承認すると、Slack の通知の申請者が「(未入力)」だった。フローに「レコードを取得」を足し、User をId = $Record.CreatedByIdで1件取って、そのNameを渡す形に直した。直したあと、申請者の名前が入ることを確かめた - ▶ Slack の Webhook の変数のキーに日本語が使えない:画面で試すと、使えたのは英字・数字・ハイフン・アンダースコアだけだった。変数の型はすべてテキストにした
- ▶ 申請者は Slack のメンションにしていない:Salesforce の側から Slack のユーザーを特定する情報が取れないので、名前の文字だけを出している
Slack のワークフロー
- ▶ 起動:Webhook。変数は5つ(すべてテキスト)
- ▶ ステップ:チャンネルにメッセージ+ボタン[対応する]→ スレッドに返信(「{押した人} が対応中です」)+ボタン[署名依頼]→ フォーム(法務のチャンネルのやりとりへのリンクを貼る)→ スレッドに返信(役員へのメンション+貼った URL、担当者へのお願い)+ボタン[締結完了]→ スレッドに返信(「締結完了({押した人})」)
- ▶ 返信先:どのスレッドへの返信も、ステップ1のメッセージに返す
- ▶ Webhook 起動でも、ボタンのあとにフォームを開けることを確かめた
- ▶ 表示の細かい点:スレッドのボタンを押すと「{押した人} さんが「*署名依頼*」をクリックしました」のように、アスタリスクが付いたまま出た
- ▶ 持ち主:共同管理者に法務の2人などを入れる(まだ入れていない)
本番への入れ方
月末・月初は稟議が多いので避けた。Webhook の URL はファイルにもチャットにも書かない。
- 指定ログイン情報を初回だけ入れる。URL は仮の値でメタデータに書き、入れたあと設定画面で本物に差し替える
- Apex とフローを入れる(テストは
RunSpecifiedTestsで上のテストクラスを指定。フローは無効のまま入る)。本番では、最初に検証だけ(変更なし)を流して、テスト2件が通ることを確かめた - 設定画面でフローを有効にする
- 作業用の権限セットの割り当てを外す
2回目以降に Apex やフローを直すときは、2 だけ。1 を入れ直すと、URL が仮の値に戻って通知が止まる。通知先を変えるときは、設定画面で指定ログイン情報の URL だけ差し替える。
失敗したとき
- ▶ 自動のやり直し:試験環境では、最初の失敗のあと、約15分・31分・61分・2時間の間隔で4回やり直した(どれも 301 で失敗)
- ▶ 記録:やり直しでも失敗したものは、フローの実行記録(FlowInterview。状態が Error)に残る
- ▶ 失敗のメール:フローのエラーメールの宛先(設定 → プロセスの自動化の設定)に届く。本番の宛先は未確認
未検証
- ▶ 本番の承認者(役員)のプロファイルで、Apex クラスへのアクセスが要るか(試験は管理者が承認した)
- ▶ 稟議の URL が本番で正しく開くか
- ▶ 本物のメンションが届くか、ほかの人の画面でボタンの表示が変わるか
- ▶ 上の「301 になった形」で試していないもの
📅 30分無料相談、受け付けています
「承認のあと、誰が動くかが決まっていない」「Salesforce と Slack をつなぎたいが、作った人がいなくなったあとが心配」——そういった段階からお気軽にどうぞ。業務の流れの聞き取りから、仕組みづくりと止め方の引き継ぎまで対応しています。
📅 30分無料相談を予約する →