Como integrar a API do Outlook Calendar no seu aplicativo
Índice
Integre todos os calendários usando uma única API
Cadastre-se na nossa Unified Calendar API para integrar todos os provedores de calendário ao seu app usando uma única API, sem necessidade de cartão de crédito.
No nosso último artigo sobre como integrar a API do Google Calendar ao seu aplicativo, explicamos todas as etapas que um desenvolvedor precisa seguir para integrar a API do Google Calendar ao seu aplicativo.
Neste artigo, explicaremos como integrar a API do Outlook Calendar ao seu aplicativo, incluindo a configuração do Registro de Aplicativo no Azure, configuração de escopos, verificação, armadilhas de integração e exemplos do mundo real.
Pré-requisitos
Este guia presume que você já possui uma conta Microsoft Work ou Developer com acesso ao Azure Active Directory.
Observe que a capacidade de criar aplicativos fora de um diretório foi descontinuada. Caso você não tenha um diretório, deve participar do Programa de Desenvolvedores Microsoft 365 ou se inscrever no Azure.
Como usar e integrar a API do Outlook Calendar ao seu aplicativo
Etapa 1: Faça login no Portal do Microsoft Azure
Acesse a Página de login do Portal do Microsoft Azure e faça login.
A página do Portal do Microsoft Azure.

Etapa 2: Registre um novo aplicativo
Após fazer login no Portal do Microsoft Azure:
- Navegue até Azure Active Directory

- Pesquise por “App Registrations” na barra de busca

- Clique em “App Registrations”

- Clique em “New registration”

- Preencha os campos obrigatórios:

- O primeiro campo é o Nome do seu aplicativo, que é o nome exibido para os usuários.
- Em seguida, você deve selecionar os tipos de conta suportados. A seleção será diferente dependendo do tipo de aplicativo que você está desenvolvendo (uso interno ou multi-tenant). Para este exemplo, selecionarei “Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant)”, pois isso garante que usuários de qualquer organização (incluindo usuários do Outlook.com) possam usar meu aplicativo. Isso é ideal para aplicativos SaaS ou qualquer aplicativo multi-tenant.
- Insira o Redirect URI: Isso é opcional, pois pode não ser necessário dependendo do tipo de aplicativo que você está construindo. Se você estiver desenvolvendo um aplicativo web, provavelmente precisará disso, pois este Redirect URI é o URI para onde o Azure enviará as respostas do OAuth. No menu suspenso “Select a platform”, selecione Web, depois preencha o campo Redirect URI (por exemplo,
https://yourapp.com/auth/callback). Para o fluxo de autenticação do lado do servidor, usar um redirect URI web é apropriado. Certifique-se de que o domínio inserido seja acessível e esteja sob seu controle. - Clique em “Register”
- Após clicar no botão “Register”, o Azure Active Directory criará seu aplicativo, e você será direcionado para a próxima página, onde poderá copiar o Client ID e o Tenant ID. O Application (client) ID é um GUID que identifica seu app. O Directory (tenant) ID nem sempre é necessário, pois na maioria dos casos, para apps multi-tenant, você usará o endpoint
common. Você pode usar o tenant ID para testes em seu próprio tenant.
Certifique-se de salvar os campos Client ID e Tenant ID em um local seguro. Normalmente, eles são armazenados como variáveis de ambiente.
Etapa 3: Configurar as permissões da API
Após registrar seu aplicativo, é hora de configurar as permissões do calendário. Essas permissões são solicitadas durante o fluxo de OAuth, e o usuário pode ver quais são os escopos do seu aplicativo antes de aprovar e conceder acesso aos calendários.
Por padrão, sua aplicação recebe a permissão “User.Read”. Caso tudo o que você queira seja fazer login e ler o perfil do usuário, pode pular esta etapa.
Para adicionar permissões da API, siga estas etapas:
- Clique na aba “Manage” na barra lateral esquerda.
- Clique em “API Permissions”.

- Clique no botão “+ Add a permission”.

- Encontre o card “Microsoft Graph” (geralmente é o primeiro no painel à direita que aparece após clicar em “Add a permission”).

- Escolha entre “Delegated permissions” e “Application permissions”. As permissões delegadas são úteis quando seu aplicativo precisa de acesso à API como o usuário conectado. As permissões de aplicativo podem ser usadas quando seu aplicativo é executado como um serviço em segundo plano sem um usuário conectado. Para este exemplo, usarei “Delegated Permissions”.

- Pesquise por “Calendars”: Esta busca mostrará todas as permissões relacionadas a calendários. Escolha as permissões que permitem que seu aplicativo funcione corretamente. Na maioria dos casos, você desejará selecionar “Calendars.ReadWrite” e “Calendars.ReadWrite.Shared” (se precisar de acesso a calendários compartilhados). Observe que os escopos de Calendário geralmente não exigem consentimento de administrador por padrão, pois são escopos delegados ao usuário, mas tenha em mente que algumas organizações restringem o consentimento do usuário. Se um usuário de um tenant externo não puder conceder consentimento, um administrador daquele tenant deverá conceder o consentimento para seu app (geralmente por meio de um prompt ou URL de consentimento administrativo).

Etapa 4: Ativar tokens de ID
Esta etapa não se aplica a todos os aplicativos, mas caso você queira acessar informações do perfil do usuário como nome, e-mail ou URL da foto de perfil, é necessário ativar a opção ID Tokens, em Manage -> Authentication.
Isso permite que seu app identifique o usuário assim que ele se conecta ao calendário, sem precisar fazer outra chamada à API.

Nota: Ativar os tokens de ID é obrigatório se você estiver usando a API Unificada de Calendário da OneCal.
Etapa 5. Gerar um Client Secret
Recomendamos que as operações de calendário (escrita, leitura, atualização, etc) sejam feitas do servidor; por isso você precisa gerar um client secret.
Para gerar um Client Secret, siga estas etapas:
- Clique na aba “Certificates & secrets”

- Clique em “New client secret”

- Insira uma descrição e uma data de expiração

Após gerar o client secret, certifique-se de copiá-lo e armazená-lo em um local seguro (geralmente no seu arquivo .env).
Observe que você não poderá visualizar ou copiar o client secret depois, então certifique-se de copiá-lo antes de sair da página.
Etapa 6. Marca e Verificação
Na seção Branding & Properties do registro do app, você pode definir um logotipo e informações (descrição do app, URL dos termos de serviço, etc.). Isso é opcional, mas recomendado para uma tela de consentimento mais profissional. É essencial definir um domínio do publicador (normalmente seu domínio personalizado, verificado no Azure AD) para evitar que o app apareça como “não verificado” ao solicitar consentimento. Para apps multi-tenant, a Microsoft agora exige que os apps sejam verificados como publicadores para uso amplo. Se seu app não estiver verificado, usuários de fora do seu tenant podem ser impedidos de conceder consentimento devido às políticas de segurança introduzidas em novembro de 2020.

Etapa 7. Familiarize-se com a API Outlook Graph
Após configurar o aplicativo e preencher todas as informações, podemos começar a explorar a Microsoft Calendar Graph API, para nos familiarizarmos com as APIs específicas para criar, atualizar e excluir eventos.
Etapa 8. Considere usar uma API Unificada de Calendário para integrar todos os provedores de calendário com uma única API
Embora a Microsoft Graph API esteja razoavelmente bem documentada, recomendamos usar um produto de API Unificada de Calendário que permite integrar todos os provedores de calendário por meio de uma única API.
Ao usar uma API Unificada de Calendário, você tem o benefício de implementar uma única API em seu aplicativo e oferecer suporte a todos os provedores de calendário, independentemente de suas limitações ou diferenças de API.
Outro benefício de usar uma única API para todos os calendários é que você não precisa manter várias APIs de calendário, lidar com mudanças que quebram integrações ou casos extremos que nunca havia previsto.
OneCal Unified Calendar API

Exemplo de fluxo de autorização do Outlook Calendar
O diagrama abaixo ilustra um fluxo OAuth simples do Outlook Calendar que permite que os usuários conectem seus calendários do Outlook ao seu aplicativo.

Acesse a página de documentação do Microsoft OAuth2 Flow para saber mais sobre o fluxo OAuth2 da Microsoft.
Client Side (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}`;
}
- O parâmetro “prompt” pode ter um dos quatro valores:
login,none,consenteselect_account. - O “response_mode” pode ter os valores
query,fragmentouform_post. Escolhemosform_postporque ele informa à Microsoft que envie uma solicitação POST para nosso redirect URI (no servidor).
API Side (Backend)
A seguir, vamos construir o handler da API, responsável por obter o código e os escopos do servidor do Outlook e trocá-los por tokens.
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;
Recomendamos também ter funções utilitárias como esta para trocar o código por tokens.
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;
}
}
Armadilhas ao integrar a API do Outlook Calendar
- A verificação pode demorar e ser frustrante às vezes: Tenha em mente que milhares (senão milhões) de desenvolvedores usam o Outlook diariamente, então a equipe da Microsoft processa milhares de submissões de aplicativos por dia. Certifique-se de preencher todos os detalhes ao enviar para revisão e leve em consideração esse tempo no seu cronograma.
- Solicite apenas os escopos estritamente necessários: A equipe da Microsoft é muito rigorosa em suas revisões, então certifique-se de solicitar apenas o que é necessário para seu app executar suas funcionalidades. Isso facilitará a aprovação e deixará a interface de consentimento mais clara para o usuário, que pode se confundir ao ver escopos desnecessários.
- Webhooks expiram, certifique-se de renová-los: Caso esteja registrando webhooks para acompanhar mudanças no calendário, configure um job de segundo plano a cada poucas horas para renovar assinaturas de webhooks que irão expirar.
- Limites de taxa e restrições: A Microsoft impõe limites rigorosos de taxa. Evite buscar itens um por um e implemente controle de taxa nas chamadas do seu app para evitar os famosos erros “MailboxConcurrency”. A tabela a seguir explica os limites:
|
Escopo |
Limite |
Observações |
|---|---|---|
|
Por caixa de correio (par App ID + caixa) |
10.000 requisições / 10 min e 4 requisições simultâneas |
O famoso erro “MailboxConcurrency”. |
|
Upload |
150 MB total de PATCH/POST/PUT a cada 5 min por caixa. |
Pode ocorrer ao anexar arquivos ICS grandes ou anexos. |
|
Global Graph |
130.000 requisições / 10 s por app em todos os tenants. |
Raro, mas grandes preenchimentos em massa podem disparar isso. |
|
Etiqueta de Repetição |
Em |
A Graph API continuará limitando se você insistir com requisições a cada segundo. |
- Problemas com fusos horários: No Outlook, o usuário pode digitar manualmente seu próprio fuso horário (sim, isso mesmo), então certifique-se de tratar esse caso também.
- Problemas com consentimento e permissões: Como mencionado na configuração dos escopos da aplicação,
Calendars.ReadWriteé um escopo delegado, mas alguns tenants não permitem consentimento de usuários. Esteja preparado para o erro “admin consent required” e ofereça um fluxo amigável de “Peça ao seu administrador”.
Integre todos os provedores de calendário ao seu app com a API Unificada de Calendário da OneCal
Integrações de calendário são nossa especialidade. Desde 2022, sincronizamos bilhões de eventos entre todos os principais provedores de calendário, e nossos links de agendamento são usados por milhares de profissionais ao redor do mundo.
As lições que aprendemos lidando com todas as APIs de calendário nos motivaram a criar a API Unificada de Calendário da OneCal, permitindo que nossos usuários evitem gastar centenas de horas com problemas relacionados a calendário e foquem em implementar funcionalidades que realmente beneficiem seus produtos e seu crescimento.
Cadastre-se na OneCal Unified Calendar API para testar nossa Unified API e integrar facilmente vários provedores de calendário usando uma única API.
FAQ
Que tipo de conta eu preciso para usar a API do Outlook Calendar?
Uma conta Microsoft Work ou Developer com acesso ao Azure Active Directory.
Quais escopos de permissão devo adicionar para acesso total ao calendário?
Adicione Calendars.ReadWrite (e Calendars.ReadWrite.Shared se precisar de calendários compartilhados) no Microsoft Graph.
Por que definir um domínio do publicador e marca?
A verificação de publicador e a tela de consentimento personalizada evitam que seu app apareça como “não verificado” e agora são exigidas para a maioria dos apps multi-tenant.
Com que frequência devo renovar as assinaturas de webhooks do Outlook?
Os webhooks de calendário do Graph expiram em poucas horas, então é necessário agendar um job de fundo para renovar qualquer assinatura prestes a expirar.
A API do Outlook Calendar suporta notificações push?
Sim. Crie uma assinatura do Microsoft Graph para receber notificações de alteração em vez de fazer polling.
Existe uma maneira mais fácil de integrar calendários do Outlook, Google e iCloud ao meu aplicativo?
Sim. Uma API Unificada de Calendário como a OneCal encapsula todos os principais provedores em uma única interface JSON consistente. Usando a API Unificada de Calendário da OneCal, você não precisa desenvolver nem manter integrações separadas para cada provedor de calendário.