アプリとつなぐ

SDK の使用例

TypeScript、Python、Go、Java、C# の公式 Google Calendar クライアントの接続先を Calendarpit に変更します。

アプリの公式 Google Calendar SDK クライアントの接続先を Calendarpit に変更します。Calendarpit 専用の SDK は不要です。

以下の例では、カレンダーの一覧を取得し、FreeBusy を照会します。

SDK を呼び出す前に

先にアクセストークンと SDK パッケージを用意します。

  1. Calendarpit を起動します(例: calendarpit serve)。詳しくは起動と設定を参照してください。
  2. https://www.googleapis.com/auth/calendar スコープでローカル OAuth フローを完了します。リフレッシュトークンが必要な場合は access_type=offline を追加します。
  3. 取得したアクセストークンを、シェルの CALENDARPIT_ACCESS_TOKEN に設定します。トークンの有効期間は 1 時間です。
  4. 各タブに記載したパッケージをプロジェクトにインストールします。Calendarpit は言語ランタイムや SDK パッケージをインストールしません。

CALENDARPIT_ACCESS_TOKEN は各例のコードが明示的に読み取る変数です。Google SDK の設定ではありません。

これらのコードは、既存のアクセストークンを渡します。Calendar API リクエストを Calendarpit に送る方法を示すためのものです。

  • 認可のコールバックやトークンの自動更新は扱いません。
  • トークンは POST /oauth/token で更新します。そのうえで、クライアントのトークンを差し替えるか、クライアントを作り直してください。

サンプルアプリと OAuth クライアントの設定全体はアプリを接続するを参照してください。

サービス URL を設定する

エンドポイントの指定形式はライブラリごとに異なります。

  • 末尾のスラッシュは表のとおりに付けてください。
  • Calendarpit を別のホストやポートで実行している場合は、すべての値の 127.0.0.1:4173 を置き換えます。
言語SDK の設定値
TypeScript / JavaScriptrootUrlhttp://127.0.0.1:4173/
Pythonclient_options.api_endpointhttp://127.0.0.1:4173/calendar/v3/
Gooption.WithEndpointhttp://127.0.0.1:4173/calendar/v3/
JavasetRootUrl + setServicePathhttp://127.0.0.1:4173/ + calendar/v3/
C# / .NETBaseClientService.Initializer.BaseUrihttp://127.0.0.1:4173/calendar/v3/

どの FreeBusy の例も、Calendarpit に POST /calendar/v3/freeBusy を送信します。同じクライアントで呼び出すイベントの CRUD やカレンダーリストの操作も、このローカル URL に送られます。

calendarList では、list・get・insert・patch・update・delete・watch に対応しています。ただし、Calendar API の互換性に記載した単一オーナーの制限があります。

SDK にほかのメソッドがあっても、対応しているのはCalendar API の互換性に記載した操作だけです。

カレンダーを一覧表示して FreeBusy を照会する

  • パッケージ: @googleapis/calendar と google-auth-library
  • ランタイム: Bun、または Node.js 22 以降で ES モジュール(.mjs)として実行します。
  • 一体型パッケージ: googleapis でも google.calendar({ version: 'v3', auth, rootUrl }) を使えます。
import { calendar } from '@googleapis/calendar';
import { OAuth2Client } from 'google-auth-library';

const token = process.env.CALENDARPIT_ACCESS_TOKEN;
if (!token) throw new Error('Set CALENDARPIT_ACCESS_TOKEN first.');

const auth = new OAuth2Client();
auth.setCredentials({ access_token: token });
const api = calendar({
  version: 'v3',
  auth,
  rootUrl: 'http://127.0.0.1:4173/',
});

const calendars = await api.calendarList.list();
console.log(calendars.data.items);

const { data } = await api.freebusy.query({
  requestBody: {
    timeMin: '2026-10-19T00:00:00+09:00',
    timeMax: '2026-10-20T00:00:00+09:00',
    timeZone: 'Asia/Tokyo',
    items: [{ id: 'primary' }],
  },
});
console.log(data.calendars?.primary?.busy ?? []);

アクセストークンだけを渡したこのクライアントは、トークンを更新できません。OAuth をすべて設定する場合は、アプリを接続するにあるローカルの endpoints 設定を使ってください。

参考: Google Calendar Node.js クライアントの実装

  • パッケージ: google-api-python-client(2.x)と google-auth
  • ディスカバリ: static_discovery=True を指定すると、インストール済みのライブラリに同梱されたディスカバリドキュメントを使います。そのため、クライアントの作成時に Google からディスカバリ情報を取得しません。
  • エンドポイント: api_endpoint には /calendar/v3/ のパスを含めます。
import os

from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build

credentials = Credentials(token=os.environ["CALENDARPIT_ACCESS_TOKEN"])
with build(
    "calendar",
    "v3",
    credentials=credentials,
    static_discovery=True,
    cache_discovery=False,
    client_options={
        "api_endpoint": "http://127.0.0.1:4173/calendar/v3/",
    },
) as api:
    print(api.calendarList().list().execute().get("items", []))
    result = api.freebusy().query(body={
        "timeMin": "2026-10-19T00:00:00+09:00",
        "timeMax": "2026-10-20T00:00:00+09:00",
        "timeZone": "Asia/Tokyo",
        "items": [{"id": "primary"}],
    }).execute()
    print(result["calendars"]["primary"]["busy"])

Credentials にリフレッシュトークンを渡す場合は、次のようにします。

  • 登録済みのクライアント ID、クライアントシークレット、token_uri="http://127.0.0.1:4173/oauth/token" も指定します。
  • scopes は省略するか、許可されたスコープを同じ順序でそのまま渡してください。

認可、userinfo、取り消しの URL は、アプリのOAuth フローで別に設定します。

参考: 同梱のディスカバリドキュメント、エンドポイントの選択

  • モジュール: google.golang.org/api と golang.org/x/oauth2
  • 認証情報: トークンソースを明示的に渡します。こうすると、クライアントが Google の Application Default Credentials を探しません。
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"golang.org/x/oauth2"
	"google.golang.org/api/calendar/v3"
	"google.golang.org/api/option"
)

func main() {
	token := os.Getenv("CALENDARPIT_ACCESS_TOKEN")
	if token == "" {
		log.Fatal("Set CALENDARPIT_ACCESS_TOKEN first.")
	}
	api, err := calendar.NewService(context.Background(),
		option.WithEndpoint("http://127.0.0.1:4173/calendar/v3/"),
		option.WithTokenSource(oauth2.StaticTokenSource(&oauth2.Token{
			AccessToken: token,
			TokenType:   "Bearer",
		})),
	)
	if err != nil {
		log.Fatal(err)
	}

	calendars, err := api.CalendarList.List().Do()
	if err != nil {
		log.Fatal(err)
	}
	for _, c := range calendars.Items {
		fmt.Println(c.Id)
	}

	result, err := api.Freebusy.Query(&calendar.FreeBusyRequest{
		TimeMin:  "2026-10-19T00:00:00+09:00",
		TimeMax:  "2026-10-20T00:00:00+09:00",
		TimeZone: "Asia/Tokyo",
		Items:    []*calendar.FreeBusyRequestItem{{Id: "primary"}},
	}).Do()
	if err != nil {
		log.Fatal(err)
	}
	for _, b := range result.Calendars["primary"].Busy {
		fmt.Println(b.Start, "-", b.End)
	}
}

StaticTokenSource はトークンを更新しません。SDK に OAuth を管理させる場合は、次のようにします。

  1. oauth2.Config.Endpoint.AuthURL と TokenURL に Calendarpit の OAuth エンドポイントを設定します。
  2. config.TokenSource(ctx, token) を渡します。

参考: Calendar クライアント、WithEndpoint、OAuth の設定

  • アーティファクト: com.google.apis:google-api-services-calendar、com.google.http-client:google-http-client、com.google.http-client:google-http-client-gson
  • Java のバージョン: この例は Java 11 以降を前提にしています。
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.util.DateTime;
import com.google.api.services.calendar.Calendar;
import com.google.api.services.calendar.model.FreeBusyRequest;
import com.google.api.services.calendar.model.FreeBusyRequestItem;
import java.util.List;

public class CalendarpitExample {
    public static void main(String[] args) throws Exception {
        String token = System.getenv("CALENDARPIT_ACCESS_TOKEN");
        if (token == null || token.isBlank()) {
            throw new IllegalStateException("Set CALENDARPIT_ACCESS_TOKEN first.");
        }
        Calendar api = new Calendar.Builder(
            new NetHttpTransport(),
            GsonFactory.getDefaultInstance(),
            request -> request.getHeaders().setAuthorization("Bearer " + token)
        )
            .setRootUrl("http://127.0.0.1:4173/")
            .setServicePath("calendar/v3/")
            .setApplicationName("Calendarpit local example")
            .build();

        System.out.println(api.calendarList().list().execute().getItems());
        FreeBusyRequest body = new FreeBusyRequest()
            .setTimeMin(new DateTime("2026-10-19T00:00:00+09:00"))
            .setTimeMax(new DateTime("2026-10-20T00:00:00+09:00"))
            .setTimeZone("Asia/Tokyo")
            .setItems(List.of(new FreeBusyRequestItem().setId("primary")));
        var result = api.freebusy().query(body).execute();
        System.out.println(result.getCalendars().get("primary").getBusy());
    }
}

リクエストイニシャライザーで Bearer トークンのヘッダーを直接設定しています。トークンの取得と更新にはローカル OAuth エンドポイントを使ってください。

setRootUrl を設定しても、Google の認可用ヘルパーの接続先は変わりません。

参考: Calendar ビルダー、FreeBusy リクエスト

  • NuGet パッケージ: Google.Apis.Calendar.v3 と Google.Apis.Auth
  • プロジェクトの種類: トップレベルステートメントを使うコンソールアプリケーション
using System;
using System.Collections.Generic;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Calendar.v3;
using Google.Apis.Calendar.v3.Data;
using Google.Apis.Services;

var token = Environment.GetEnvironmentVariable("CALENDARPIT_ACCESS_TOKEN");
if (string.IsNullOrWhiteSpace(token))
    throw new InvalidOperationException("Set CALENDARPIT_ACCESS_TOKEN first.");

using var api = new CalendarService(new BaseClientService.Initializer
{
    BaseUri = "http://127.0.0.1:4173/calendar/v3/",
    HttpClientInitializer = GoogleCredential.FromAccessToken(token),
    ApplicationName = "Calendarpit local example",
});

var calendars = await api.CalendarList.List().ExecuteAsync();
foreach (var calendar in calendars.Items)
    Console.WriteLine(calendar.Id);

var result = await api.Freebusy.Query(new FreeBusyRequest
{
    TimeMinRaw = "2026-10-19T00:00:00+09:00",
    TimeMaxRaw = "2026-10-20T00:00:00+09:00",
    TimeZone = "Asia/Tokyo",
    Items = new List<FreeBusyRequestItem>
    {
        new FreeBusyRequestItem { Id = "primary" },
    },
}).ExecuteAsync();

foreach (var interval in result.Calendars["primary"].Busy)
    Console.WriteLine($"{interval.StartRaw} - {interval.EndRaw}");

FromAccessToken はトークンを更新しません。ローカルのトークンエンドポイントで更新し、認証情報を作り直してください。

BaseUri が変えるのは Calendar API リクエストの接続先だけです。OAuth ヘルパーの接続先は変わりません。

参考: サービスのベース URI、アクセストークンによる認証情報、FreeBusy リクエスト

同じ HTTP エンドポイントは、どの言語からでも直接呼び出せます。

curl --fail-with-body http://127.0.0.1:4173/calendar/v3/users/me/calendarList \
  -H "Authorization: Bearer $CALENDARPIT_ACCESS_TOKEN"

curl --fail-with-body http://127.0.0.1:4173/calendar/v3/freeBusy \
  -H "Authorization: Bearer $CALENDARPIT_ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{
    "timeMin": "2026-10-19T00:00:00+09:00",
    "timeMax": "2026-10-20T00:00:00+09:00",
    "timeZone": "Asia/Tokyo",
    "items": [{"id": "primary"}]
  }'

期待される結果

primary は、認証済みのテストユーザーのプライマリカレンダーを指します。

デフォルトの Fixture の Alex の場合、この照会では busy 区間が 1 件返ります。Asia/Tokyo で 2026 年 10 月 19 日 10:00 から 11:00 までの区間です。

管理画面でイベントを編集すると、次の FreeBusy の応答に反映されます。transparent のイベントとキャンセル済みのイベントは、busy 区間に含まれません。

検証状況

自動化された E2E テストの対象は、アプリを接続するで説明している Bun/TypeScript のサンプルアプリだけです。

このページの例は、TypeScript の例も含めて公式クライアントの API をもとに書いたものです。このリポジトリの CI ではコンパイルも実行もしていません。

設定やリクエストでよくあるエラーについては、トラブルシューティングを参照してください。

目次