外部サービス連携

Salesforceのホームからfreeeに打刻する

freee人事労務のAPIを画面フローから呼ぶと、Salesforceのホームで出勤と退勤を打刻できます。2021年に作った自社の仕組みを、2026年9月時点のAPIの仕様とSalesforceの公式ヘルプで確かめ直し、Apexのサンプルを足しました。

2021.03.24

どういうときに使うのか

私たちはfreee人事労務で勤怠を管理しています。freee人事労務にはWeb画面やアプリから打刻する機能がありますが、打刻のためだけに別の画面を開くのは手間です。

私たちの会社ではSalesforceが業務の中心で、仕事を始めるときに必ず開きます。そこで、Salesforceのホーム画面から、そのまま出勤と退勤を打刻できるようにしました。

作ったものは次の4つです。

部品役目
freeeのアプリSalesforceからfreeeのAPIを呼ぶための Client ID と Client Secret を発行する
認証プロバイダと指定ログイン情報OAuthでfreeeに認証し、APIの呼び出し先をまとめる
Apexのクラス打刻できる種別を取る処理と、打刻する処理を画面フローから呼べるようにする
画面フローホームに置き、「出勤」か「退勤」を表示して打刻する

freee側でアプリを作る

  1. アプリを作る

    freeeのアプリストアの開発者向け画面でアプリを作ります。発行された Client ID と Client Secret は、あとでSalesforceの認証プロバイダに入れます。

  2. コールバックURLはあとで上書きする

    コールバックURLは、Salesforceで認証プロバイダを作ったあとに表示されるURLへ書き換えます。

  3. 権限を付ける

    権限設定で、打刻の参照と登録ができるようにします。

freeeアプリストアのアプリ詳細画面。アプリ名Salesforce連携、コールバックURL、Client IDの欄がある
freee側のアプリの基本情報です。コールバックURLとClient IDの値は伏せています。

Salesforce側の設定

リモートサイトの設定

当時は、freeeの認証のURLと、APIのURLの2つをリモートサイトに登録していました。

リモートサイトの詳細。リモートサイト名freeeAPI_AccessToken、URLはhttps://accounts.secure.freee.co.jp
認証のURLを登録したリモートサイトです。
リモートサイトの詳細。リモートサイト名freeeAPI、URLはhttps://api.freee.co.jp
APIのURLを登録したリモートサイトです。
Salesforceの公式ヘルプでは、指定ログイン情報に定義したサイトへの呼び出しは、リモートサイトの設定を省けると書かれています。指定ログイン情報を通して呼ぶなら、APIのURLのリモートサイトは要りません。

認証プロバイダ

種類は Open ID Connect にし、freeeのアプリの Client ID と Client Secret を入れます。承認とトークンのエンドポイントには、freeeの認証のURLを入れます。

認証プロバイダの詳細。プロバイダタイプOpen ID Connect、名前Freee、承認エンドポイントとトークンエンドポイントのURL
当時の認証プロバイダです。認証プロバイダIDとコンシューマ鍵は伏せています。

承認エンドポイントの https://accounts.secure.freee.co.jp/public_api/authorize は、2026年9月時点のfreeeのクイックスタートでも同じURLです。

指定ログイン情報

URLに https://api.freee.co.jp/hr/api/v1 を入れ、ID種別をユーザ、認証プロトコルをOAuth 2.0、認証プロバイダを上で作ったものにします。ID種別をユーザにすると、打刻は利用者それぞれのfreeeアカウントで行われます。

指定ログイン情報の編集画面。表示ラベルFreeeHrUser、URL https://api.freee.co.jp/hr/api/v1、ID種別ユーザ、認証プロトコルOAuth 2.0
当時の指定ログイン情報です。ID種別を「ユーザ」にしています。
2026年9月時点の注意です。この画面の形式は、いまは「従来の指定ログイン情報」と呼ばれています。Salesforceの公式ヘルプでは、従来の指定ログイン情報は非推奨で、今後のリリースではサポートされないとされています。Winter '23で入った新しい形式(外部ログイン情報と組み合わせる指定ログイン情報)で作ることが勧められています。

Apexで2つの処理を作る

freee人事労務のAPIで使うのは、次の3つです。2026年9月時点のfreee公式のAPIスキーマで確かめました。

API使いどころ
GET /api/v1/users/meログインユーザーの事業所IDと従業員IDを取る
GET /api/v1/employees/{employee_id}/time_clocks/available_typesいま打刻できる種別を取る。すでに出勤していれば、休憩開始と退勤が返る
POST /api/v1/employees/{employee_id}/time_clocks打刻する。事業所IDと種別(clock_in、break_begin、break_end、clock_out)が必須

当時は自社用に書いたコードで、エラー処理が不十分だったため掲載していませんでした。今回、同じ考え方のサンプルを書き直しました。

public with sharing class FreeeHrApi {
    public class FreeeHrException extends Exception {}

    public class Me {
        public Integer companyId;
        public Integer employeeId;
    }

    // ログインユーザーが従業員として登録されている事業所を1つ返す
    public static Me me() {
        Map<String, Object> body = send('GET', '/users/me', null);
        for (Object c : (List<Object>) body.get('companies')) {
            Map<String, Object> company = (Map<String, Object>) c;
            if (company.get('employee_id') != null) {
                Me m = new Me();
                m.companyId = (Integer) company.get('id');
                m.employeeId = (Integer) company.get('employee_id');
                return m;
            }
        }
        throw new FreeeHrException('freee人事労務に従業員として登録されていません');
    }

    public static Map<String, Object> send(String method, String path, Map<String, Object> payload) {
        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:FreeeHrUser' + path);
        req.setMethod(method);
        req.setTimeout(20000);
        if (payload != null) {
            req.setHeader('Content-Type', 'application/json');
            req.setBody(JSON.serialize(payload));
        }
        HttpResponse res = new Http().send(req);
        if (res.getStatusCode() >= 300) {
            throw new FreeeHrException('freee APIの呼び出しに失敗しました: ' + res.getStatusCode() + ' ' + res.getBody());
        }
        return (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
    }
}

指定ログイン情報を通してfreee人事労務のAPIを呼ぶ共通処理

public with sharing class FreeeHrGetTimeClocksAvailableType {
    @InvocableMethod(label='freee 打刻可能種別の取得')
    public static List<String> run() {
        FreeeHrApi.Me m = FreeeHrApi.me();
        Map<String, Object> body = FreeeHrApi.send('GET',
            '/employees/' + m.employeeId + '/time_clocks/available_types?company_id=' + m.companyId, null);
        List<Object> types = (List<Object>) body.get('available_types');
        String result = '';
        if (types.contains('clock_in')) {
            result = 'clock_in';
        } else if (types.contains('clock_out')) {
            result = 'clock_out';
        }
        return new List<String>{ result };
    }
}

いま打刻できる種別を出勤か退勤で返す

public with sharing class FreeeHrPostTimeClocks {
    @InvocableMethod(label='freee 打刻の登録')
    public static List<String> run(List<String> types) {
        FreeeHrApi.Me m = FreeeHrApi.me();
        FreeeHrApi.send('POST', '/employees/' + m.employeeId + '/time_clocks',
            new Map<String, Object>{ 'company_id' => m.companyId, 'type' => types[0] });
        return new List<String>{ types[0] };
    }
}

画面フローから受け取った種別で打刻する

ここで間違えやすいところです。打刻の登録APIは、整合性の取れない打刻を受け付けません。freeeのAPIスキーマには、休憩開始の連続や退勤だけの打刻は登録できないと書かれています。先に打刻できる種別を取り、その結果だけを画面に出すのはこのためです。

画面フローとホームへの配置

画面は、コードを書かずに画面フローで作りました。最初の画面で「次へ」を押すと打刻できる種別を取り、2つ目の画面で「出勤」か「退勤」を出し、もう一度「次へ」で打刻します。

Flow Builderの画面。画面、Apexアクション、画面、Apexアクション、画面の順に並んだ画面フロー
当時の画面フローです。2つのApexアクションを、画面の間に挟んでいます。
Lightningアプリケーションビルダーでホームページの右上にフローコンポーネントを置いている画面
ホームページの右上に、フローのコンポーネントとして置きました。

動かしてみる

  1. 利用者がfreeeの認証を通す

    個人設定の「外部システムの認証設定」で、指定ログイン情報「FreeeHrUser」を選び、保存時に認証フローを開始します。freeeの画面で「許可する」を押すと、Salesforceに戻って認証が終わります。

  2. ホームで「次へ」を押す

    ここでAPIを呼び、いま打刻できる種別を取ります。

  3. 「出勤」か「退勤」を確かめて打刻する

    見間違いを防ぐため、出勤はオレンジ、退勤は青で表示しました。もう一度「次へ」を押すと、freee人事労務に打刻されます。

外部システムの認証設定の編集画面。指定ログイン情報FreeeHrUser、認証プロトコルOAuth 2.0、保存時に認証フローを開始にチェック
利用者それぞれが行う認証の設定です。ユーザー名はテスト用の値です。
freeeのアプリ連携の開始画面。打刻の参照と、打刻の追加・変更・削除の権限を求めている
freee側の許可画面です。アプリが求める権限に打刻が含まれていることを確かめます。
Salesforceのホーム画面。右上にfreee打刻のコンポーネントと次へボタンがある
ホームの右上に出る最初の画面です。
ホーム画面右上のコンポーネントにオレンジ色で出勤と表示されている
「次へ」を押すと、いま打刻できる「出勤」が出ます。
freee人事労務の勤怠画面。タイムレコーダーの欄に08:25 出勤の打刻がある
freee人事労務の画面で、出勤が打刻されていることを確かめました。

確認した環境

  • 2026年9月時点のfreee公式のAPIスキーマ(freee-api-schema の人事労務API)、freeeのクイックスタート、Salesforce公式ヘルプ「Understand Legacy Named Credentials」で確認しています
  • 当時の仕組みは、2021年3月にSandboxで動かしています
  • 画像は2021年当時のものです。右上のユーザーアイコン、コールバックURL、Client ID、認証プロバイダID、コンシューマ鍵、作成者と更新者の名前を白で伏せています

まとめ

  • freee人事労務のAPIを画面フローから呼ぶと、Salesforceのホームで打刻できます
  • 使うAPIは、ログインユーザーの取得、打刻可能種別の取得、打刻の登録の3つです
  • 指定ログイン情報のID種別をユーザにすると、利用者それぞれのfreeeアカウントで打刻されます
  • 当時の形式の指定ログイン情報は非推奨です。いま作るなら新しい形式で作ります
  • 打刻できる種別を先に取り、その結果だけを画面に出すと、不整合な打刻を防げます

Salesforceの導入・運用についてご相談ください

導入前の検討から、お使いの環境の改修・運用、AIとの連携まで承ります。状況を伺ったうえで、進め方をご提案します。