Come integrare Outlook Calendar API nella tua app
Pubblicato il
Nel nostro articolo precedente su come integrare l’API di Google Calendar nella tua applicazione, abbiamo mostrato passo dopo passo cosa deve fare uno sviluppatore per collegare Google Calendar alla propria app.
In questo articolo facciamo lo stesso con l’API di Outlook Calendar. Vedremo la registrazione dell’app su Azure, gli scope, la verifica, le insidie più comuni dell’integrazione e alcuni esempi di codice reali.
Prerequisiti
Questa guida presuppone che tu abbia già un account Microsoft Work o Developer con accesso ad Azure Active Directory (oggi chiamato Microsoft Entra ID).
Tieni presente che non è più possibile creare applicazioni al di fuori di una directory. Se non ne hai ancora una, aderisci al Microsoft 365 Developer Program o iscriviti ad Azure.
Come usare e integrare l’API di Outlook Calendar nella tua app
Passaggio 1: Accedi al Portale di Microsoft Azure
Apri la pagina di accesso al Portale di Microsoft Azure ed effettua l’accesso con il tuo account.
La pagina del Portale di Microsoft Azure.
Passaggio 2: Registra una nuova applicazione
Dopo aver effettuato l’accesso al Portale di Microsoft Azure:
- Vai su Azure Active Directory

- Cerca “App Registrations” nella barra di ricerca

- Clicca su “App Registrations”

- Clicca su “New registration”

- Compila i campi richiesti:
- Il primo campo è il Nome dell’applicazione. È il nome che gli utenti vedranno nella schermata di consenso.
- Poi seleziona i tipi di account supportati. La scelta giusta dipende dal tipo di applicazione che stai sviluppando (uso interno o multi-tenant). Per questo esempio selezionerò “ Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) ”, perché permette agli utenti di qualsiasi organizzazione (compresi gli utenti Outlook.com) di usare la mia app. È l’opzione migliore per i prodotti SaaS e le altre applicazioni multi-tenant.
- Inserisci l’URI di reindirizzamento: questo campo è opzionale, perché non tutti i tipi di applicazione ne hanno bisogno. Se stai sviluppando una web app, molto probabilmente ti servirà, perché questo URI è dove Azure invia le risposte OAuth. Nel menu “Select a platform” scegli Web, quindi compila il campo Redirect URI (per esempio,
https://yourapp.com/auth/callback). Per un flusso di autenticazione lato server, un URI web è la scelta giusta. Assicurati che il dominio inserito sia raggiungibile e sotto il tuo controllo. - Clicca su “Register”.
- Dopo il clic su “Register”, Azure Active Directory crea la tua applicazione e ti porta alla pagina di panoramica, dove puoi copiare Client ID e Tenant ID. L’ Application (client) ID è un GUID che identifica la tua app. Il Directory (tenant) ID non è sempre necessario. Per le app multi-tenant di solito si usa l’endpoint
common, ma il tenant ID è comodo per fare test nel tuo tenant.
Passaggio 3: Configura le autorizzazioni API
Una volta registrata l’app, è il momento di configurare i permessi del calendario. Questi permessi vengono mostrati durante il flusso OAuth, così l’utente vede quali scope richiede la tua app prima di concedere l’accesso ai propri calendari.
Per impostazione predefinita, la tua app riceve solo il permesso “User.Read”. Se ti serve soltanto far accedere l’utente e leggere il suo profilo, puoi saltare questo passaggio.
Per aggiungere permessi API, segui questi passaggi:
- Clicca sulla scheda “Manage” nella barra laterale sinistra.
- Clicca su “API Permissions”.

- Clicca sul pulsante “+ Add a permission”.

- Trova la scheda “Microsoft Graph” (di solito è la prima nel pannello che si apre a destra dopo il clic su “Add a permission”).

- Scegli tra “Delegated permissions” e “Application permissions”. Le autorizzazioni delegate sono la scelta giusta quando la tua app chiama l’API per conto dell’utente connesso. Le application permissions, invece, servono quando l’applicazione gira come servizio in background senza un utente connesso. Per questo esempio userò “Delegated Permissions”.

- Cerca “Calendars”: la ricerca mostra tutti i permessi relativi al calendario. Seleziona solo quelli di cui la tua app ha davvero bisogno. Nella maggior parte dei casi ti serviranno “Calendars.ReadWrite” e “Calendars.ReadWrite.Shared” (se ti serve l’accesso ai calendari condivisi). Gli scope del calendario di solito non richiedono il consenso dell’amministratore, perché sono delegati all’utente, ma ricorda che alcune organizzazioni limitano il consenso degli utenti. Se un utente di un tenant esterno non può dare il consenso, un amministratore di quel tenant dovrà concederlo per la tua app (di solito tramite un prompt o un URL di consenso amministratore).

Passaggio 4: Abilitare i token ID
Non tutte le app hanno bisogno di questo passaggio, ma se vuoi accedere alle informazioni del profilo utente, come nome, e-mail o URL dell’immagine del profilo, devi abilitare l’opzione Token ID in Gestisci -> Autenticazione.
Con i token ID la tua app può identificare l’utente subito dopo che ha collegato il calendario, senza una chiamata API aggiuntiva.
Passaggio 5: Genera un Client Secret
Consigliamo di eseguire tutte le operazioni di calendario (lettura, scrittura, aggiornamento, ecc.) dal server. Per questo è necessario generare un client secret.
Per generare un Client Secret, segui questi passaggi:
- Clicca sulla scheda “Certificates & secrets”

- Clicca su “New client secret”

- Inserisci una descrizione e una data di scadenza

Dopo aver generato il client secret, copialo subito e conservalo in un luogo sicuro (di solito nel tuo file .env).
Passaggio 6: Branding e Verifica
Nella sezione Branding & Properties della registrazione dell’app puoi impostare un logo e altre informazioni (descrizione, URL dei termini di servizio, ecc.). È facoltativo, ma lo consigliamo per una schermata di consenso più curata. È importante impostare un Publisher Domain (di solito il tuo dominio personalizzato, verificato in Azure AD), perché evita che l’app venga mostrata come “non verificata” quando gli utenti concedono il consenso. Per le app multi-tenant, Microsoft ora si aspetta che le app siano publisher-verified per un uso esteso. Se la tua app non è verificata dal publisher, gli utenti esterni al tuo tenant potrebbero non riuscire a dare il consenso a causa delle politiche di sicurezza introdotte a novembre 2020.
Passaggio 7: Familiarizza con l’Outlook Graph API
Con l’applicazione configurata, è il momento di esplorare la Microsoft Calendar Graph API per prendere confidenza con gli endpoint per creare, aggiornare e cancellare eventi.
Passaggio 8: Valuta l’uso di un servizio di API Calendario Unificata per integrare tutti i provider con un’unica API
La Microsoft Graph API è abbastanza ben documentata, ma consigliamo comunque di dare un’occhiata a una API Calendario Unificata che ti permette di integrare tutti i provider di calendario tramite un’unica API.
Con una API Calendario Unificata implementi una sola API nella tua applicazione e supporti tutti i provider di calendario, indipendentemente dalle loro limitazioni o dalle differenze tra le API.
Un altro vantaggio di un’unica API per tutti i calendari è che non devi mantenere più integrazioni, occuparti di breaking change o gestire casi limite a cui non avevi mai pensato.
La Apiroc Unified Calendar API
Esempio di flusso di autorizzazione per Outlook Calendar
Il diagramma di flusso qui sotto mostra un semplice flusso OAuth di Outlook Calendar con cui gli utenti collegano il loro calendario Outlook alla tua app.
Consulta la pagina di documentazione sul flusso OAuth2 di Microsoft se vuoi saperne di più sul flusso OAuth2 di Microsoft.
Lato client (UI)
const microsoftOauthUrl = getMicrosoftOAuthUrl()
<button href="microsoftOauthUrl" rel="noopener noreferrer"> Connect Outlook Calendar </button>
export const SCOPES = [
"openid",
"email",
"profile",
"offline_access",
"Calendars.ReadWrite",
"User.Read",
];
export interface ClientState {
session: Session;
returnUrl?: string;
}
export function stateToB64(session: ClientState): string {
return encode(JSON.stringify(session));
}
export function getMicrosoftOAuthUrl(
state: ClientState,
) {
const nonce = uuid();
const TENANT_ID = process.env.NEXT_PUBLIC_MICROSOFT_TENANT_ID;
const params = new URLSearchParams({
client_id: process.env.MICROSOFT_CLIENT_ID || "",
redirect_uri: `${getHostName()}/api/connect/microsoft`,
response_type: "code id_token",
scope: SCOPES.join(" "),
prompt: "consent",
response_mode: "form_post",
state: stateToB64(state),
nonce,
});
return `https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/authorize?${params}`;
}
- Il parametro “prompt” accetta uno di questi quattro valori:
login,none,consenteselect_account. - Il parametro “response_mode” accetta
query,fragmentoform_post. Abbiamo sceltoform_postperché indica a Microsoft di inviare una richiesta POST al nostro redirect URI (sul server).
Lato API (Backend)
Ora costruiamo l’handler API. Riceve il code e gli scope dal server Microsoft e li scambia con i token.
In questo esempio usiamo zod per la validazione.
const successSchema = z.object({
code: z.string(),
state: z.string(),
id_token: z.string(),
session_state: z.string().optional(),
});
const errorSchema = z.object({
error: z.string(),
error_description: z.string().optional(),
});
type ErrorParams = z.infer<typeof errorSchema>;
const querySchema = z.union([successSchema, errorSchema]);
function isError(query: Record<string, any>): query is ErrorParams {
return Boolean(query.error);
}
const microsoftHandler: NextApiHandler = async (req, res) => {
try {
const result = querySchema.parse(req.body);
if (isError(result)) {
const q = new URLSearchParams({
error: "ACCESS_DENIED",
provider: CalendarProvider.MICROSOFT,
});
console.error({ result });
return res.redirect(302, `/?${q}`);
}
const { session, returnUrl } = stateFromB64(result.state);
const { email } = decodeIdToken(result.id_token);
const { access_token, refresh_token, expires_in, scope } =
await exchangeCodeForTokens(result.code);
const connection = await upsertConnection(
{
email,
accessToken: access_token,
refreshToken: refresh_token,
expiresInSeconds: expires_in,
status: ConnectionStatus.ACTIVE,
provider: CalendarProvider.MICROSOFT,
scopes: scope,
},
session.user
);
const q = new URLSearchParams({
cid: connection.id,
});
if (returnUrl) q.append("returnUrl", returnUrl);
res.redirect(302, returnUrl ? returnUrl : `/calendars/microsoft?${q}`);
} catch (e: any) {
let error = JSON.stringify(e);
const querystr =
typeof req.query === "string" ? req.query : JSON.stringify(req.query);
const q = new URLSearchParams({
error,
provider: CalendarProvider.MICROSOFT,
});
return res.redirect(302, `/?${q}`);
}
};
export default microsoftHandler;
Come per il lato client, consigliamo di avere piccole funzioni di utilità, per esempio per scambiare il code con i token.
const TENANT_ID = process.env.MICROSOFT_TENANT_ID;
export async function exchangeCodeForTokens(code: string) {
const data = new FormData();
data.append("client_id", process.env.MICROSOFT_CLIENT_ID || "");
data.append("scope", SCOPES.join(" "));
data.append("code", code);
data.append("redirect_uri", `${getHostName()}/api/connect/microsoft`);
data.append("grant_type", "authorization_code");
data.append("client_secret", process.env.MICROSOFT_CLIENT_SECRET || "");
try {
const result = await fetch(
`https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/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("Exchange failed");
throw e;
}
}
Insidie dell’integrazione dell’API di Outlook Calendar
-
La verifica può richiedere tempo ed essere frustrante : Tieni presente che migliaia, se non milioni, di sviluppatori costruiscono su Outlook, quindi Microsoft esamina ogni giorno un gran numero di richieste. Compila ogni dettaglio quando invii l’app per la revisione e prevedi nella tua roadmap il tempo necessario per la verifica.
-
Richiedi solo gli scope strettamente necessari : Il team Microsoft esamina le app con attenzione, quindi richiedi solo ciò che serve davvero alle funzionalità della tua app. Questo facilita l’approvazione e aiuta anche quando gli utenti concedono l’accesso. Gli utenti si confondono se un’app chiede scope che non hanno nulla a che fare con le sue funzionalità reali.
-
I webhook scadono, ricordati di rinnovarli : Se registri webhook per monitorare le modifiche al calendario, imposta un job in background che giri ogni poche ore e rinnovi ogni sottoscrizione prossima alla scadenza.
-
Rate limiting e throttling : Microsoft applica regole di rate limiting e throttling molto rigide. Evita di recuperare gli elementi uno alla volta e implementa il rate limiting nelle tue chiamate API, così non incorri nei famosi errori “MailboxConcurrency”. La tabella seguente riassume i limiti:
Ambito Limite Note Per mailbox (app ID & mailbox) 10 000 richieste / 10 min e 4 richieste concorrenti Errore “MailboxConcurrency”. Caricamento 150 MB totali PATCH/POST/PUT per 5 min per mailbox. Possibile quando si allegano grandi file ICS o allegati. Graph globale 130 000 richieste / 10 s per app su tutti i tenant. Raro, ma back-fill SaaS estesi possono attivarlo. Buone pratiche per i retry Su 429o503/504controlla l’headerRetry-After, esegui backoff esponenzialeLa Graph API continua a limitare se la colpisci ogni secondo. -
Problemi di fuso orario : In Outlook un utente può digitare manualmente il nome del proprio fuso orario (capisci dove voglio arrivare), quindi assicurati che il tuo codice gestisca anche questo caso.
-
Problemi di consenso e permessi : Come detto nella sezione sugli scope,
Calendars.ReadWriteè delegato all’utente. Molti tenant consentono il consenso utente, ma altri no. Preparati a gestire l’errore “admin consent required” e proponi un flusso amichevole di “Chiedi al tuo admin”.
Integra tutti i provider di calendario nella tua app con la Apiroc Unified Calendar API
Le integrazioni di calendario sono il nostro pane quotidiano. Il nostro team lavora da anni con Google Calendar, Outlook e iCloud Calendar e ha costruito integrazioni di calendario che gestiscono miliardi di chiamate API.
Le lezioni apprese lavorando con tutte le principali API dei calendari sono confluite nella Apiroc Unified Calendar API. Fa risparmiare agli sviluppatori centinaia di ore di problemi legati ai calendari, così possono concentrarsi sulle funzionalità che fanno crescere il prodotto.
Registrati ad Apiroc per provare la Unified Calendar API e integrare più provider di calendario con un’unica API. Il piano gratuito non richiede una carta di credito.
Domande frequenti
Che tipo di account serve per usare l’API Calendario Outlook?
Serve un account Microsoft Work o Developer con accesso ad Azure Active Directory.
Quali ambiti di autorizzazione devo aggiungere per il pieno accesso al calendario?
Aggiungi Calendars.ReadWrite (e Calendars.ReadWrite.Shared se ti servono i calendari condivisi) in Microsoft Graph.
Perché impostare un dominio publisher e un branding?
La verifica del publisher e una schermata di consenso con il tuo marchio impediscono che l’app risulti “non verificata”, e ormai sono attese per la maggior parte delle app multi-tenant.
Con quale frequenza devo rinnovare le sottoscrizioni webhook di Outlook?
I webhook di calendario Graph scadono dopo poche ore. Imposta quindi un job in background che rinnovi ogni sottoscrizione in scadenza.
L’API Calendario Outlook supporta le notifiche push?
Sì. Crea una sottoscrizione Microsoft Graph e riceverai le notifiche di modifica senza dover fare polling.
Esiste un modo più semplice per integrare i calendari Outlook, Google e iCloud?
Sì. Una Unified Calendar API come Apiroc racchiude tutti i principali provider dietro un’unica interfaccia JSON coerente. Con la Apiroc Unified Calendar API non devi sviluppare e mantenere un’integrazione separata per ogni provider di calendario.
