なぜATSエンジニアはAPIを理解する必要があるか
ATS(採用管理システム)の価値は単体のプロダクトとしてではなく、 HRエコシステムのハブとして機能することで最大化されます。 ATSとHRIS(人事情報システム)・ジョブボード・評価ツール・バックグラウンドチェックサービスの連携は、 すべてAPIを通じて行われます。
エンジニアがATSのAPIを扱う場面は主に3つです。
- ① HR Techプロダクト開発(ATSとの連携機能): 自社プロダクトをATSと統合する際、ATSのAPIエンドポイント・認証方式・データスキーマの理解が不可欠です。 例えば、評価プラットフォームが「候補者のステージ変更」をトリガーにスコアをATSに書き戻す場合などが典型です。
- ② 社内採用システムのカスタム連携: 大企業では既製のATS連携では要件を満たせず、独自の統合レイヤーを構築するケースがあります。 求人情報のマルチポストや、複数ATSからのデータ統合ダッシュボードなどがその例です。
- ③ 採用データの分析パイプライン構築: 時間帯別応募数・チャネル別ソース・ファネル通過率などの採用データを データウェアハウスに取り込むETLパイプラインの構築では、ATSのAPIとWebhookを扱います。
本章では市場シェアが高い3つのAPI——Greenhouse Harvest API v3、Lever API、LinkedIn Job Posting API——の 実装詳細と、Google for Jobs対応のためのJSON-LD実装を解説します。
Greenhouse Harvest API v3
v1/v2 vs v3 の主要変更点
| 項目 | v1 / v2 | v3 | 備考 |
|---|---|---|---|
| 認証方式 | Basic Auth(APIキー) | OAuth 2.0 Bearer JWT | トークン取得先: https://auth.greenhouse.io/token |
| ページネーション | オフセットベース(page, per_page) | カーソルベース(after, limit) | 件数多い場合のパフォーマンス大幅改善 |
| レスポンス形式 | JSON(配列直接返却) | JSON(data + meta ラッパー) | ページネーション情報が meta に含まれる |
| Webhook署名 | なし or SHA256(オプション) | HMAC-SHA256(必須) | X-Greenhouse-Signatureヘッダー |
| 廃止予定 | 2026年8月31日 | 継続サポート | v3移行推奨 |
主要エンドポイント解説
Greenhouse Harvest API v3 の中心となるエンドポイントを3つ紹介します。 ベースURLは https://harvest.greenhouse.io です。
GET /v1/applications は採用パイプライン全体の状況把握に使います。 フィルタパラメータ job_id、status、created_after、last_activity_afterを組み合わせて差分取得が可能です。
// GET /v1/applications のレスポンス例
{
"id": 123,
"status": "active",
"applied_at": "2026-06-16T09:00:00Z",
"current_stage": {
"id": 456,
"name": "一次面接",
"interviews": []
},
"source": { "id": 1, "name": "LinkedIn" },
"credited_to": {
"id": 789,
"email": "recruiter@example.com",
"name": "採用 太郎"
},
"custom_fields": {},
"attachments": []
}その他の主要エンドポイントは以下の通りです。
| エンドポイント | 用途 | 主要フィルタ |
|---|---|---|
| GET /v1/applications | 応募一覧・ステータス取得 | job_id, status, created_after |
| GET /v1/candidates | 候補者プロフィール取得 | email, created_after, updated_after |
| GET /v1/jobs | 求人票一覧・ステータス | status, department_id |
| PATCH /v1/applications/{id}/advance | ステージ進行 | from_stage_id(必須) |
Webhookイベント一覧
Greenhouse のWebhookは全30種類以上が定義されており、すべてHMAC-SHA256署名付きで配信されます。 カテゴリ別の主要イベントを以下に整理します。
| カテゴリ | イベント名 | 発火タイミング |
|---|---|---|
| アプリケーション系 | new_candidate_application | 新規応募作成時 |
| offer_created | オファー作成時 | |
| offer_approved | オファー承認時 | |
| 候補者系 | candidate_stage_change | ステージ進行時(最頻出) |
| hire_candidate | オファー承諾時 | |
| reject_candidate | 不採用時 | |
| candidate_anonymized | 匿名化処理時(GDPR対応) |
candidate_stage_change のWebhookペイロード例です。action フィールドでイベント種別を判別し、payload.application.current_stageで遷移後のステージを取得します。
// candidate_stage_change Webhookペイロード
{
"action": "candidate_stage_change",
"payload": {
"application": {
"id": 123,
"status": "active",
"current_stage": { "id": 456, "name": "二次面接" },
"source": { "name": "LinkedIn" }
}
}
}Lever API
Lever の最大の特徴はOpportunity中心のデータモデルです。 他のATSが「候補者(Candidate)」を中心に設計されているのに対し、 Lever は「応募機会(Opportunity)」を第一級エンティティとして扱います。
graph LR A[Contact\n(人・永続ID)] -->|1対多| B[Opportunity A\nバックエンドエンジニア] A -->|1対多| C[Opportunity B\nSREポジション] A -->|1対多| D[Opportunity C\n2年後の再応募] B --> E[ステージ・タグ・メモ] C --> F[ステージ・タグ・メモ] D --> G[ステージ・タグ・メモ] style A fill:#10b981,stroke:#059669,color:#fff style B fill:#1e40af,stroke:#1d4ed8,color:#fff style C fill:#1e40af,stroke:#1d4ed8,color:#fff style D fill:#1e40af,stroke:#1d4ed8,color:#fff
ベースURLは https://api.lever.co/v1。 認証はBasic Auth(APIキー)またはOAuth 2.0が利用可能です。
主要エンドポイント
| エンドポイント | 用途 |
|---|---|
| GET /opportunities | 候補者パイプライン一覧(中心エンドポイント) |
| GET /opportunities/deleted | 削除済みOpportunity(差分同期に必要) |
| GET /postings | 求人票一覧・ステータス |
| GET /contacts/{id} | 個人コンタクト情報(全Opportunity横断) |
| POST /opportunities/{id}/stage | ステージ更新 |
Lever APIのレスポンスはすべて以下の共通構造を持ちます。 ページネーションは next トークンによるカーソル方式です。
// Lever APIレスポンス共通構造
{
"data": [...],
"next": "0.1414895548650.a6070140-33db-407c-91f5-2760e15c8e94",
"hasNext": true
}LinkedIn Job Posting API
LinkedIn Job Posting API(Foundation Schema)は、採用担当者や HR Tech企業が 求人票をLinkedInプラットフォームに直接掲載するための標準APIです。 バージョニングヘッダー LinkedIn-Version: li-lts-2025-01 以降を使用します。
Foundation Schema 必須フィールド
| フィールド名 | 型 | 説明・制約 |
|---|---|---|
| jobPostingOperationType | enum | CREATE / UPDATE / CLOSE |
| company | URN | urn:li:organization:{id} 形式 |
| companyApplyUrl | URL | 応募フォームURL(Easy Apply無効時必須) |
| externalJobPostingId | string | 外部ユニークID(最大75文字) |
| title | string | 求人タイトル(200文字以内) |
| description | string | 職務内容(100〜25,000文字) |
| listedAt | number | 掲載日時(epochミリ秒) |
| location | string | 地名(例: "Tokyo, Japan") |
| workplaceTypes | array | On-site / Hybrid / Remote |
| posterEmail | string | 掲載者メール(不正掲載防止) |
給与情報(compensation)はオプションですが、記載することでLinkedInの求人検索での表示優先度が上がります。 給与フィールドの構造例です。
// LinkedIn Job Posting API: compensation フィールド例
"compensation": {
"compensations": [{
"period": "YEARLY",
"type": "BASE_SALARY",
"value": {
"range": {
"start": {"amount": "6000000", "currencyCode": "JPY"},
"end": {"amount": "9000000", "currencyCode": "JPY"}
}
}
}]
}Google for Jobs JSON-LD実装
Google for Jobs は求人票ページに構造化データ(JSON-LD)を埋め込むことで、 Googleの求人検索結果に表示される仕組みです。 求人SEOにおいてオーガニックトラフィックを大幅に増やせる重要な施策であり、 ジョブボードを持つ企業は必ず対応すべき実装です。
最低限必要な5つのフィールド
Google for Jobsに求人を表示させるための最小限のJSON-LD実装例です。script タグを求人詳細ページの head または body 内に配置します。
<script type="application/ld+json">
{
"@context": "https://schema.org/",
"@type": "JobPosting",
"title": "Backendエンジニア",
"description": "<p>職務内容...</p>",
"datePosted": "2026-06-16",
"validThrough": "2026-08-31T00:00",
"employmentType": "FULL_TIME",
"hiringOrganization": {
"@type": "Organization",
"name": "株式会社Example",
"sameAs": "https://example.co.jp"
},
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"addressLocality": "渋谷区",
"addressCountry": "JP"
}
}
}
</script>| フィールド | 必須/推奨 | 備考 |
|---|---|---|
| title | 必須 | 求人タイトル |
| description | 必須 | HTMLタグ使用可 |
| datePosted | 必須 | ISO 8601形式(YYYY-MM-DD) |
| hiringOrganization | 必須 | name と sameAs(企業URL) |
| jobLocation | 必須 | PostalAddress で詳細指定可 |
| validThrough | 推奨 | 締切日。未指定だと期限なし掲載 |
| baseSalary | 推奨 | 給与情報(表示優先度向上) |
| jobLocationType | リモート必須 | "TELECOMMUTE"(リモート求人のみ) |
Webhookの実装パターン — ポーリング vs イベント駆動
| 観点 | ポーリング | Webhook(イベント駆動) |
|---|---|---|
| 遅延 | 最大ポーリング間隔(1〜5分) | ほぼリアルタイム(秒〜数十秒) |
| サーバー負荷 | 一定の定期リクエスト負荷 | イベント発生時のみ |
| 実装難易度 | シンプル(クーロンジョブ等) | エンドポイント公開・署名検証が必要 |
| レート制限リスク | 高(頻繁なポーリングで抵触) | 低(受信側なのでレート制限なし) |
| 適用場面 | 外部Webhookが利用できない場合 | 本番環境の推奨パターン |
HMAC-SHA256署名の検証(Node.js実装例)
Greenhouse・Leverともに、Webhookの送信元が正規のATSサーバーであることを確認するため、 HMAC-SHA256署名をリクエストヘッダーに付与します。 受信側では以下のように検証します。
const crypto = require('crypto');
// Greenhouse: X-Greenhouse-Signature ヘッダーの検証
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
// timingSafeEqual でタイミング攻撃を防ぐ
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// Express ミドルウェアでの使用例
app.post('/webhooks/greenhouse', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-greenhouse-signature'];
const secret = process.env.GREENHOUSE_WEBHOOK_SECRET;
if (!verifyWebhookSignature(req.body, signature, secret)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = JSON.parse(req.body);
// べき等処理: event_id で重複排除
processEvent(event);
res.status(200).json({ received: true });
});べき等性の設計 — Deduplication
ネットワーク障害やATSサーバーのリトライにより、同一Webhookが複数回配信されることがあります。 これを適切に処理するためにべき等性(Idempotency)の設計が必要です。
event_id による重複排除パターン
- ① Webhookペイロードの
idまたはevent_idを抽出 - ② Redisや処理済みテーブルで「既に処理したか」を確認
- ③ 未処理の場合のみビジネスロジックを実行
- ④ 処理済みとしてIDをマーク(TTL: 24〜72時間が目安)
- ⑤ 重複の場合は 200 OK を返す(再送停止のため)
エンジニア視点のコラム: ATS APIは「採用のGit」だ
ATS APIのWebhookイベントをよく見ると、Gitのコマンドと驚くほど対応していることに気づきます。
| ATSイベント | Gitの概念 | 意味 |
|---|---|---|
| new_candidate_application | git init / git clone | 採用パイプラインの開始 |
| candidate_stage_change | git commit | ステージ進行(状態変化の記録) |
| pipeline(採用フロー) | git branch | 候補者ごとの並行進行 |
| hire_candidate | git merge | 採用決定(チームへの合流) |
| reject_candidate | git branch -d | 不採用(ブランチのクローズ) |
この対応から見えてくるのは、採用データが本質的にイベントソーシング(Event Sourcing)的な性質を持つということです。 候補者のステージ変更はすべてAppend-onlyで記録され、現在のステータスはイベントの積み上げによって導出されます。 Gitのコミット履歴がコードの変遷を追えるように、ATSのWebhookイベントは候補者の採用プロセスを完全に再現できます。
この視点をアーキテクチャに活かした実装パターンが、Webhookイベントをイベントバスに流してデータレイクに格納する構成です。
graph LR A[Greenhouse / Lever\nWebhook配信] --> B[APIゲートウェイ\n署名検証・べき等チェック] B --> C[イベントバス\nAmazon SQS / Pub/Sub] C --> D[ストリーム処理\nCloud Functions] D --> E[データレイク\nBigQuery / Redshift] E --> F[採用ダッシュボード\n通過率・時間・チャネル分析] D --> G[HRIS連携\n入社処理自動化] style A fill:#f97316,stroke:#ea580c,color:#fff style C fill:#3b82f6,stroke:#1d4ed8,color:#fff style E fill:#10b981,stroke:#059669,color:#fff style F fill:#10b981,stroke:#059669,color:#fff
このアーキテクチャにより、採用ファネルの各ステージの通過率・所要時間・チャネル別効果を リアルタイムに可視化できます。さらに hire_candidate イベントをトリガーに HRIS(Workday等)への入社手続き自動起票まで連携すれば、 採用決定から入社手続き完了までの工数を大幅に削減できます。
理解度チェック
Greenhouse Harvest API v3 で v1/v2 から変更された認証方式はどれですか?
キーボード: 1〜4 で選択、Enter で回答