kintone REST APIでデータを全件取得する方法|認証エラーの原因とCSVエクスポートでは失われる情報の救い方

この記事の結論

kintoneからHubSpotへデータを移行する際、CSVエクスポートだけに頼ると「選択肢の定義」と「アプリ間の関連構造」の2つの情報が失われます。 これをREST APIで確実に救うには、3種類ある認証方式の使い分け、CB_OA01エラーの原因切り分け、10,000件を超える場合のページング設計という3つの壁を越える必要があります。

ブログ目次

記事の内容を、そのまま実務に落とし込みたい方向け

HubSpotゴールドパートナーのStartLinkが、HubSpot導入・AI活用・CRM整備・業務効率化までをまとめて支援しています。記事で気になったテーマを、そのまま相談ベースで整理できます。


kintoneからHubSpotへデータを移行する際、CSVエクスポートだけに頼ると「選択肢の定義」と「アプリ間の関連構造」の2つの情報が失われます。 これをREST APIで確実に救うには、3種類ある認証方式の使い分け、CB_OA01エラーの原因切り分け、10,000件を超える場合のページング設計という3つの壁を越える必要があります。

「CSVでエクスポートしたら、ドロップダウンの選択肢が全部バラバラの文字列になってしまった」「関連レコード一覧に表示されていたはずのデータが、エクスポートすると消えている」——kintoneからHubSpotへの移行を検討する企業様から、こうした声を何度も聞いてきました。

私たちがこれまでの移行支援で確立してきた実務手順は、CSVエクスポートを起点にせず、kintone REST APIから直接データを取得することです。本記事では、認証方式の判別から、時間を溶かしやすい認証エラーの事前チェック、全件取得のページング設計、フィールド定義APIの活用まで、動くレベルの具体的な手順で解説します。移行プロジェクト全体の流れはkintone→HubSpot移行の完全ガイドでも整理していますので、あわせてご覧ください。


この記事でわかること

  • CSVエクスポートで失われる2つの情報とAPIで救えるもの — 選択肢定義とアプリ間の関連構造がなぜ抜け落ちるのかを解説します。
  • kintone REST APIの3つの認証方式の使い分け — 共通管理トークン・アプリトークン・パスワード認証、それぞれの用途と実務での選び方を紹介します。
  • CB_OA01エラーで時間を溶かさない事前チェック手順 — 無認証プローブの使い方とエラーコード早見表を掲載します。
  • 10,000件の壁を超える全件取得の実装 — ページング設計をPython(requests)とcurlの両方でコード例とともに解説します。
  • フィールド定義APIで選択肢・ルックアップ参照先まで取得する方法 — HubSpot側のプロパティ設計にそのまま流用できる情報の取り方を紹介します。

kintoneからHubSpotへのデータ移行を担当しており、CSVエクスポートだけでは選択肢の定義やアプリ間の関連構造が失われてしまうことに困っている方に、特に読んでいただきたい内容です。ぜひ最後までご確認ください。


なぜCSVエクスポートではなくAPIで取得すべきなのか

kintoneの画面から「エクスポート」ボタンを押せば、誰でも数秒でCSVファイルを取得できます。ただしこの手軽さと引き換えに、移行に必要な情報の一部が失われてしまう点が、結構ミソになってくる部分です。

CSVで失われる2つの情報

1つ目は選択肢の定義情報です。CSVエクスポートでは、ドロップダウンやチェックボックスの「選択された値の文字列」しか出力されません。そのフィールドに本来どんな選択肢が用意されていたか、選択肢の並び順や未選択の選択肢が何だったかは、CSVを見ただけでは分かりません。HubSpot側でenumプロパティ(選択リスト)を設計する際、この元の選択肢一覧が欠けていると、後から手作業で選択肢を洗い出す手間が発生します。

2つ目はアプリ間の関連構造です。kintoneの「関連レコード一覧」(ルックアップで参照している別アプリのレコード一覧を画面上に表示する機能)は、あくまで表示専用の機能であり、CSVエクスポートの対象データには含まれません。案件管理アプリの画面上で取引先の過去案件が一覧表示されていても、それはCSVには出力されない「見た目だけの情報」だということです。

APIで救えるもの

REST APIであれば、この2つの情報をどちらも取得できます。フィールド定義API(/k/v1/app/form/fields.json)を呼べば、選択肢の一覧を型情報ごと丸ごと取得できますし、関連構造については、表示用テーブルに頼らず実際のキー項目(数値ID・コード等)でレコード間の紐付けを再構築できます。この実キーによる紐付け設計は、複数アプリを横断してHubSpotオブジェクトへ再設計する際の土台になります(詳しくは後述の複数アプリ統合設計の記事で扱います)。

なお、CSVエクスポートを使った簡易的な移行手順そのものは否定しません。アプリ数が少なく、選択肢の再設計や関連構造の復元が不要なケースでは、CSVを使った移行手順の方が早いこともあります。判断基準を整理したのが以下の表です。

情報カバー範囲 CSVエクスポート REST API
レコードの値そのもの ○ 取得可能 ○ 取得可能
選択肢の定義(未選択分含む全選択肢) × 取得不可 ○ fields APIで取得可能
フィールドのデータ型(文字列/数値/日付等) △ 目視推測のみ ○ fields APIで正確に取得
ルックアップの参照先アプリ情報 × 取得不可 ○ fields APIで取得可能
「関連レコード一覧」の表示データ × 取得不可 △ 実キー項目からの再構築が必要
10,000件超の大量データ △ 一括ダウンロードのみ ○ ページング設計で確実に取得
自動化・定期実行への組み込み × 手動操作が前提 ○ スクリプト化・スケジュール実行可能

kintone REST APIの認証方式は3種類ある

kintone REST APIには3種類の認証方式があり、これを取り違えるとCB_OA01(保護されたリソースにアクセスできません)というエラーで時間を溶かすことになります。顧客から「APIキーをもらいました」と連携された際に、まずどの形式かを見た目で即座に判別することが実務の勘所です。

形式A 共通管理トークン(JWT)=レコード取得は不可

cy.s.api1.から始まる長い文字列のトークンで、Authorization: Bearerヘッダーで送信します。これはユーザー管理・組織管理・グループ管理といった管理系APIの専用トークンであり、アプリのレコードを取得することはできません。移行担当者からこの形式のトークンを渡された場合は、レコード取得には使えないことを先に伝え、別の形式を発行してもらう必要があります。

形式B アプリトークン=1トークン1アプリ・発行後「アプリを更新」押下必須

64文字の英数字で構成されるトークンで、X-Cybozu-API-Tokenヘッダーで送信します。1つのトークンにつき1つのアプリのレコード操作しかできません。発行しただけでは有効化されず、アプリの設定画面で「アプリを更新」ボタンを押すまでAPIが機能しないという落とし穴があり、これを見落として「トークンが間違っているのでは」と原因調査に時間を取られるケースが多く見られます。

形式C パスワード認証=閲覧権限1アカウントで全アプリ取得できる実務の本命

ログインIDとパスワードをbase64(login:password)の形式でエンコードし、X-Cybozu-Authorizationヘッダーで送信する方式です。閲覧権限を持つアカウントが1つあれば、個別にトークンを発行することなく、対象組織の全アプリのレコードを取得できます。データ移行のように複数アプリを横断してデータを抽出する場面では、この形式Cが実務の本命になります。

私たちが移行支援で確立した実務ハックとして、アプリトークン(形式B)の発行が各アプリの管理者承認待ちなどで滞留した場合は、閲覧権限を持つ1つのアカウントのID/パスワードで形式Cのパスワード認証に切り替えることで、個別アプリの発行を待たずに全アプリを一括取得できます。アプリ数が10を超えるような移行案件では、この切り替え判断が全体の作業時間を大きく左右します。

形式 見た目 ヘッダー 用途
A: 共通管理トークン(JWT) cy.s.api1.〜 Authorization: Bearer ユーザー/組織/グループ管理API専用。レコード取得は不可
B: アプリトークン 64文字の英数字 X-Cybozu-API-Token 1トークン=1アプリのレコード操作。発行後「アプリを更新」押下必須
C: パスワード認証 ログインID/パスワード X-Cybozu-Authorization: base64(login:pw) 閲覧権限アカウント1つで全アプリのレコード取得が可能。個別トークン発行不要

認証エラーCB_OA01で時間を溶かさない事前チェック

認証エラーCB_OA01で時間を溶かさない事前チェック

認証方式を取り違えたまま接続を試みると、CB_OA01のような分かりにくいエラーコードだけが返り、原因の切り分けに時間がかかります。本格的な実装に入る前に、以下の事前チェックを行うことで無駄な試行錯誤を避けられます。

無認証プローブ /k/v1/app.json?id=N の使い方

まず認証ヘッダーを一切付けずにGET /k/v1/app.json?id=N(Nは対象アプリのID)を叩いてみます。このレスポンスの内容によって、対象環境がどのようなセキュリティ設定になっているかを事前に把握できます。

WWW-Authenticate: Basic が返る=セキュアアクセスON

レスポンスヘッダーにWWW-Authenticate: Basicが含まれる場合、その環境では「セキュアアクセス」と呼ばれるBasic認証によるIPアクセス制限が有効になっています。この場合は、通常のAPI認証ヘッダーに加えて、Basic認証用の別の認証情報を追加で送信する必要があります。事前にこれが分かっていれば、後から「なぜ認証情報が正しいのにアクセスできないのか」と悩む時間を省けます。

パスワード認証が通らない3条件

パスワード認証(形式C)は便利な反面、以下の3つの条件に該当する場合は使用できません。

  • SSO(シングルサインオン)のみが設定されており、cybozu.comの直接パスワードが未設定
  • 2段階認証が有効になっている
  • セキュアアクセス(Basic認証によるアクセス制限)が有効になっている

これらの条件に該当する場合は、パスワード認証ではなく形式B(アプリトークン)を使う必要があります。事前に管理者へ「SSO専用アカウントか」「2段階認証は有効か」を確認しておくと、実装段階での手戻りを防げます。

アプリトークン発行が滞った時は形式Cへ切替

前述の通り、アプリトークンの発行・承認フローが止まってしまった場合は、閲覧権限を持つアカウントでのパスワード認証に切り替えるのが最も現実的な打開策です。ただし上記3条件に該当する環境では使えないため、事前チェックの結果と合わせて判断する必要があります。

エラーコード 意味 主な原因
CB_OA01 保護されたリソースにアクセスできません 認証方式の取り違え・スコープ不足
CB_AU01 ログインしていません 認証ヘッダー未設定・認証情報の誤り
GAIA_IA02 アプリIDが不正、またはアプリの更新が未実施 アプリトークン発行後に「アプリを更新」を押していない
520系エラー サーバーエラー サブドメインの指定誤り・ヘッダー形式の誤り

全レコードを確実に取得する—ページングと10,000件の壁

認証を突破できたら、次は全レコードを漏れなく取得するページング設計です。kintoneのレコード取得APIには1リクエストあたりの上限があり、この上限を正しく処理しないとデータの欠落が起きます。

records.json基本形 query="order by $id asc limit 500 offset N"

レコード取得には/k/v1/records.jsonエンドポイントを使い、queryパラメータでorder by $id asc limit 500 offset Nのように指定します。1リクエストで取得できる件数は最大500件です。$id(レコード番号)の昇順で並べ、offsetを500ずつずらしながらループすることで、全件を漏れなく取得していきます。

offset上限10,000を超える場合は$id範囲分割に切替

ここで注意が必要なのが、offsetにはハード上限として10,000という制限があることです。offsetが10,000を超えるクエリを送ると正しく動作しません。対象アプリのレコード件数が10,000件を超える場合は、offsetによるページングをそのまま続けるのではなく、直前に取得できた最大の$idを使ってquery="$id > 直前の最大id order by $id asc limit 500"のようにカーソル的に範囲を絞り込む方式に切り替える必要があります。この$id範囲分割方式であれば、件数がどれだけ多くても取りこぼしなく全件取得できます。

Pythonコード例(requests、ページング全件取得の実装)

以下は、10,000件の壁を超えても動作するよう$id範囲分割方式で実装した全件取得スクリプトの例です。

import requests
import json

SUBDOMAIN = "your-subdomain"
APP_ID = 10
BASE_URL = f"https://{SUBDOMAIN}.cybozu.com/k/v1/records.json"

# 形式C: パスワード認証を使う場合
import base64
login = base64.b64encode(b"login-id:password").decode("utf-8")
headers = {
    "X-Cybozu-Authorization": login,
}

# 形式B: アプリトークンを使う場合はこちらに切り替え
# headers = {"X-Cybozu-API-Token": "発行した64文字トークン"}

def fetch_all_records(app_id: int) -> list[dict]:
    all_records: list[dict] = []
    last_id = 0
    limit = 500

    while True:
        query = f"$id > {last_id} order by $id asc limit {limit}"
        params = {"app": app_id, "query": query}
        res = requests.get(BASE_URL, headers=headers, params=params, timeout=30)
        res.raise_for_status()
        records = res.json()["records"]

        if not records:
            break

        all_records.extend(records)
        last_id = int(records[-1]["$id"]["value"])

        if len(records) < limit:
            break

    return all_records

if __name__ == "__main__":
    records = fetch_all_records(APP_ID)
    print(f"取得件数: {len(records)}")
    with open("kintone_records.json", "w", encoding="utf-8") as f:
        json.dump(records, f, ensure_ascii=False, indent=2)

このスクリプトは$idの昇順でカーソルのように進んでいくため、途中でoffsetの10,000件制限に引っかかることがなく、レコード件数がどれだけ増えても同じロジックで全件取得を継続できます。

curlコード例

動作確認や簡易的な検証には、curlで1ページ分を取得するのが手早い方法です。

# 形式C: パスワード認証
CREDENTIAL=$(echo -n "login-id:password" | base64)

curl -X GET "https://your-subdomain.cybozu.com/k/v1/records.json" \
  --data-urlencode "app=10" \
  --data-urlencode "query=order by \$id asc limit 500 offset 0" \
  -G \
  -H "X-Cybozu-Authorization: ${CREDENTIAL}"

# 形式B: アプリトークン
curl -X GET "https://your-subdomain.cybozu.com/k/v1/records.json" \
  --data-urlencode "app=10" \
  --data-urlencode "query=\$id > 500 order by \$id asc limit 500" \
  -G \
  -H "X-Cybozu-API-Token: 発行した64文字トークン"

offsetを使う1ページ目の確認にはシンプルなクエリで十分ですが、本番の全件取得では前述のPythonスクリプトのように$id範囲分割へ切り替えることをおすすめします。


フィールド定義APIで選択肢・ルックアップ参照先まで取得する

レコードの値そのものだけでなく、そのアプリがどんなフィールド構成になっているかを取得できるのがフィールド定義APIです。HubSpot側のプロパティ設計をする際に、この情報が土台になります。

/k/v1/app/form/fields.json?app=N でcode/label/type/選択肢(options)/ルックアップ参照先を取得

GET /k/v1/app/form/fields.json?app=Nを呼ぶと、対象アプリの全フィールドについて、フィールドコード(code)、表示ラベル(label)、データ型(type)、ドロップダウン等の選択肢一覧(options)、ルックアップフィールドが参照している先のアプリ情報までを一度に取得できます。ブラウザの開発者コンソールからkintone.api(...)を実行してTSV形式で出力することも可能ですが、移行作業のように再現性が必要な場面ではAPI経由でJSONとして保存しておく方が確実です。

選択肢はそのままHubSpot enumプロパティ設計に流用できる

fields APIで取得した選択肢一覧(options)は、そのままHubSpot側のenumプロパティ(選択リスト)の選択肢設計に流用できます。CSVエクスポートでは「選択された値」しか見えませんが、fields APIなら未選択の選択肢も含めて全選択肢を正確に把握できるため、移行後のプロパティ設計で選択肢の抜け漏れが起きにくくなります。

レイアウトのGROUP要素は値を持たないため除外

fields APIのレスポンスには、画面レイアウト上の「グループ」(GROUP要素)も含まれますが、これは表示上の区切りであり、レコード自体の値は持ちません。フィールド一覧を処理する際は、GROUP要素をデータフィールドとして扱わないよう除外しておく必要があります。

「関連レコード一覧」(REFERENCE_TABLE)は表示専用でレコード値に出ない=実キー項目で紐付けを再構築する

fields APIのレスポンスに含まれるREFERENCE_TABLE(関連レコード一覧)は、あくまで画面上に別アプリのレコードを表示するための設定情報であり、レコードの実データそのものではありません。案件管理アプリの画面で取引先の過去案件が一覧表示されていても、それはこのREFERENCE_TABLEによる表示であり、レコード値としてエクスポートされることはありません。この関連構造をHubSpot側で再現するには、REFERENCE_TABLEの表示設定を見るのではなく、両アプリに共通して存在する実キー項目(数値の取引先IDなど)を使って、レコード同士の紐付けを自分たちで再構築する必要があります。


取得したデータをHubSpotへどう受け渡すか

ここまでの手順で、選択肢定義・データ型・関連構造まで含めた正確なデータをkintoneから取得できる状態になりました。次のステップは、このデータを複数アプリ横断でHubSpotのオブジェクト(コンタクト・会社・取引等)へどう再設計してマッピングするかという判断です。

複数アプリ→オブジェクト再設計は次のステップ

1つのkintoneアプリを1つのHubSpotオブジェクトへ単純に移し替えるだけであれば比較的シンプルですが、実際の移行案件では、案件管理アプリと取引先管理アプリのように、複数のアプリが互いに関連付けられているケースがほとんどです。この場合、どのアプリをどのHubSpotオブジェクトに対応させるか、関連付けのキーとして使える実キーがどれくらいの精度でデータに入っているかを事前に実測してから設計する必要があります。この複数アプリの統合設計については、複数アプリをHubSpotオブジェクトに再設計する記事で詳しく解説しています。

自社実装が難しい場合の選択肢

ここまでの認証方式の判別、ページング設計、フィールド定義の解析、そして複数アプリのオブジェクト再設計までを自社のエンジニアリソースだけで完結させるのは、特にアプリ数が多い移行案件では相応の工数がかかります。

HubSpot ゴールドパートナーとしての移行支援

StartLinkはHubSpotゴールドパートナーとして、kintoneからHubSpotへのAPI移行を数多く支援してきました。認証方式の判別・全件取得の実装・複数アプリのオブジェクト再設計までを一気通貫で伴走します。自社での実装リソースが不足している場合は、移行を「コスト」ではなく、データ資産をCRMの動く仕組みに載せ替える「投資」として検討いただければと思います。詳しくはお問い合わせページからご相談ください。

なお、kintoneとHubSpotを全面移行せず併用する設計を検討している場合は、kintone×HubSpot連携設計の記事を、そもそも移行するかどうかの判断に迷っている場合は、HubSpot vs kintone比較記事をあわせてご覧ください。


まとめ

kintone REST APIでのデータ全件取得は、以下の3つの壁を順に越えることで確実に実行できます。

  • CSVエクスポートでは選択肢定義とアプリ間の関連構造が失われる — フィールド定義APIとレコードAPIを組み合わせることでこの2つを救えます
  • 認証方式は3種類あり、レコード取得に使えるのは形式B(アプリトークン)と形式C(パスワード認証)のみ — アプリトークンの発行が滞ったら、閲覧権限アカウントによるパスワード認証への切り替えが実務の打開策になります
  • CB_OA01等のエラーは、無認証プローブでの事前チェックとエラーコード早見表で切り分けられる — 本格実装の前にセキュアアクセスの有無を確認しておくと手戻りを防げます
  • 全件取得はoffsetの10,000件上限を超えたら$id範囲分割方式に切り替える — この方式であればレコード件数がどれだけ増えても同じロジックで対応できます
  • REFERENCE_TABLE(関連レコード一覧)は表示専用であり、実キー項目での紐付け再構築が必須 — ここを見落とすとHubSpot側で関連付けが正しく張れません

まずは対象アプリの認証方式を判別し、無認証プローブでセキュアアクセスの有無を確認するところから始めてみてください。そのうえでフィールド定義APIを先に呼んでおけば、レコード本体の取得作業も選択肢の再設計もスムーズに進められます。データが正確に取得できて初めて、その先の複数アプリのオブジェクト再設計やHubSpot側のパイプライン設計といった、移行の本質的な価値に手が届くようになります。


よくある質問(FAQ)

Q1. CSVとAPIどちらを使うべきですか?

アプリ数が少なく、選択肢の再設計や関連構造の復元が不要な小規模な移行であれば、CSVエクスポートによる簡易的な手順でも対応できます。一方、ドロップダウンの選択肢定義を正確に引き継ぎたい場合や、複数アプリをまたいだ関連構造をHubSpot側で再現したい場合は、REST APIでの取得が必須になります。移行するアプリの規模と、選択肢・関連構造をどこまで正確に引き継ぐ必要があるかで判断してください。

Q2. アプリトークンとパスワード認証どちらを先に試すべきですか?

対象アプリが1〜2個程度であればアプリトークン(形式B)を発行して個別に扱うのがシンプルです。ただし対象アプリが多い場合や、アプリトークンの発行・承認が管理者側で滞留している場合は、閲覧権限を持つアカウントによるパスワード認証(形式C)に切り替えると、個別発行を待たずに全アプリへアクセスできます。ただしSSO専用アカウント・2段階認証有効・セキュアアクセス有効のいずれかに該当する環境では、パスワード認証は使えません。

Q3. 1万件を超えるデータはどう取得すればよいですか?

kintoneのレコード取得APIはoffsetに10,000件のハード上限があります。この上限を超える場合は、offsetによるページングを続けるのではなく、直前に取得した最大の$idを使って$id > 直前のidという条件でクエリを組み立て直す、$id範囲分割方式に切り替えてください。この方式であれば件数の上限なく全件を取得できます。

Q4. 「関連レコード一覧」が取れないのはなぜですか?

kintoneの「関連レコード一覧」(REFERENCE_TABLE)は、画面上に別アプリのレコードを表示するための表示専用の設定であり、レコード自体が保持しているデータではないためです。CSVエクスポートにもレコード取得APIのレスポンスにも、この表示内容そのものは含まれません。同様の紐付けをHubSpot側で再現するには、両アプリに共通する実キー項目(数値IDなど)を使って関連付けを組み直す必要があります。


株式会社StartLinkは、事業推進に関わる「販売促進」「DXによる業務効率化(ERP/CRM/SFA/MAの導入)」などのご相談を受け付けております。 サービスのプランについてのご相談/お見積もり依頼や、ノウハウのお問い合わせについては、無料のお問い合わせページより、お気軽にご連絡くださいませ。

関連キーワード:

サービス資料を無料DL

著者情報

7-1

今枝 拓海 / Takumi Imaeda

株式会社StartLink 代表取締役。累計150社以上のHubSpotプロジェクト支援実績を持ち、Claude CodeやHubSpotを軸にしたAI活用支援・経営基盤AXのコンサルティング事業を展開。
HubSpotのトップパートナー企業や大手人材グループにて、エンタープライズCRM戦略策定・AI戦略ディレクションを経験した後、StartLinkを創業。現在はCRM×AIエージェントによる経営管理支援を専門とする。