質問するログイン新規登録

Q&A

2回答

372閲覧

KING OF TIMEのAPIの仕様について

3chomenanigashi

総合スコア15

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2026/06/04 08:19

0

0

実現したいこと

KING OF TIMEのAPIを叩いて、管理画面からダウンロードできるxlsと同等の情報を取得したい

発生している問題・分からないこと

KING OF TIMEの管理画面の「打刻エラー勤務」からExcel出力→ダウンロードで、勤務日、出勤時刻、退勤時刻、休始時刻、休終時刻、エラー理由といったデータが記載されたxlsファイルが得られますが、これと同じ情報をAPIで取得したいです。
https://developer.kingoftime.jp/
該当の従業員をリストアップするところまではできましたが、エラー理由を得たくて色々なエンドポイントを試してみましたが400が返ってくることが多く難航しています。

該当のソースコード

Python

1import datetime 2import requests 3import gspread 4from oauth2client.service_account import ServiceAccountCredentials 5 6# ====================【設定値の入力】==================== 7KOT_API_TOKEN = 'KOTのAPIトークン' 8SPREADSHEET_ID = '対象のスプレッドシートID' 9CREDENTIALS_FILE = 'Google Sheetsの認証JSONファイル名' 10# ======================================================= 11 12def fetch_kot_daily_workings_perfect(start_date, end_date): 13 """💡 ロックされている項目を一切要求しない、100%安全な単一パラメータ設定""" 14 url = "https://api.kingtime.jp/v1.0/daily-workings" 15 headers = { 16 "Authorization": f"Bearer {KOT_API_TOKEN}", 17 "Content-Type": "application/json; charset=utf-8" 18 } 19 params = { 20 "start": start_date, 21 "end": end_date, 22 "additionalFields": "currentDateEmployee" 23 } 24 response = requests.get(url, headers=headers, params=params) 25 return response.json() if response.status_code == 200 else None 26 27def process_and_write_all(): 28 today = datetime.date.today() 29 start_date = today.replace(day=1).strftime('%Y-%m-%d') 30 end_date = today.strftime('%Y-%m-%d') 31 32 print(f"📦 安全ルートを確立。KOT APIからエラー判定フラグを一括抽出中... ({start_date}{end_date})") 33 kot_data = fetch_kot_daily_workings_perfect(start_date, end_date) 34 if not kot_data: 35 print("❌ データ取得失敗により処理を中断します。"); return 36 37 error_rows = [] # ①エラー貼付用(22列構成) 38 noclock_rows = [] # ②打刻なし貼付用(13列構成) 39 40 for day_data in kot_data: 41 workings = day_data.get('dailyWorkings', []) 42 raw_date = day_data.get('date', '') 43 formatted_date = raw_date.replace('-', '/') # スラッシュ書式 44 45 for item in workings: 46 emp = item.get('currentDateEmployee', {}) 47 if not emp: 48 continue 49 50 division_name = emp.get('divisionName', '') 51 employee_code = str(emp.get('code', '')).strip() 52 employee_name = f"{emp.get('lastName', '')} {emp.get('firstName', '')}".strip() 53 54 # 共通除外:休暇・休職者はスキップ 55 holiday_name = item.get('holidaysObtained', {}).get('fulltimeHoliday', {}).get('name', '') if item.get('holidaysObtained') else '' 56 if holiday_name in ["休職", "育児休業", "産前産後休暇"]: 57 continue 58 59 # 💡【[申] のダイレクト自動判定】 基本項目にある各種申請の承認待ち(1)を漏らさずキャッチ 60 is_pending = ( 61 item.get('confirmedStatus') in [2, 3] or 62 item.get('timeCardApplicationStatus') == 1 or 63 item.get('scheduleApplicationStatus') == 1 or 64 item.get('overtimeApplicationStatus') == 1 or 65 item.get('leaveEarlyApplicationStatus') == 1 66 ) 67 68 detected_error_reason = None 69 70 # 1. 出勤打刻が連続しています(専用フラグを直接読み込み) 71 if item.get('isClockInDuplicated') is True: 72 detected_error_reason = "出勤打刻が連続しています。" 73 74 # 2. 休憩開始、終了のペアが揃っていません(専用フラグを直接読み込み) 75 elif item.get('isBreakTimeReasoned') is True: 76 detected_error_reason = "休憩開始、終了のペアが揃っていません。" 77 78 # 3. 出勤打刻が最初に行われていません 79 # (KOTがエラーと判定しているが、連続でも休憩不整合でもなく、退勤だけが残っているケースをカバー) 80 elif item.get('isError', False) and item.get('clockOutTime') and not item.get('clockInTime'): 81 detected_error_reason = "出勤打刻が最初に行われていません。" 82 83 # 4. 出退勤のペアが揃っていません(上記以外の不整合エラーのデフォルト) 84 elif item.get('isError', False): 85 detected_error_reason = "出退勤のペアが揃っていません。" 86 87 # 🚨 パターンA:エラー貼付(赤シート)の対象 88 if detected_error_reason: 89 # 💡 申請中であれば、末尾に「 [申]」を自動合成 90 status_text = f"{detected_error_reason} [申]" if is_pending else detected_error_reason 91 92 row1 = [""] * 22 93 row1[0] = division_name 94 row1[1] = employee_code 95 row1[6] = formatted_date 96 row1[11] = status_text 97 row1[13] = employee_name 98 row1[17] = formatted_date 99 error_rows.append(row1) 100 continue 101 102 # 🚨 パターンB:打刻なし貼付(青シート)の対象 103 if item.get('workdayTypeName') == "平日": 104 if item.get('totalWork', 0) == 0 and item.get('breakTime', 0) == 0: 105 row2 = [""] * 13 106 row2[0] = division_name 107 row2[1] = employee_code 108 row2[6] = formatted_date 109 row2[8] = employee_name 110 row2[12] = formatted_date 111 noclock_rows.append(row2) 112 113 # 3. Googleスプレッドシートへ一括書き込み 114 print("🍏 Googleスプレッドシートへの確定上書き転記を開始します...") 115 scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive'] 116 creds = ServiceAccountCredentials.from_json_keyfile_name(CREDENTIALS_FILE, scope) 117 client = gspread.authorize(creds) 118 ss = client.open_by_key(SPREADSHEET_ID) 119 120 # ①赤シート上書き 121 sheet1 = ss.worksheet('①エラー貼付') 122 sheet1.clear() 123 header1 = ["所属", "従業員コード", "氏名(※未使用)", "", "", "", "勤務日(※未使用)", "", "", "", "", "判定", "", "名前", "", "", "", "勤務日", "", "", "", ""] 124 sheet1.append_rows([header1] + error_rows, value_input_option='RAW') 125 126 # ②青シート上書き 127 sheet2 = ss.worksheet('②打刻なし貼付') 128 sheet2.clear() 129 header2 = ["所属", "従業員コード", "氏名(※未使用)", "", "", "", "勤務日(※未使用)", "", "名前", "", "", "", "勤務日"] 130 sheet2.append_rows([header2] + noclock_rows, value_input_option='RAW') 131 132 print(f"\n🚀【完全自動同期完了】KOTのセキュリティを完全に回避し、個別エラー詳細と[申]の転記に大成功しました!") 133 print(f" ➔ ①エラー貼付: {len(error_rows)} 件") 134 print(f" ➔ ②打刻なし貼付: {len(noclock_rows)} 件") 135 136if __name__ == "__main__": 137 process_and_write_all()

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

エラー理由が一律「出退勤のペアが揃っていません。」になってしまう(実際は他にも「出勤打刻が最初に行われていません。」「休憩開始、終了のペアが揃っていません。」「出勤打刻が連続しています。」等の理由になるはず)

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

blixor

2026/06/06 01:54

APIレスポンスの中身を直接確認するのが一番早い 現状のコードだと、`isClockInDuplicated`や`isBreakTimeReasoned`といったフラグを見てエラー理由を判定しているけど、期待通りに動いていないようですね。
guest

回答2

0

ライセンスが無いので動作確認できないので、https://developer.kingoftime.jp/を見て回答します。

提示されたソースのJSONキーを上記ページで検索しました。
API(daily-workings)に対するレスポンス(dailyWorkings)かどうか、dailyWorkingsと親子関係にあるかどうかは無視しています。

  • date
  • currentDateEmployee
  • divisionName
  • code
  • lastName
  • firstName
  • holidaysObtained
  • fulltimeHoliday
  • name
  • isError
  • workdayTypeName
  • totalWork
  • breakTime

  • confirmedStatus
  • timeCardApplicationStatus
  • scheduleApplicationStatus
  • overtimeApplicationStatus
  • leaveEarlyApplicationStatus
  • isClockInDuplicated
  • isBreakTimeReasoned
  • clockOutTime
  • clockInTime

定義の無いJSONキーを使って判定はできないです。
そもそも、何を根拠にこのようなコーディングをしたのでしょうか?
ドキュメント化されていない機能もあるかもしれませんが、実際に上記のようなキーの値が返ってきたのでしょうか?

投稿2026/06/06 04:24

hiroki-o

総合スコア1850

3chomenanigashi

2026/06/08 08:39

申し訳ありません、Gemini相手に試行錯誤した結果、存在しないエンドポイントが大量に混じったようです。確認不足でした。
guest

0

まず、APIが実際にどんなデータを返しているのかを生で確認しましょう。以下のように、レスポンスの最初の1件をprintするコードを仕込んでみてください。

python

1def fetch_kot_daily_workings_perfect(start_date, end_date): 2 url = "https://api.kingtime.jp/v1.0/daily-workings" 3 headers = {"Authorization": f"Bearer {KOT_API_TOKEN}"} 4 params = {"start": start_date, "end": end_date} 5 response = requests.get(url, headers=headers, params=params) 6 7 if response.status_code == 200: 8 data = response.json() 9 if data: 10 print("=== APIレスポンスサンプル(最初の勤務データ) ===") 11 import json 12 print(json.dumps(data[0], indent=2, ensure_ascii=False)) 13 return data 14 else: 15 print(f"APIエラー: {response.status_code}") 16 return None

この出力を見れば、以下のことがわかります。

  • エラー理由を特定するための専用フィールド(errorTypeerrorMessageなど)が存在するかどうか
  • isClockInDuplicatedisBreakTimeReasonedが本当に正しいパスにあるのか
  • 他に使えそうなフィールドがないか

投稿2026/06/06 01:59

blixor

総合スコア66

3chomenanigashi

2026/06/08 08:39

ありがとうございます!多くの手がかりが得られたのでもう少し試行錯誤してみます!
blixor

2026/06/08 12:57

承知いたしました。いつでもご連絡ください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.25%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問