[{"data":1,"prerenderedAt":531},["ShallowReactive",2],{"content-/mf-api-oauth-authentication-journey":3,"all-pages-for-dir":529,"og-image-/mf-api-oauth-authentication-journey":530},{"id":4,"title":5,"body":6,"category":509,"description":510,"extension":511,"meta":512,"navigation":513,"ogImage":514,"path":515,"project_name":516,"published":517,"publishedAt":518,"seo":519,"stem":520,"tags":521,"todo":527,"unpublished":517,"updatedAt":514,"__hash__":528},"pages/2026-03/2026-03-26/mf-api-oauth-authentication-journey.md","クラウド会計公式API・OAuth認証の試行錯誤ログ - APIキーからOAuthアプリ登録まで",{"type":7,"value":8,"toc":498},"minimark",[9,14,23,26,31,38,94,102,105,109,116,123,171,174,179,186,190,193,212,364,369,373,376,379,383,386,453,459,462,470,473,476,494],[10,11,13],"h1",{"id":12},"クラウド会計公式apioauth認証の試行錯誤ログ","クラウド会計公式API・OAuth認証の試行錯誤ログ",[15,16,17,18,22],"p",{},"APIキーを手に入れてターミナルで叩いた瞬間、",[19,20,21],"code",{},"services: [\"conac\"]","の文字列が返ってきて手が止まった。連結会計のスコープしかない。ここから半日かけて、MCPのトークン流用、自前OAuthアプリ登録と、認証手段を3回乗り換えることになった記録。",[24,25],"hr",{},[27,28,30],"h2",{"id":29},"第1段階-apiキーで挑む失敗","第1段階: APIキーで挑む（失敗）",[15,32,33,34,37],{},"会計サービスのAPIキー（",[19,35,36],{},"key_KF547uA6","）を取得し、キー交換でJWTトークンを取得した。トークン自体は問題なく返ってくる。",[39,40,45],"pre",{"className":41,"code":42,"language":43,"meta":44,"style":44},"language-json shiki shiki-themes vitesse-light vitesse-light","{\n  \"services\": [\"conac\"]\n}\n","json","",[19,46,47,56,88],{"__ignoreMap":44},[48,49,52],"span",{"class":50,"line":51},"line",1,[48,53,55],{"class":54},"shFtX","{\n",[48,57,59,63,67,70,73,76,79,83,85],{"class":50,"line":58},2,[48,60,62],{"class":61},"sqvqQ","  \"",[48,64,66],{"class":65},"sz8Xr","services",[48,68,69],{"class":61},"\"",[48,71,72],{"class":54},":",[48,74,75],{"class":54}," [",[48,77,69],{"class":78},"sMJiu",[48,80,82],{"class":81},"sdGka","conac",[48,84,69],{"class":78},[48,86,87],{"class":54},"]\n",[48,89,91],{"class":50,"line":90},3,[48,92,93],{"class":54},"}\n",[15,95,96,97,101],{},"連結会計（conac）のスコープしか付与されていない。会計APIには一切アクセスできない。クラウド会計サービスの確定申告機能には",[98,99,100],"strong",{},"公開APIが存在しない","ことがここで判明した。",[15,103,104],{},"APIキーでできることはここまで。別のルートを探す必要がある。",[27,106,108],{"id":107},"第2段階-公式mcpを発見突破口","第2段階: 公式MCPを発見（突破口）",[15,110,111,112,115],{},"調べていく中で、会計サービス公式のMCPサーバー（",[19,113,114],{},"mfc_ca","）を発見した。リモートMCPサーバーとして接続設定を行い、OAuth認証フローを通して接続に成功。",[15,117,118,119,122],{},"ここで一つ気づいた。",[98,120,121],{},"MCPのOAuthトークンを使って、直接REST APIを叩ける","。",[39,124,128],{"className":125,"code":126,"language":127,"meta":44,"style":44},"language-bash shiki shiki-themes vitesse-light vitesse-light","# MCPが内部で使っているAPIと同じエンドポイント\ncurl -H \"Authorization: Bearer ${ACCESS_TOKEN}\" \\\n  https://api-accounting.example.com/api/v3/journals\n","bash",[19,129,130,136,166],{"__ignoreMap":44},[48,131,132],{"class":50,"line":51},[48,133,135],{"class":134},"sxvE3","# MCPが内部で使っているAPIと同じエンドポイント\n",[48,137,138,142,146,149,152,155,158,161,163],{"class":50,"line":58},[48,139,141],{"class":140},"senZ8","curl",[48,143,145],{"class":144},"snbK4"," -H",[48,147,148],{"class":78}," \"",[48,150,151],{"class":81},"Authorization: Bearer ",[48,153,154],{"class":54},"${",[48,156,157],{"class":81},"ACCESS_TOKEN",[48,159,160],{"class":54},"}",[48,162,69],{"class":78},[48,164,165],{"class":144}," \\\n",[48,167,168],{"class":50,"line":90},[48,169,170],{"class":81},"  https://api-accounting.example.com/api/v3/journals\n",[15,172,173],{},"MCPは薄いラッパーに過ぎず、トークンは共通。仕訳の取得・登録・削除、全て直接APIで動いた。",[175,176,178],"h3",{"id":177},"mcpトークンの限界","MCPトークンの限界",[15,180,181,182,185],{},"アクセストークンの有効期限は1時間。MCPのトークンストアには",[19,183,184],{},"refresh_token","が含まれていない。1時間ごとに再認証が必要で、自動化には使えない。",[27,187,189],{"id":188},"第3段階-自前oauthアプリ登録最終解","第3段階: 自前OAuthアプリ登録（最終解）",[15,191,192],{},"会計サービスのアプリポータルで自前のOAuthアプリケーションを登録した。",[194,195,196,200,206],"ol",{},[197,198,199],"li",{},"アプリポータルでアプリ作成",[197,201,202,205],{},[19,203,204],{},"redirect_uri","を追加（ローカルのコールバックURL）",[197,207,208,211],{},[19,209,210],{},"oauth_flow.py","で認可コード取得→トークン交換",[39,213,217],{"className":214,"code":215,"language":216,"meta":44,"style":44},"language-python shiki shiki-themes vitesse-light vitesse-light","# oauth_flow.py のトークン交換部分\n# 認可コードをrefresh_tokenに交換\nresponse = requests.post(token_url, data={\n    \"grant_type\": \"authorization_code\",\n    \"code\": auth_code,\n    \"redirect_uri\": redirect_uri,\n    \"client_id\": client_id,\n    \"client_secret\": client_secret,\n})\n# refresh_token: 有効期限540日\n","python",[19,218,219,224,229,263,286,302,318,335,352,358],{"__ignoreMap":44},[48,220,221],{"class":50,"line":51},[48,222,223],{"class":134},"# oauth_flow.py のトークン交換部分\n",[48,225,226],{"class":50,"line":58},[48,227,228],{"class":134},"# 認可コードをrefresh_tokenに交換\n",[48,230,231,235,238,241,244,247,250,253,256,260],{"class":50,"line":90},[48,232,234],{"class":233},"sG7-3","response ",[48,236,237],{"class":54},"=",[48,239,240],{"class":233}," requests",[48,242,243],{"class":54},".",[48,245,246],{"class":233},"post",[48,248,249],{"class":54},"(",[48,251,252],{"class":233},"token_url",[48,254,255],{"class":54},",",[48,257,259],{"class":258},"s4oTP"," data",[48,261,262],{"class":54},"={\n",[48,264,266,269,272,274,276,278,281,283],{"class":50,"line":265},4,[48,267,268],{"class":78},"    \"",[48,270,271],{"class":81},"grant_type",[48,273,69],{"class":78},[48,275,72],{"class":54},[48,277,148],{"class":78},[48,279,280],{"class":81},"authorization_code",[48,282,69],{"class":78},[48,284,285],{"class":54},",\n",[48,287,289,291,293,295,297,300],{"class":50,"line":288},5,[48,290,268],{"class":78},[48,292,19],{"class":81},[48,294,69],{"class":78},[48,296,72],{"class":54},[48,298,299],{"class":233}," auth_code",[48,301,285],{"class":54},[48,303,305,307,309,311,313,316],{"class":50,"line":304},6,[48,306,268],{"class":78},[48,308,204],{"class":81},[48,310,69],{"class":78},[48,312,72],{"class":54},[48,314,315],{"class":233}," redirect_uri",[48,317,285],{"class":54},[48,319,321,323,326,328,330,333],{"class":50,"line":320},7,[48,322,268],{"class":78},[48,324,325],{"class":81},"client_id",[48,327,69],{"class":78},[48,329,72],{"class":54},[48,331,332],{"class":233}," client_id",[48,334,285],{"class":54},[48,336,338,340,343,345,347,350],{"class":50,"line":337},8,[48,339,268],{"class":78},[48,341,342],{"class":81},"client_secret",[48,344,69],{"class":78},[48,346,72],{"class":54},[48,348,349],{"class":233}," client_secret",[48,351,285],{"class":54},[48,353,355],{"class":50,"line":354},9,[48,356,357],{"class":54},"})\n",[48,359,361],{"class":50,"line":360},10,[48,362,363],{"class":134},"# refresh_token: 有効期限540日\n",[15,365,366,368],{},[19,367,184],{},"の有効期限は540日。これで自動化の土台が整った。自前OAuthアプリ経由で仕訳登録・削除にも成功。",[27,370,372],{"id":371},"ハマりポイント-windowsコマンドライン長制限","ハマりポイント: Windowsコマンドライン長制限",[15,374,375],{},"JSONの仕訳データ94件をGoogle スプレッドシートに書き込む処理で、Windowsのコマンドライン長制限（約8,191文字）に引っかかった。94件分のJSONを1コマンドで渡そうとして、コマンドが途中で切れる。",[15,377,378],{},"バッチ分割（10〜20件ずつ）で解決。Windows環境でJSON大量データを扱うときの定番の罠だった。",[27,380,382],{"id":381},"結論-chrome拡張とapiの使い分け","結論: Chrome拡張とAPIの使い分け",[15,384,385],{},"半日触って見えてきた速度感の比較。",[387,388,389,405],"table",{},[390,391,392],"thead",{},[393,394,395,399,402],"tr",{},[396,397,398],"th",{},"操作",[396,400,401],{},"Chrome拡張",[396,403,404],{},"API",[406,407,408,420,431,442],"tbody",{},[393,409,410,414,417],{},[411,412,413],"td",{},"エクスポート（仕訳一覧取得）",[411,415,416],{},"画面操作1回で完結、速い",[411,418,419],{},"ページネーション処理が必要",[393,421,422,425,428],{},[411,423,424],{},"インポート（仕訳登録）",[411,426,427],{},"1件ずつ画面操作、遅い",[411,429,430],{},"バッチで一括投入できる",[393,432,433,436,439],{},[411,434,435],{},"削除",[411,437,438],{},"1件ずつ、つらい",[411,440,441],{},"APIで一括削除",[393,443,444,447,450],{},[411,445,446],{},"更新",[411,448,449],{},"画面操作が必要",[411,451,452],{},"PUTで直接更新",[15,454,455,458],{},[98,456,457],{},"エクスポートはChrome拡張を維持、インポート・削除・更新はAPIに移行","が最適解という結論に落ち着いた。",[27,460,461],{"id":461},"認証手段の変遷まとめ",[39,463,468],{"className":464,"code":466,"language":467},[465],"language-text","APIキー(conacのみ) → MCP経由OAuth(1時間制限) → 自前OAuthアプリ(540日)\n","text",[19,469,466],{"__ignoreMap":44},[15,471,472],{},"最初からOAuthアプリを登録していれば30分で終わった話だが、MCPの内部構造を覗けたのは収穫だった。「MCPは薄いラッパー」という理解は、今後別のMCPサーバーを評価するときにも効いてくる。",[27,474,475],{"id":475},"学んだこと",[477,478,479,482,485,491],"ul",{},[197,480,481],{},"クラウド会計サービスの確定申告機能には公開APIがない。APIキーで取れるスコープは連結会計のみ",[197,483,484],{},"MCP経由のOAuthトークンとREST API直叩きのトークンは同一。MCPを介さず直接APIを叩ける",[197,486,487,488,490],{},"自前OAuthアプリの",[19,489,184],{},"は540日有効。自動化にはこのルートが必須",[197,492,493],{},"WindowsでJSON大量データをCLIに渡すときは、コマンドライン長制限を常に頭に入れておく",[495,496,497],"style",{},"html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .sqvqQ, html code.shiki .sqvqQ{--shiki-default:#99841877;--shiki-dark:#99841877}html pre.shiki code .sz8Xr, html code.shiki .sz8Xr{--shiki-default:#998418;--shiki-dark:#998418}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html pre.shiki code .snbK4, html code.shiki .snbK4{--shiki-default:#A65E2B;--shiki-dark:#A65E2B}html pre.shiki code .sG7-3, html code.shiki .sG7-3{--shiki-default:#393A34;--shiki-dark:#393A34}html pre.shiki code .s4oTP, html code.shiki .s4oTP{--shiki-default:#B07D48;--shiki-dark:#B07D48}",{"title":44,"searchDepth":58,"depth":58,"links":499},[500,501,504,505,506,507,508],{"id":29,"depth":58,"text":30},{"id":107,"depth":58,"text":108,"children":502},[503],{"id":177,"depth":90,"text":178},{"id":188,"depth":58,"text":189},{"id":371,"depth":58,"text":372},{"id":381,"depth":58,"text":382},{"id":461,"depth":58,"text":461},{"id":475,"depth":58,"text":475},"dev","クラウド会計サービスのAPIキー取得からOAuth認証まで段階的に突破した記録。MCPのOAuthトークンでREST APIを直接叩けることを発見し、最終的に自前OAuthアプリでrefresh_token（540日有効）を取得するまでの過程","md",{},true,null,"/mf-api-oauth-authentication-journey","misc-dev",false,"2026-03-26T00:00:00.000Z",{"title":5,"description":510},"2026-03/2026-03-26/mf-api-oauth-authentication-journey",[522,523,404,524,525,526],"クラウド会計","OAuth","MCP","認証","会計","memo","ffYheDzQCMqOtueF8byGxEv5bBk4Hyz3_66aMxJqcq4",[],"https://log.eurekapu.com/og/blog/mf-api-oauth-authentication-journey.png?v=2026-03-26T00%3A00%3A00.000Z&title=%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E4%BC%9A%E8%A8%88%E5%85%AC%E5%BC%8FAPI%E3%83%BBOAuth%E8%AA%8D%E8%A8%BC%E3%81%AE%E8%A9%A6%E8%A1%8C%E9%8C%AF%E8%AA%A4%E3%83%AD%E3%82%B0%20-%20API%E3%82%AD%E3%83%BC%E3%81%8B%E3%82%89OAuth%E3%82%A2%E3%83%97%E3%83%AA%E7%99%BB%E9%8C%B2%E3%81%BE%E3%81%A7&author=Kei%20Komatsu&sig=d95ae491e58c0a76",1782528821125]