So integrieren Sie die Google Calendar API in Ihre App
Inhaltsverzeichnis
Alle Kalender über eine einzige API integrieren
Trage dich in die Warteliste unserer Unified Calendar API ein, um Zugriff auf unsere Unified Calendar API zu erhalten, mit der du alle Kalenderanbieter über eine einzige API in deine App integrieren kannst.
In diesem Leitfaden erklären wir ausführlich, wie Sie die Google-Calendar-API in Ihre App integrieren. Dazu gehören die Einrichtung eines Google-Cloud-Projekts, die benötigten Scopes, Stolperfallen sowie ein Praxisbeispiel für den Autorisierungsablauf.
Voraussetzungen
Sie benötigen eine E-Mail-Adresse, eine vorhandene Domain für die Einrichtung des Google-Cloud-Projekts, grundlegende Programmierkenntnisse und eine halbwegs klare Vorstellung davon, was Sie bauen möchten.
Dieser Leitfaden ist auch hilfreich, wenn Sie noch nie mit der Google-Calendar-API gearbeitet haben und alle notwendigen Schritte kennenlernen wollen, um sie in Ihre App zu integrieren.
So nutzen und integrieren Sie die Google-Calendar-API in Ihre App
1. Registrieren Sie sich in der Google Developer Console
Falls Sie noch kein Konto in der Google Developer Console haben, erstellen Sie eines unter https://console.cloud.google.com/.
2. Erstellen Sie ein neues oder wählen Sie ein bestehendes Google-Cloud-Projekt
Google Cloud erlaubt Entwickler- und Organisationskonten mehrere Projekte. Vergewissern Sie sich, dass Sie sich beim folgenden Vorgehen im richtigen Projekt befinden.
Klicken Sie oben links auf den Projekt-Drop-down. Der Name entspricht üblicherweise dem Projektnamen.
Wählen Sie ein bestehendes Projekt oder klicken Sie auf „Neues Projekt“ oben rechts im Dialog, um ein neues anzulegen.
3. Aktivieren Sie die Google-Calendar-API-Dienste
Nachdem Sie ein Konto erstellt und das richtige Projekt ausgewählt haben, aktivieren Sie die Google-Calendar-API:
Öffnen Sie die Google Cloud Console
Klicken Sie auf „APIs & Dienste“
Klicken Sie auf „APIs und Dienste aktivieren“
Suchen Sie nach „Google Calendar API“
Klicken Sie auf „Aktivieren“, um den Dienst freizuschalten.
4. Richten Sie den OAuth-Zustimmungsbildschirm ein
Nach dem Aktivieren der API-Dienste ist der nächste Schritt das Einrichten des OAuth-Zustimmungsbildschirms. Dies ist die Oberfläche, die Endnutzer sehen, wenn sie ihren Kalender mit Ihrer App verbinden. Dort erscheinen u. a. Ihr App-Logo, -Name und die angeforderten Berechtigungen.
Klicken Sie auf den Tab „OAuth-Zustimmungsbildschirm“.
Klicken Sie auf „Los geht’s“.
Füllen Sie den Abschnitt „App-Informationen“ aus. Geben Sie Ihren App-Namen und eine Support-E-Mail-Adresse an.
Wählen Sie die Zielgruppe. Intern, wenn die App nicht öffentlich ist und nur Personen Ihrer Organisation sich verbinden dürfen, oder extern, wenn beliebige Google-Konten zugreifen sollen.
Geben Sie Ihre Kontaktinformationen an. Google informiert Sie bei Änderungen am Projekt.
Aktivieren Sie das Kontrollkästchen „Google API Services: User Data Policy akzeptieren“.
Klicken Sie auf „Erstellen“.
5. Erstellen Sie Ihren OAuth-Client
Nach dem Zustimmungsbildschirm können Sie nun den OAuth-Client anlegen. Klicken Sie unter „Clients“ auf „Client erstellen“ oder alternativ auf „OAuth-Client erstellen“ in der Übersicht.
Für jede Plattform (z. B. Web- oder iOS-App) brauchen Sie eine eigene Client-ID.
In diesem Beispiel erstellen wir einen „Webanwendung“-Client namens „Web Client“.
Hier tragen wir auch die autorisierten JavaScript-Ursprünge und Redirect-URIs ein.
Bei Autorisierten JavaScript-Ursprüngen geben Sie die Domain/URL Ihrer Web-App an, z. B. https://myapp.domain.com
.
Unter Autorisierte Redirect-URIs tragen Sie alle URLs ein, zu denen Nutzer nach der Authentifizierung zurückgeleitet werden sollen (inklusive Protokoll).
Vergessen Sie nicht, auch Ihre localhost-Redirect-URLs zu whitelisten, falls die App in der Entwicklung genutzt wird.
Nach dem Ausfüllen klicken Sie auf „Erstellen“. Google zeigt ein Dialogfenster mit Client-ID und Client-Secret an. Kopieren Sie beide und speichern Sie sie sicher (z. B. in Ihrer .env
-Datei oder einem Passwortmanager).
Sichern Sie die Daten jetzt, denn nach Schließen des Dialogs können Sie das Client-Secret nicht mehr anzeigen.
6. Fügen Sie Testnutzer hinzu
Während der lokalen Entwicklung können sich nur freigegebene Testnutzer verbinden, da Ihre noch nicht verifizierte App extern ist.
Klicken Sie auf den Tab „Zielgruppe“.
Scrollen Sie zum Abschnitt „Testnutzer“.
Klicken Sie auf „Nutzer hinzufügen“ und tragen Sie die E-Mail-Adresse ein.
7. Fügen Sie die benötigten Kalender-Scopes hinzu
Welche Scopes (Berechtigungen) Sie anfordern, hängt von Ihrem Anwendungsfall ab. Beispiele sind das Auflisten von Kalendern oder das Anzeigen von Events.
Google unterscheidet zwischen sensiblen und nicht sensiblen Scopes. Bei sensiblen Scopes muss Ihre App verifiziert werden (auch nachträglich, falls Sie weitere hinzufügen).
Geben Sie für jeden Scope eine Begründung und ein Demo-Video an – beides ist für die Verifizierung erforderlich.
Klicken Sie auf den Tab „Datenzugriff“.
Klicken Sie auf „Scopes hinzufügen oder entfernen“.
Suchen und wählen Sie den gewünschten Scope aus.
8. Machen Sie sich mit der Google-Calendar-API vertraut
Nachdem der Client steht, empfiehlt es sich, die Übersichtsseite der Google-Calendar-API und wichtige Endpunkte wie Events oder Calendars durchzugehen.
9. Nutzen Sie eine Unified Calendar API, um mehrere Anbieter über eine Schnittstelle einzubinden
Wenn Sie ausschließlich Google Calendar integrieren, können Sie diesen Schritt überspringen. Andernfalls empfehlen wir eine Unified Calendar API, die alle großen Kalenderanbieter über eine einzige API abdeckt.
So brauchen Sie nur eine Integration und ersparen sich zusätzlichen Wartungsaufwand, falls Sie später z. B. Outlook unterstützen wollen.
Beispiel für einen Google-Calendar-Autorisierungsablauf
Die folgende Grafik zeigt einen einfachen OAuth-Flow, mit dem Nutzer ihren Google Calendar verbinden können.
Google stellt Clients für Node.js, Python usw. bereit. Zur Veranschaulichung nutzen wir jedoch nur HTTP-Aufrufe und TypeScript.
Client-Seite (UI)
Im Frontend zeigen wir einen Button „Google Calendar verbinden“:
const googleOauthUrl = getGoogleOAuthUrl()
<button href="googleOauthUrl" rel="noopener noreferrer">Google Calendar verbinden</button>
Wir empfehlen eine Hilfsfunktion getGoogleOAuthUrl
, um Lesbarkeit und Parametrisierung (State, Scopes usw.) zu verbessern.
const SCOPES = [
"openid",
"email",
"https://www.googleapis.com/auth/calendar.calendarlist",
"https://www.googleapis.com/auth/calendar.events",
"https://www.googleapis.com/auth/calendar.readonly",
// weitere Scopes nach Bedarf
];
export interface ClientState {
session: Session;
returnUrl?: string;
}
export function stateToB64(session: ClientState): string {
return encode(JSON.stringify(session));
}
export function getGoogleOAuthUrl(
state: ClientState,
) {
const params = new URLSearchParams({
client_id: process.env.GOOGLE_CLIENT_ID || "",
redirect_uri: `${getHostName()}/api/connect/google`,
response_type: "code",
scope: SCOPES.join(" "),
prompt: "consent",
access_type: "offline",
state: stateToB64(state),
});
return `https://accounts.google.com/o/oauth2/v2/auth?${params}`;
}
prompt akzeptiert
none
,consent
oderselect_account
.consent
: den Autorisierungsdialog erneut erzwingen (z. B. bei neuen Scopes).select_account
: den Nutzer auffordern, ein Konto auszuwählen.none
: keinen Dialog anzeigen.
API-Seite (Backend)
Hier verarbeiten wir den zurückgegebenen Code und tauschen ihn gegen Tokens.
import { z } from "zod";
const successSchema = z.object({
code: z.string(),
scope: z.string(),
state: z.string(),
});
const errorSchema = z.object({
error: z.string(),
});
type ErrorParams = z.infer<typeof errorSchema>;
const querySchema = z.union([successSchema, errorSchema]);
// Handler const googleHanlder: NextApiHandler = async (req, res) => {
try {
const result = querySchema.parse(req.query);
if (isError(result)) {
const q = new URLSearchParams({ error: "ACCESS_DENIED" });
return res.redirect(`/?${q}`);
}
const { session, returnUr } = stateFromB64(result.state);
if (!hasRequiredScopes(result.scope)) {
const q = new URLSearchParams({ error: "MISSING_REQUIRED_PERMISSIONS" });
return res.redirect(`/?${q}`);
}
const { access_token, refresh_token, id_token, expires_in } =
await exchangeCodeForTokens(result.code);
const { email } = decodeIdToken(id_token);
const connection = await upsertConnection(
{
email,
accessToken: access_token,
refreshToken: refresh_token,
expiresInSeconds: expires_in,
status: ConnectionStatus.ACTIVE,
provider: CalendarProvider.GOOGLE,
scopes: result.scope,
reminderCount: 0,
lastRemindedAt: null,
},
session.user
);
const q = new URLSearchParams({ cid: connection.id });
if (returnUrl) q.append("returnUrl", returnUrl);
res.redirect(returnUrl ? returnUrl : `/calendars/google?${q}`);
} catch (e: any) {
let error = JSON.stringify(e);
const querystr =
typeof req.query === "string" ? req.query : JSON.stringify(req.query);
console.error("Fehler im googleHandler", querystr);
console.error("Google-Konto konnte nicht verbunden werden", e);
const q = new URLSearchParams({ error });
return res.redirect(`/?${q}`);
}
};
Hilfsfunktionen wie exchangeCodeForTokens
, decodeIdToken
usw.:
export async function exchangeCodeForTokens(code: string) {
const data = new FormData();
data.append("code", code);
data.append("client_id", process.env.GOOGLE_CLIENT_ID || "");
data.append("client_secret", process.env.GOOGLE_CLIENT_SECRET || "");
data.append("redirect_uri", `${getHostName()}/api/connect/google`);
data.append("grant_type", "authorization_code");
try {
const result = await fetch("https://oauth2.googleapis.com/token", {
method: "POST",
body: data,
});
const json = await result.json();
if (json.error) throw json;
const parsed = responseSchema.parse(json);
return parsed;
} catch (e) {
console.error("Token-Austausch fehlgeschlagen");
throw e;
}
}
export function decodeIdToken(idToken: string) {
const data = jwt.decode(idToken);
if (typeof data === "string" || !data?.email) {
throw new Error(`id_token konnte nicht geparst werden: ${idToken}`);
}
return data;
}
function isError(query: Record<string, any>): query is ErrorParams {
return Boolean(query.error);
}
export function stateFromB64(encoded: string): ClientState {
const str = decode(encoded);
return JSON.parse(str) as ClientState;
}
process.env.GOOGLE_CLIENT_ID und process.env.GOOGLE_CLIENT_SECRET stammen aus Schritt 5. Kopieren Sie sie sofort, da das Secret später nicht mehr sichtbar ist.
Stolperfallen bei der Google-Calendar-API-Integration
Verifizierung dauert Wochen – planen Sie den Launch entsprechend und rechnen Sie mit möglichen Ablehnungen.
Webhooks laufen nach ca. 24 Stunden ab – erneuern Sie sie rechtzeitig, z. B. per Cron-Job.
Fordern Sie nur notwendige Scopes an – zu viele Scopes verzögern die Verifizierung und schrecken Nutzer ab.
Berücksichtigen Sie Quoten und Ratenlimits – bei Überschreitung erhalten Sie 403
usageLimits
oder 429rateLimitExceeded
. Nutzen Sie Exponential Back-off.Keine personenbezogenen Daten loggen – Eventbeschreibungen enthalten oft sensible Informationen.
Mehrere Kalenderanbieter integrieren mit der OneCal Unified Calendar API
OneCal hat bereits Millionen Kalender-Events zwischen Google Calendar, Outlook und iCloud synchronisiert. Mit unserer Unified Calendar API können Sie alle großen Anbieter über eine einzige robuste Schnittstelle anbinden.
Treten Sie der Warteliste zur Unified Calendar API bei, um bei Launch benachrichtigt zu werden.