連携APIの説明

受入れ企業から鍵を受け取った監理団体・送り出し機関・教材会社のシステムが、学習の進み具合と確認済みの用語集を読み書きできます。どの学習者の情報も、本人が共有に同意した分だけです。

OpenAPI の定義(/api/partner/v1/openapi.json)

鍵と呼び出しの決まり

  • 受入れ企業の管理者が発行した鍵を Authorization: Bearer で送ります。
  • 鍵ごとに見てよい範囲(スコープ)と対象の言語が決まっています。
  • 1本の鍵で1分に60回まで。超えると 429 と Retry-After を返します。
  • 作成・更新(POST・PUT)には Idempotency-Key ヘッダーが必要です。同じキーなら同じ応答を返します(24時間)。
  • 一覧は limit(最大100、既定50)と cursor でページを送ります。
  • 日時は +09:00 付きの ISO 8601 です。

エンドポイント

エンドポイント
メソッドパススコープ概要
GET/api/partner/v1/ping(鍵があれば可)鍵の確認
GET/api/partner/v1/openapi.json(なし)OpenAPI 3.1 の定義
GET/api/partner/v1/learnerslearners:read本人が共有に同意している学習者の一覧と進み具合。名前は pii:read かつ組織の設定がオンのときだけ
GET/api/partner/v1/learners/{learner_id}/progresslearners:read1人の進み具合・最近の小テスト10回・間違いの多い言葉(最大5語)
GET/api/partner/v1/glossary/termsglossary:read会社の現場用語集(確認済みの訳だけ)
POST/api/partner/v1/glossary/termsglossary:write用語の取り込み(1回100語まで。必ず下書きとして入る)
GET/api/partner/v1/glossary/rulesglossary:read訳し方の決まり(訳さない言葉・訳を固定する言葉)
PUT/api/partner/v1/glossary/rulesglossary:write訳し方の決まりの取り込み(1回200件まで)
GET/api/partner/v1/templatestemplates:readSBGGが承認した業種別テンプレートの一覧
GET/api/partner/v1/templates/{template_id}templates:readテンプレートの中身(カードと確認済みの訳)

イベント(Webhook)

イベント(Webhook)
learner.test_passed学習者が小テストで80点以上を取ったとき(本人が共有に同意している場合だけ)。名前は入れません。
card.native_approved確認者がカードのインドネシア語またはベトナム語の訳を承認したとき(修正して承認を含む)。
glossary.updated用語の取り込み・テンプレートの追加・カードのアーカイブ・訳し方の決まりの変更のとき(1回の操作で1件)。

イベントの届く順番は保証しません。created_at で判断してください。

{"id":"evt_tp_c1d2e3f4-0000-4000-8000-000000000003","type":"learner.test_passed","created_at":"2026-09-20T20:05:00+09:00","org_id":"0f0e...","data":{"learner_id":"7b0e1c52-...","attempt_id":"c1d2e3f4-...","lang":"id","job_type":"manufacturing","score":90,"correct":9,"total":10,"first_pass":true,"finished_at":"2026-09-20T20:05:00+09:00","days_to_first_pass":18}}

署名の確かめ方

  • ヘッダー X-SBGG-Signature は t=<UNIX秒>,v1=<署名> の形です。
  • 署名は、登録のときに表示した署名用の秘密で、「t + . + 本文」を HMAC-SHA256 で計算した16進数です。
  • t が今の時刻から300秒以上ずれていたら捨ててください。
  • 失敗したときは 1分→5分→30分→2時間→12時間 の間隔で最大6回送ります。
// Node.js
import crypto from 'node:crypto';
function verify(secret, rawBody, header) {
  const [, t, v1] = header.match(/^t=(\d+),v1=([0-9a-f]{64})$/) ?? [];
  if (!t || Math.abs(Date.now() / 1000 - Number(t)) >= 300) return false;
  const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}

エラーの形

{"error":{"code":"invalid_request","message":"The request is invalid.","details":[{"path":"terms[0].term_ja","issue":"too_long"}]}}
  • 400 invalid_request
  • 400 idempotency_key_required
  • 401 unauthorized
  • 403 forbidden
  • 404 not_found
  • 409 idempotency_conflict
  • 422 card_limit
  • 429 rate_limited

個人情報

学習者の名前は、鍵に pii:read があり、組織の設定がオンで、本人が共有に同意しているときだけ返します。

在留カード番号・パスポート番号・在留資格の項目はありません。未知の項目を送ると 400 になります。

curl の例

curl -H "Authorization: Bearer gb_live_xxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  https://genba-kotoba.com/api/partner/v1/ping
curl -H "Authorization: Bearer $GENBA_KEY" \
  "https://genba-kotoba.com/api/partner/v1/learners?lang=id&limit=50"
curl -X POST -H "Authorization: Bearer $GENBA_KEY" \
  -H "Idempotency-Key: 2026-10-01-import-001" \
  -H "Content-Type: application/json" \
  -d '{"terms":[{"term_ja":"玉掛け","meaning_ja":"クレーンで吊る荷物にワイヤーを掛けること","category":"safety"}]}' \
  https://genba-kotoba.com/api/partner/v1/glossary/terms