株式会社etika(エティカ)CRMサポートセンターです。
検証環境の構築や複数組織への同じ設定展開で、「カスタム項目を毎回UIでポチポチ作るのが大変」という場面があります。実はZoho CRMのカスタム項目はAPIでまとめて作成できます。この記事では、/crm/v8/settings/fieldsエンドポイントを使って、テキスト・複数行テキスト・選択リストの項目をNode.jsから一括作成する方法を、実コードとハマりどころつきで解説します。
結論(先に要点)
- 項目作成は
POST /crm/v8/settings/fields?module=<モジュール>に{ fields: [ ... ] }を送る- 複数行テキスト(textarea)は
textarea: { type: "small" }の指定が必須- 作成後にAPIで払い出されたAPI名(api_name)を取得しておくと、後続のレコード更新で使える
(認証トークンの取得は別記事「Zoho APIをスクリプトから叩く最短ルート」を参照してください。以下のcrmFetchはそこで作ったヘルパーです。)
作成する項目の定義
例として、商談(Deals)モジュールに3種類の項目を作ります。
const FIELD_DEFS = [
// 1行テキスト
{ field_label: "次回アクション", data_type: "text", length: 255 },
// 複数行テキスト(★ textarea.type が必須)
{ field_label: "商談要約(AI)", data_type: "textarea", textarea: { type: "small" } },
// 選択リスト(picklist)
{
field_label: "業種",
data_type: "picklist",
pick_list_values: ["産業機械", "自動車部品", "医療機器", "家電", "建材"].map((v, i) => ({
display_value: v, actual_value: v, sequence_number: i + 1,
})),
},
];

ポイントは複数行テキストです。data_type: "textarea"だけでは作成に失敗し、textarea: { type: "small" }(small / large / rich_text)の指定が必要です。
冪等に作る(同名があればスキップ)
スクリプトは何度実行しても壊れないように作るのが鉄則です。作成前に既存項目を取得し、同じラベルがあればスキップします。
async function createFields(token) {
const existing = (await crmFetch(token, "/crm/v8/settings/fields?module=Deals")).fields ?? [];
const byLabel = new Map(existing.map((f) => [f.field_label, f]));
for (const def of FIELD_DEFS) {
if (byLabel.has(def.field_label)) {
console.log(`スキップ(既存): ${def.field_label} → ${byLabel.get(def.field_label).api_name}`);
continue;
}
try {
await crmFetch(token, "/crm/v8/settings/fields?module=Deals", {
method: "POST",
body: { fields: [def] },
});
console.log(`作成: ${def.field_label}`);
} catch (e) {
// 権限エラー(403)等はUIで手動作成 → 再実行でapi_nameだけ拾う運用に
console.error(`作成失敗: ${def.field_label} — ${e.message}`);
}
}
}
払い出されたAPI名を取得する
カスタム項目のAPI名は、ラベルから自動生成されます(同名衝突時は末尾に連番が付くこともあります)。後でレコード更新に使うため、作成後に再取得して控えておきます。
async function resolveApiNames(token) {
const fields = (await crmFetch(token, "/crm/v8/settings/fields?module=Deals")).fields ?? [];
const findApi = (label) => fields.find((f) => f.field_label === label)?.api_name ?? null;
return {
nextAction: findApi("次回アクション"),
meetingSummary: findApi("商談要約(AI)"),
industrySegment: findApi("業種"),
};
}
// → { nextAction: "Next_Action", meetingSummary: "field...", industrySegment: "..." } のように確定

つまずきやすいポイント
- textareaの
type未指定:data_type: "textarea"単独では失敗します。textarea: { type: "small" }を必ず付けます。 - 必要なscope:
ZohoCRM.settings.fields.ALL(またはZohoCRM.settings.ALL)が必要です。 - 権限(403):管理者権限やエディションによって項目作成が制限される場合があります。UI手動作成にフォールバックし、スクリプトは「api_nameの取得だけ」再実行できる設計にしておくと安全です。
- API名はラベル依存:日本語ラベルからは
field123のような自動名が付くことがあります。レコード更新では表示ラベルではなく、このapi_nameを使います。
まとめ
/crm/v8/settings/fieldsへのPOSTで、カスタム項目はコードから一括作成できます。textareaのtype指定と作成後のapi_name取得、そして冪等な作りの3点を押さえれば、検証環境の再現や複数組織への設定展開が一気に楽になります。項目作成→データ投入→レコード更新までスクリプト化すれば、デモ環境や検証環境を「コードで再構築できる資産」にできます。



