GAS(Google Apps Script)で外部APIを呼び出すには、UrlFetchApp.fetch に URL とオプションを渡し、返ってきた HTTPResponse から応答コードと本文を取り出します。 APIキーはコードに直接書かず、スクリプト プロパティに保存して実行時に読み込みます。

この記事では、APIキーの読み込み・応答コードでの分岐・待機つきの再試行・入れ子の JSON を表にする処理・シートへの一括書き込みを1つにまとめたコードと、fetch のオプション、HTTPResponse のメソッド、3種類のプロパティ、割り当て上限の一覧表を載せます。

確認環境:Google Apps Script の公式リファレンスとガイド(UrlFetchApp、HTTPResponse、Properties サービス、割り当て)を 2026-10-05 に開いて照合しました。掲載コードは Node.js 22.22.2 で構文を検査し、TypeScript 7.0.2 と型定義 @types/google-apps-script 2.0.13 で、メソッド名と引数の型が合うことを検査しています。再試行と表への変換の動きは、UrlFetchApp などを代役のオブジェクトに差し替えて Node.js で動かした結果です。Google のサーバー上での出力例は載せていません。

この記事の結論

  • APIキーはスクリプト プロパティに保存します。 PropertiesService.getScriptProperties().getProperty('API_KEY') で読み込み、コードには書きません。
  • fetch には muteHttpExceptions: true を付けます。 4xx や 5xx でも例外にならず HTTPResponse が返るので、getResponseCode() で分岐できます。
  • 再試行するのは 429 と 5xx だけにします。 401 や 404 は待っても結果が変わらないので、すぐに内容を表示して止めます。
  • シートへの書き込みは、2次元配列にして setValues を1回だけ呼びます。 行ごとに書き込むより呼び出しの回数が少なくなります。
  • 複数の URL をまとめて取るなら fetchAll、1件ずつ結果を見て次を決めるなら fetch を使います。

UrlFetchAppの早見表

やりたいこと 書き方
GET で取得する UrlFetchApp.fetch(url)
オプションを付けて取得する UrlFetchApp.fetch(url, { method: 'get', headers: {...} })
JSON を POST する { method: 'post', contentType: 'application/json', payload: JSON.stringify(obj) }
フォーム形式で POST する { method: 'post', payload: { name: '値' } }
認証ヘッダーを付ける headers: { Authorization: 'Bearer ' + key }
4xx・5xx でも例外にしない muteHttpExceptions: true
応答コードを調べる res.getResponseCode()
本文を文字列で取り出す res.getContentText()
JSON をオブジェクトにする JSON.parse(res.getContentText())
応答ヘッダーを調べる res.getHeaders()
複数の URL をまとめて取得する UrlFetchApp.fetchAll([{ url: ... }, { url: ... }])
送る内容を送信せずに確かめる UrlFetchApp.getRequest(url, params)
APIキーを読む PropertiesService.getScriptProperties().getProperty('API_KEY')
待機する Utilities.sleep(ミリ秒)

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「GASで外部APIを呼び出す UrlFetchAppとAPIキーの保存方法」

コピーして使える1本のコード

題材は、備品の一覧を返す架空の API(https://api.example.com/v1/items)です。スプレッドシートに紐づいたスクリプトに貼り、API_BASE と認証ヘッダーの形を、使う API の仕様に合わせて置き換えてください。

// ===== 設定 =====
const API_BASE = 'https://api.example.com/v1';   // 呼び出す API の URL に置き換える
const SHEET_NAME = 'items';                      // 書き込み先のシート名
const MAX_TRIES = 4;                             // 最初の1回を含めた試行回数

/**
 * スクリプト プロパティから API キーを読む。
 * 未設定のときは、原因が分かるメッセージで止める。
 */
function getApiKey_() {
  const key = PropertiesService.getScriptProperties().getProperty('API_KEY');
  if (!key) {
    throw new Error('スクリプト プロパティ API_KEY が設定されていません。');
  }
  return key;
}

/**
 * 応答コードを見て、429 と 5xx のときだけ待ってから再試行する。
 * 2xx なら HTTPResponse を返し、それ以外は応答コードつきのエラーにする。
 */
function fetchWithRetry_(url, params) {
  const options = Object.assign({}, params, { muteHttpExceptions: true });

  for (let attempt = 1; ; attempt++) {
    const res = UrlFetchApp.fetch(url, options);
    const code = res.getResponseCode();

    if (code >= 200 && code < 300) {
      return res;
    }

    const retryable = code === 429 || code >= 500;
    if (!retryable || attempt >= MAX_TRIES) {
      throw new Error('HTTP ' + code + ': ' + res.getContentText().slice(0, 200));
    }

    Utilities.sleep(waitMillis_(res.getHeaders(), attempt));
  }
}

/**
 * 待ち時間(ミリ秒)を決める。
 * Retry-After ヘッダーが秒数で付いていればそれに従い、無ければ 1秒→2秒→4秒 と倍にする。
 */
function waitMillis_(headers, attempt) {
  const retryAfter = Number(headers['Retry-After'] || headers['retry-after']);
  const ms = retryAfter > 0 ? retryAfter * 1000 : 1000 * Math.pow(2, attempt - 1);
  return Math.min(ms, 30000);
}

/**
 * 入れ子のオブジェクトを「親.子」という列名の1階層に平らにする。
 * 配列は「, 」でつないだ1つの文字列にする。
 */
function flatten_(obj, prefix, out) {
  prefix = prefix || '';
  out = out || {};
  Object.keys(obj).forEach(function (k) {
    const v = obj[k];
    const key = prefix ? prefix + '.' + k : k;
    if (Array.isArray(v)) {
      out[key] = v.map(function (x) {
        return x !== null && typeof x === 'object' ? JSON.stringify(x) : x;
      }).join(', ');
    } else if (v !== null && typeof v === 'object') {
      flatten_(v, key, out);
    } else {
      out[key] = v === null || v === undefined ? '' : v;
    }
  });
  return out;
}

/**
 * オブジェクトの配列を、1行目が見出しの2次元配列にする。
 * 行によって項目が欠けていても、列数がそろうように空文字で埋める。
 */
function toTable_(items) {
  const rows = items.map(function (item) { return flatten_(item); });
  const headers = [];
  rows.forEach(function (row) {
    Object.keys(row).forEach(function (k) {
      if (headers.indexOf(k) === -1) headers.push(k);
    });
  });
  const body = rows.map(function (row) {
    return headers.map(function (h) { return h in row ? row[h] : ''; });
  });
  return [headers].concat(body);
}

/**
 * 外部 API から JSON を取得し、シートへ1回で書き込む。
 */
function importItems() {
  const res = fetchWithRetry_(API_BASE + '/items?limit=100', {
    method: 'get',
    headers: {
      Authorization: 'Bearer ' + getApiKey_(),
      Accept: 'application/json'
    }
  });

  const data = JSON.parse(res.getContentText());
  const items = Array.isArray(data) ? data : data.items;
  if (!items || items.length === 0) {
    console.log('取得した件数は 0 件でした。');
    return;
  }

  const table = toTable_(items);
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName(SHEET_NAME) || ss.insertSheet(SHEET_NAME);

  sheet.clearContents();
  sheet.getRange(1, 1, table.length, table[0].length).setValues(table);
  console.log(items.length + ' 件を書き込みました。');
}

このコードの流れは次の4段階です。

段階 関数 していること
1. キーを読む getApiKey_ スクリプト プロパティから読み、無ければ原因の分かる文で止める
2. 呼び出す fetchWithRetry_ 応答コードで分岐し、429 と 5xx だけ待って再試行する
3. 表にする flatten_・toTable_ 入れ子を「親.子」の列名に平らにし、見出しつきの2次元配列にする
4. 書き込む importItems 範囲の行数・列数を配列に合わせ、setValues を1回呼ぶ

関数名の末尾の _ は、スクリプト エディタの実行メニューに出さない補助関数に付けています。

動きを確かめた結果

UrlFetchApp・Utilities・PropertiesService・SpreadsheetApp を代役のオブジェクトに差し替え、Node.js 22.22.2 で importItems を動かした結果です。API が次の JSON を返す想定にしました。

{"items": [
  {"id": 101, "name": "プロジェクター", "room": {"floor": 3, "name": "会議室A"}, "tags": ["映像", "貸出可"], "note": null},
  {"id": 102, "name": "ホワイトボード", "room": {"floor": 2, "name": "会議室B"}, "tags": []},
  {"id": 103, "name": "延長コード", "room": {"floor": 3, "name": "倉庫"}, "tags": ["電源"], "owner": {"dept": "総務"}}
]}
--- 1) 1回目で 200
fetch の回数: 1  待機(ms): []
ログ: 3 件を書き込みました。
setValues の範囲: 4 行 x 7 列
["id","name","room.floor","room.name","tags","note","owner.dept"]
[101,"プロジェクター",3,"会議室A","映像, 貸出可","",""]
[102,"ホワイトボード",2,"会議室B","","",""]
[103,"延長コード",3,"倉庫","電源","","総務"]
--- 2) 429(Retry-After: 3) → 503 → 200
fetch の回数: 3  待機(ms): [3000,2000]
ログ: 3 件を書き込みました。
--- 3) 500 が続く
fetch の回数: 4  待機(ms): [1000,2000,4000]
エラー: HTTP 500: e4
--- 4) 401(再試行しない)
fetch の回数: 1  待機(ms): []
エラー: HTTP 401: {"error":"invalid api key"}
--- 5) API_KEY が無い
fetch の回数: 0  待機(ms): []
エラー: スクリプト プロパティ API_KEY が設定されていません。
--- 6) 0 件
fetch の回数: 1  待機(ms): []
ログ: 取得した件数は 0 件でした。
  • 1) では、3件目にしか無い owner.dept も列になり、項目の無い行は空文字で埋まっています。行ごとに列数がそろっているので、setValues にそのまま渡せます。
  • 2) では、Retry-After が付いた 429 のあとは 3 秒、ヘッダーの無い 503 のあとは 2 秒待っています。
  • 3) では、4回試したところで止まり、最後の応答コードと本文がエラーの文に入ります。
  • 4) の 401 は、1回で止まっています。

APIキーをスクリプト プロパティに保存する

画面から保存する手順

Google の公式ガイドに書かれている手順です(画面の表記は英語版のガイドのもの)。

  1. Apps Script のプロジェクトを開く
  2. Project Settings(プロジェクトの設定)をクリックする
  3. Script Properties の下の Add script property をクリックする
  4. Property にキーの名前(例:API_KEY)、Value に値を入力する
  5. Save script properties をクリックする

この画面から追加できるのは 50 個までで、それより多い場合はコードから設定すると書かれています。

コードから保存する

/**
 * API キーをコードから保存する(1回だけ実行し、実行後は値を消しておく)。
 */
function saveApiKeyOnce() {
  PropertiesService.getScriptProperties().setProperty('API_KEY', 'ここにキーを貼る');
}

この関数は、キーを貼って1回実行したら、貼った値をコードから消しておきます。値はプロパティに残るので、以降は getApiKey_ で読み込めます。

プロパティを読み書きするメソッド

メソッド 戻り値 内容
getProperty(key) String キーに対応する値を返す。キーが無ければ null
getProperties() Object すべてのキーと値のコピーを返す
getKeys() String[] すべてのキーを返す
setProperty(key, value) Properties 1組を保存する
setProperties(properties) Properties オブジェクトの中身をまとめて保存する
setProperties(properties, deleteAllOthers) Properties まとめて保存し、指定すればほかのプロパティを消す
deleteProperty(key) Properties 1つ消す
deleteAllProperties() Properties すべて消す

値はすべて文字列として保存されます。 文字列でない値は自動で文字列に変換されると書かれているので、数値や真偽値を読み出したときは Number(...) や === 'true' で扱います。オブジェクトを入れたいときは JSON.stringify で文字列にしてから保存し、読むときに JSON.parse します。

スクリプト・ユーザー・ドキュメントの3種類の違い

種類 取得するメソッド 誰が読めるか どこに紐づくか 公式ガイドの用途の例
スクリプト プロパティ getScriptProperties() そのスクリプトのすべての利用者 スクリプト 開発者の外部データベースのユーザー名とパスワードのような、アプリ全体の設定
ユーザー プロパティ getUserProperties() いま実行している利用者だけ スクリプトと利用者の組み合わせ 単位の表示設定のような、利用者ごとの設定
ドキュメント プロパティ getDocumentProperties() 開いているドキュメントのすべての利用者 スクリプトとドキュメントの組み合わせ 埋め込んだグラフの元 URL のような、ドキュメントごとのデータ
  • どの種類も、別のスクリプトとは共有されません。
  • getDocumentProperties() は、スクリプトがアドインとして公開されているか、Google のファイルに紐づいている場合だけ使えます。それ以外では null を返します。

どのプロパティに保存するかの判断表

条件 選ぶもの
チームで1つの APIキーを共有し、誰が実行しても同じキーで呼び出す スクリプト プロパティ
利用者それぞれが自分の APIキーやトークンを持っている ユーザー プロパティ
スプレッドシートごとに取得先の URL や対象の ID が違う ドキュメント プロパティ
前回の取得日時など、スクリプト全体で1つあればよい値 スクリプト プロパティ

スクリプト プロパティの値は、プロジェクトの設定画面に一覧で表示されます。プロジェクトを開ける人の範囲と、キーを知ってよい人の範囲が合っているかを、保存する前に確かめておくと安心です。

fetchのオプション一覧

UrlFetchApp.fetch(url, params) の params に指定できる項目です。

項目 型 内容 既定値
method String HTTP メソッド。get・delete・patch・post・put get
headers Object リクエスト ヘッダーのキーと値 なし
contentType String 本文の種類。例:application/json、application/xml; charset=utf-8 application/x-www-form-urlencoded
payload String など 送る本文。文字列、バイト配列、Blob、またはオブジェクト。オブジェクトはフォームの項目名と値として扱われる なし
muteHttpExceptions Boolean true にすると、応答コードがエラーを示していても例外にせず HTTPResponse を返す false
followRedirects Boolean false にするとリダイレクトをたどらず、元の応答を返す true
validateHttpsCertificates Boolean false にすると HTTPS の証明書が無効でも続ける true
escaping Boolean false にすると URL の予約文字をエスケープしない true
  • URL の長さは 2,082 文字までと書かれています。
  • UrlFetchApp を使うスクリプトには https://www.googleapis.com/auth/script.external_request のスコープが必要です。通常は自動で検出され、スコープを明示的に設定している場合だけ自分で追加します。
  • リクエストは Google の IP アドレスの範囲から送られます。接続元を制限している API では、その範囲を許可する設定が要ります。

JSONをPOSTする

/**
 * JSON を POST で送る。
 */
function createItem() {
  const res = fetchWithRetry_(API_BASE + '/items', {
    method: 'post',
    contentType: 'application/json',
    headers: { Authorization: 'Bearer ' + getApiKey_() },
    payload: JSON.stringify({ name: 'プロジェクター', room: { floor: 3, name: '会議室A' } })
  });
  const created = JSON.parse(res.getContentText());
  console.log('登録した ID: ' + created.id);
}

JSON を送るときは、contentType と JSON.stringify の2つをそろえます。 payload にオブジェクトをそのまま渡すと、フォームの項目として送られます。

送りたい形式 contentType payload
JSON 'application/json' JSON.stringify(obj)
フォーム 指定しない(既定値) { name: '値', memo: '値' }
ファイルつきのフォーム 指定しない { name: '値', file: blob }

送る前に内容を確かめたいときは、UrlFetchApp.getRequest(url, params) を使います。実際には送信せず、送られるはずのリクエストの内容をオブジェクトで返します。

HTTPResponseのメソッド一覧

メソッド 戻り値 内容
getResponseCode() Integer HTTP の応答コード(200 など)
getContentText() String 本文を文字列で返す
getContentText(charset) String 文字コードを指定して本文を文字列で返す
getContent() Byte[] 本文をバイト配列で返す
getBlob() Blob 本文を Blob で返す
getAs(contentType) Blob 指定した種類に変換した Blob を返す
getHeaders() Object 応答ヘッダーをキーと値で返す
getAllHeaders() Object 応答ヘッダーを返す。同じ名前のヘッダーが複数あるものは配列になる

本文が文字化けするときは、getContentText('Shift_JIS') のように、API が返す文字コードを指定します。画像や PDF のようなバイナリは、getBlob() で受けます。

応答コードで分岐する

muteHttpExceptions: true を付けたうえで、応答コードごとの扱いを決めます。

応答コード 意味 この記事のコードでの扱い
200〜299 成功 HTTPResponse を返す
400 リクエストの形が合っていない 再試行せず、本文を表示して止める
401・403 認証・権限 再試行せず止める。キーの値とヘッダーの形を見直す
404 URL や ID が見つからない 再試行せず止める
429 呼び出しの回数が多い 待ってから再試行する
500〜599 サーバー側の一時的な不調 待ってから再試行する

待ち時間は、応答に Retry-After ヘッダーが秒数で付いていればそれに従い、無ければ 1秒・2秒・4秒と倍に延ばします。1回の待機は 30 秒で頭打ちにしています。スクリプトの実行時間には上限(後述)があるので、試行回数は数回にとどめます。

muteHttpExceptions が効くのは、相手から応答コードが返ってきた場合です。URL の書き方が正しくないなど、応答そのものが得られない場合は fetch が例外を投げるので、呼び出し元を try...catch で囲んで内容を記録します。

function runImport() {
  try {
    importItems();
  } catch (e) {
    console.error('取り込みを中止しました: ' + e.message);
    throw e;   // トリガー実行のときに、実行ログへエラーとして残す
  }
}

入れ子のJSONを表に平らにする

API の JSON は、オブジェクトの中にオブジェクトや配列が入っていることがよくあります。シートは行と列の2次元なので、次の決まりで1階層にします。

JSON の形 表での扱い 例
入れ子のオブジェクト 「親.子」という列名にする room.floor、room.name
文字列や数値の配列 「, 」でつないで1つのセルに入れる 映像, 貸出可
オブジェクトの配列 要素を JSON の文字列にしてつなぐ {"k":1}, {"k":2}
null・項目なし 空文字にする (空のセル)

setValues に渡す2次元配列は、すべての行の列数が同じである必要があります。 toTable_ は、全行に出てくるキーを集めて見出しを作り、その見出しの順に値を並べるので、項目が欠けた行があっても列数がそろいます。

オブジェクトの配列を別の行に展開したい場合(1件の備品に複数の貸出履歴がある、など)は、親の ID を付けた別の表にして、別のシートへ書き込むと扱いやすくなります。

fetchとfetchAllの使い分け

fetchAll は、リクエストの配列を受け取り、HTTPResponse の配列を返します。配列の要素は、URL の文字列か、url に fetch と同じオプションを加えたオブジェクトです。

/**
 * 複数の URL をまとめて取得する。
 */
function importDetails() {
  const ids = [101, 102, 103];
  const key = getApiKey_();
  const requests = ids.map(function (id) {
    return {
      url: API_BASE + '/items/' + id,
      headers: { Authorization: 'Bearer ' + key },
      muteHttpExceptions: true
    };
  });

  const responses = UrlFetchApp.fetchAll(requests);

  const ok = [];
  const ng = [];
  responses.forEach(function (res, i) {
    if (res.getResponseCode() === 200) {
      ok.push(JSON.parse(res.getContentText()));
    } else {
      ng.push(ids[i] + ' (HTTP ' + res.getResponseCode() + ')');
    }
  });
  console.log('取得できた件数: ' + ok.length + ' / 取得できなかったもの: ' + ng.join(', '));
  return ok;
}

代役のオブジェクトで、200・404・200 の3つの応答を返して動かした結果です。

ログ: 取得できた件数: 2 / 取得できなかったもの: 102 (HTTP 404)

muteHttpExceptions は、リクエストごとに付けます。付けておくと、1件が 404 でも全体は止まらず、応答コードで振り分けられます。

条件 選ぶもの
呼び出す URL が1つ fetch
前の応答の内容で、次に呼ぶ URL が決まる(次のページの URL が応答に入っている、など) fetch を順に呼ぶ
呼び出す URL の一覧が先に決まっている(ID ごとの詳細、複数のページ番号) fetchAll
1件ごとに待機を挟んで再試行したい fetch(この記事の fetchWithRetry_)
まとめて取り、うまくいかなかった分だけあとで取り直したい fetchAll のあと、残りを fetch で再試行

一度に送る件数が多いと、相手の API の回数制限に当たりやすくなります。一覧を 10 件ずつなどに区切って fetchAll に渡し、429 が返ったものを取り直す形にすると、制限の範囲に収めやすくなります。

割り当て上限(公式記載の値)

Google の「Quotas for Google Services」のページに書かれている値です(2026-10-05 閲覧)。

項目 一般のアカウント Google Workspace のアカウント
URL Fetch の呼び出し回数 20,000 回/日 100,000 回/日
プロパティの読み書き 50,000 回/日 500,000 回/日
項目 上限
スクリプトの実行時間 6 分/1回の実行
カスタム関数の実行時間 30 秒/1回の実行
同時実行 30/利用者
URL Fetch の応答の大きさ 50 MB/1回の呼び出し
URL Fetch の POST の大きさ 50 MB/1回の呼び出し
URL Fetch のヘッダーの数 100/1回の呼び出し
URL Fetch のヘッダーの大きさ 8 KB/1回の呼び出し
URL Fetch の URL の長さ 2 KB/1回の呼び出し
プロパティの値の大きさ 9 KB/1つの値
プロパティの合計の大きさ 500 KB/1つのプロパティ ストア
  • 1日あたりの割り当ては利用者ごとで、最初のリクエストから 24 時間後にリセットされると書かれています。
  • 上限を超えると、スクリプトは例外を投げて実行が止まります。
  • プロパティの値は 9 KB までなので、API の応答をまるごと保存する用途には向きません。保存するのは、キーや前回の取得日時のような短い値にします。

実行時間の 6 分に収めるには、取得する件数を1回の実行で扱える量に区切り、どこまで取得したか(ページ番号や最後の ID)をスクリプト プロパティに保存して、次の実行で続きから始める形にします。

似た仕組みとの違いと選び方

仕組み 向き 向いている用途
UrlFetchApp で API を呼び出す(この記事) GAS から外へ取りに行く 外部サービスのデータを定期的にシートへ取り込む
UrlFetchApp で Webhook の URL へ POST する GAS から外へ送る チャットへの通知など、決まった宛先へ知らせを送る
ウェブアプリ(doGet・doPost) 外から GAS へ届く 外部サービスからの通知を受け取る
条件 選ぶもの
APIキーやヘッダーが必要 UrlFetchApp
取得した JSON を加工してから書き込みたい UrlFetchApp
決まった時刻に自動で取り込みたい UrlFetchApp + 時間主導型のトリガー
決まった宛先へ知らせを送りたい Webhook の URL へ POST
外部サービスからの通知を受け取りたい ウェブアプリ

確かめて分かったこと

公式のページを開いて照合し、コードを動かして分かった点です。

  1. contentType の既定値は application/x-www-form-urlencoded です。 JSON を送るつもりで payload に JSON.stringify した文字列だけを渡すと、種類の指定がフォームのままになります。contentType: 'application/json' を必ず書きます。
  2. muteHttpExceptions の既定値は false です。 付けないと、4xx や 5xx のときに例外になり、getResponseCode() まで進みません。
  3. getProperty は、キーが無いとき例外ではなく null を返します。 そのまま 'Bearer ' + key とつなぐと Bearer null という文字列が送られるので、読んだ直後に有無を確かめます(代役での実行 5)。
  4. プロパティの値は文字列になります。 数値のつもりで保存した値も、読み出すと文字列です。
  5. 型の検査では、method: 'head' と書くと、型が合わないというエラー(TS2322)になりました。 型定義が受け付けるのは get・delete・patch・post・put で、公式の表に書かれている5種類と一致します。
  6. 項目の欠けた JSON をそのまま行にすると、行ごとに列数が変わります。 全行のキーを集めて見出しを作る形にすると、3件目だけにある owner.dept も含めて 7 列にそろいました(代役での実行 1)。

よくある質問

Q. UrlFetchApp とは何ですか? A. GAS から HTTP と HTTPS のリクエストを送り、応答を受け取るためのサービスです。UrlFetchApp.fetch(url, params) が基本で、戻り値の HTTPResponse から応答コードと本文を取り出します。

Q. スクリプト プロパティとユーザー プロパティの違いは何ですか? A. スクリプト プロパティはそのスクリプトのすべての利用者が読める保存場所、ユーザー プロパティは実行している利用者だけが読める保存場所です。共有の APIキーは前者、利用者ごとのキーは後者に入れます。

Q. API からエラーが返ったとき、内容を確認できないときはどうしますか? A. muteHttpExceptions: true を付けて、getResponseCode() と getContentText() をログに出します。多くの API は、本文に原因を示す JSON を入れて返します。

Q. 取得した JSON をシートに書き込めないときは何を確かめますか? A. 範囲の行数・列数と、2次元配列の行数・列数が一致しているかを確かめます。getRange(1, 1, table.length, table[0].length) のように、配列の大きさから範囲を作ると一致します。

Q. fetch と fetchAll の違いは何ですか? A. fetch は1つのリクエストを送って1つの HTTPResponse を返し、fetchAll はリクエストの配列を送って HTTPResponse の配列を返します。URL の一覧が先に決まっているときは fetchAll が向いています。

まとめ

  • APIキーはスクリプト プロパティに保存し、getProperty で読んだ直後に有無を確かめる
  • fetch には muteHttpExceptions: true を付け、getResponseCode() で分岐する
  • 再試行は 429 と 5xx だけ。Retry-After があれば従い、無ければ待ち時間を倍に延ばす
  • JSON の POST は contentType: 'application/json' と JSON.stringify をそろえる
  • 入れ子の JSON は「親.子」の列名に平らにし、全行の列数をそろえてから setValues を1回呼ぶ
  • URL の一覧が先に決まっていれば fetchAll、前の応答で次が決まるなら fetch
  • URL Fetch は一般のアカウントで 20,000 回/日、実行時間は 6 分/回。件数を区切り、続きの位置をプロパティに保存する

参考・出典

いずれも 2026-10-05 に閲覧しました。

  • Google Apps Script リファレンス「Class UrlFetchApp」 https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app
  • Google Apps Script リファレンス「Class HTTPResponse」 https://developers.google.com/apps-script/reference/url-fetch/http-response
  • Google Apps Script ガイド「Properties Service」 https://developers.google.com/apps-script/guides/properties
  • Google Apps Script リファレンス「Class PropertiesService」 https://developers.google.com/apps-script/reference/properties/properties-service
  • Google Apps Script リファレンス「Class Properties」 https://developers.google.com/apps-script/reference/properties/properties
  • Google Apps Script ガイド「Quotas for Google Services」 https://developers.google.com/apps-script/guides/services/quotas
  • npm「@types/google-apps-script」(型の検査に使用した型定義) https://www.npmjs.com/package/@types/google-apps-script

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「GASで外部APIを呼び出す UrlFetchAppとAPIキーの保存方法」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?