アプリ設定API
kintone の REST API は、レコードの操作だけでなく、アプリそのものの設定をプログラムから操作することもできます。フィールドの追加・変更・削除、フォームレイアウトの更新、一覧やグラフの設定など、管理画面から行う操作の多くを API で自動化できます。
これにより、大量のアプリに同じフィールドを一括追加したり、テンプレートからアプリを自動作成したりといった運用が可能になります。
この記事では、アプリ設定に関連する主要な REST API の使い方と、運用上の注意点を解説します。
アプリ設定 API の概要
アプリ設定 API で操作できる主な項目は以下のとおりです。
| API | エンドポイント | 操作内容 |
|---|---|---|
| アプリの取得 | GET /k/v1/app.json | アプリの基本情報を取得 |
| アプリ一覧の取得 | GET /k/v1/apps.json | 条件に一致するアプリの一覧を取得 |
| フォームフィールドの取得 | GET /k/v1/app/form/fields.json | フィールドの設定一覧を取得 |
| フォームフィールドの追加 | POST /k/v1/app/form/fields.json | フィールドを追加 |
| フォームフィールドの更新 | PUT /k/v1/app/form/fields.json | フィールドの設定を変更 |
| フォームフィールドの削除 | DELETE /k/v1/app/form/fields.json | フィールドを削除 |
| フォームレイアウトの取得 | GET /k/v1/app/form/layout.json | フォームレイアウトを取得 |
| フォームレイアウトの更新 | PUT /k/v1/app/form/layout.json | フォームレイアウトを変更 |
| アプリの設定変更をデプロイ | POST /k/v1/preview/app/deploy.json | 変更を本番環境に反映 |
| デプロイ状況の確認 | GET /k/v1/preview/app/deploy.json | デプロイの進行状況を確認 |
アプリ設定の変更は、まずプレビュー環境に反映されます。変更を実際のアプリに適用するには、デプロイ(運用環境への反映)が必要です。これは管理画面での「アプリを更新」に相当します。
フォームフィールドの取得
アプリに設定されているフィールドの一覧を取得します。
/**
* アプリのフォームフィールド一覧を取得する
* @param { Object } params
* @param { string | number } params.app - アプリID
* @returns { Promise<{ properties: Record<string, any>, revision: string }> }
*/
const getFormFields = (params) => {
return kintone.api(kintone.api.url('/k/v1/app/form/fields.json', true), 'GET', {
app: params.app,
});
};
Node.js で外部から取得する場合
const KINTONE_DOMAIN = 'your-subdomain.cybozu.com';
const API_TOKEN = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const APP_ID = 1;
const getFormFields = async () => {
const url = `https://${KINTONE_DOMAIN}/k/v1/app/form/fields.json?app=${APP_ID}`;
const response = await fetch(url, {
headers: { 'X-Cybozu-API-Token': API_TOKEN },
});
return response.json();
};
const { properties } = await getFormFields();
// フィールドタイプごとに分類
const fieldsByType = {};
for (const [code, field] of Object.entries(properties)) {
const type = field.type;
if (!fieldsByType[type]) fieldsByType[type] = [];
fieldsByType[type].push({ code, label: field.label });
}
console.log(fieldsByType);
フィールドの追加
プログラムからアプリにフィールドを追加できます。大量のアプリに同じフィールドを一括追加する場合などに有効です。
const KINTONE_DOMAIN = 'your-subdomain.cybozu.com';
const API_TOKEN = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const APP_ID = 1;
/**
* アプリにフィールドを追加する
* @param { string | number } app - アプリID
* @param { Record<string, any> } properties - 追加するフィールド定義
*/
const addFormFields = async (app, properties) => {
const url = `https://${KINTONE_DOMAIN}/k/v1/preview/app/form/fields.json`;
const response = await fetch(url, {
method: 'POST',
headers: {
'X-Cybozu-API-Token': API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({ app, properties }),
});
if (!response.ok) {
const error = await response.json();
throw new Error(`[${error.code}] ${error.message}`);
}
return response.json();
};
// 文字列1行フィールドを追加する例
await addFormFields(APP_ID, {
管理番号: {
type: 'SINGLE_LINE_TEXT',
code: '管理番号',
label: '管理番号',
required: true,
unique: true,
},
備考: {
type: 'MULTI_LINE_TEXT',
code: '備考',
label: '備考',
required: false,
},
});
POST /k/v1/preview/app/form/fields.json
はプレビュー環境にフィールドを追加します。実際のアプリに反映するには、後述のデプロイ API
を実行する必要があります。
フィールドタイプと設定例
主要なフィールドタイプの定義例を紹介します。
const fieldExamples = {
// 文字列(1行)
タイトル: {
type: 'SINGLE_LINE_TEXT',
code: 'タイトル',
label: 'タイトル',
required: true,
maxLength: '100',
},
// 数値
金額: {
type: 'NUMBER',
code: '金額',
label: '金額',
required: false,
digit: true, // 桁区切りを表示
unit: '円',
unitPosition: 'AFTER',
},
// ドロップダウン
カテゴリ: {
type: 'DROP_DOWN',
code: 'カテゴリ',
label: 'カテゴリ',
required: true,
options: {
営業: { label: '営業', index: '0' },
開発: { label: '開発', index: '1' },
管理: { label: '管理', index: '2' },
},
defaultValue: '営業',
},
// 日付
期限日: {
type: 'DATE',
code: '期限日',
label: '期限日',
required: false,
defaultNowValue: false,
},
// チェックボックス
対応OS: {
type: 'CHECK_BOX',
code: '対応OS',
label: '対応OS',
options: {
Windows: { label: 'Windows', index: '0' },
macOS: { label: 'macOS', index: '1' },
Linux: { label: 'Linux', index: '2' },
},
defaultValue: ['Windows'],
},
// ユーザー選択
担当者: {
type: 'USER_SELECT',
code: '担当者',
label: '担当者',
required: true,
},
};
フィールドの更新・削除
フィールドの設定を変更する
// フィールドのラベルと必須設定を変更する
await fetch(`https://${KINTONE_DOMAIN}/k/v1/preview/app/form/fields.json`, {
method: 'PUT',
headers: {
'X-Cybozu-API-Token': API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
app: APP_ID,
properties: {
管理番号: {
label: '管理ID', // ラベルを変更
required: false, // 必須を解除
},
},
}),
});
フィールドを削除する
// 指定したフィールドコードのフィールドを削除する
await fetch(`https://${KINTONE_DOMAIN}/k/v1/preview/app/form/fields.json`, {
method: 'DELETE',
headers: {
'X-Cybozu-API-Token': API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
app: APP_ID,
fields: ['備考', '旧管理番号'],
}),
});
フィールドを削除すると、そのフィールドに格納されていたデータも完全に失われます。デプロイ前であればプレビュー環境の変更を破棄できますが、デプロイ後のロールバックはできません。削除前に必ずバックアップを取ってください。
アプリのデプロイ
フィールドの追加・変更・削除などの設定変更は、デプロイを実行するまで本番環境に反映されません。
/**
* アプリの設定変更をデプロイする
* @param { Array<{ app: string | number, revision?: string | number }> } apps - デプロイ対象のアプリ
*/
const deployApps = async (apps) => {
await fetch(`https://${KINTONE_DOMAIN}/k/v1/preview/app/deploy.json`, {
method: 'POST',
headers: {
'X-Cybozu-API-Token': API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({ apps }),
});
};
/**
* デプロイの完了を待つ
* @param { string | number } appId - アプリID
* @param { number } [maxWait=30000] - 最大待機時間(ミリ秒)
*/
const waitForDeploy = async (appId, maxWait = 30000) => {
const startTime = Date.now();
while (Date.now() - startTime < maxWait) {
const response = await fetch(
`https://${KINTONE_DOMAIN}/k/v1/preview/app/deploy.json?apps=${appId}`,
{ headers: { 'X-Cybozu-API-Token': API_TOKEN } }
);
const data = await response.json();
const status = data.apps[0].status;
if (status === 'SUCCESS') {
console.log('デプロイ完了');
return;
}
if (status === 'FAIL') {
throw new Error('デプロイに失敗しました');
}
if (status === 'CANCEL') {
throw new Error('デプロイがキャンセルされました');
}
// PROCESSING の場合は 1 秒待ってリトライ
await new Promise((resolve) => setTimeout(resolve, 1000));
}
throw new Error('デプロイがタイムアウトしました');
};
// 実行例: フィールドを追加してデプロイ
await addFormFields(APP_ID, {
新フィールド: {
type: 'SINGLE_LINE_TEXT',
code: '新フィールド',
label: '新フィールド',
},
});
await deployApps([{ app: APP_ID }]);
await waitForDeploy(APP_ID);
デプロイ状況の確認 API は以下のステータスを返します: - PROCESSING: デプロイ処理中 - SUCCESS:
デプロイ成功 - FAIL: デプロイ失敗 - CANCEL: デプロイがキャンセルされた
実践例:複数アプリへの一括フィールド追加
複数のアプリに同じフィールドを一括で追加するスクリプトの例です。
const TARGET_APP_IDS = [1, 2, 3, 4, 5];
const NEW_FIELD = {
最終確認日: {
type: 'DATE',
code: '最終確認日',
label: '最終確認日',
required: false,
},
};
const batchAddField = async () => {
const results = [];
for (const appId of TARGET_APP_IDS) {
try {
// フィールドを追加
await addFormFields(appId, NEW_FIELD);
results.push({ appId, status: 'success' });
console.log(`アプリ ${appId}: フィールド追加成功`);
} catch (error) {
results.push({ appId, status: 'error', message: error.message });
console.error(`アプリ ${appId}: フィールド追加失敗 - ${error.message}`);
}
}
// 成功したアプリを一括デプロイ
const successApps = results
.filter((r) => r.status === 'success')
.map((r) => ({ app: r.appId }));
if (successApps.length > 0) {
await deployApps(successApps);
console.log(`${successApps.length} 件のアプリをデプロイしました`);
// デプロイ完了を待つ
for (const app of successApps) {
await waitForDeploy(app.app);
}
}
return results;
};
一括操作を行う場合は、最初にテスト用のアプリで動作確認してから本番アプリに適用することをお勧めします。
アプリ設定 API 利用時の注意点
API トークンのアクセス権
アプリ設定 API を使用するには、API トークンにアプリ管理のアクセス権が必要です。レコード操作のアクセス権とは別に設定する必要があります。
同時編集の制限
アプリの設定を編集中(プレビュー環境に未デプロイの変更がある状態)に別の設定変更を行うと、エラーになることがあります。管理画面での手動変更と API による変更が競合しないよう注意してください。
レート制限
アプリ設定 API にも kintone のレート制限が適用されます。大量のアプリを連続で操作する場合は、リクエスト間に適切なインターバルを設けてください。
まとめ
- アプリ設定 API を使えば、フィールドの追加・変更・削除をプログラムから実行できる
- 設定変更はプレビュー環境に反映され、デプロイ API で本番環境に適用する
- 複数アプリへの一括フィールド追加など、管理画面では手間のかかる操作を自動化できる
- API トークンにはアプリ管理のアクセス権が必要
- フィールドの削除は取り消し不可のため、実行前のバックアップが重要