Como integrar a API do iCloud Calendar ao seu aplicativo
Índice
Use uma API única para todos os calendários
Cadastre-se na nossa Unified Calendar API para integrar todos os provedores de calendário usando uma única API, sem necessidade de cartão de crédito.
No nosso artigo anterior, explicamos como integrar a API do Google Calendar ao seu aplicativo, destacando todas as etapas para fazer a integração funcionar.
Diferentemente do Google Calendar, integrar o iCloud Calendar não é tão simples, pois a documentação é escassa e a Apple não se esforçou tanto em detalhar o que um desenvolvedor precisa fazer para integrar o iCloud Calendar em um aplicativo.
Neste artigo, vamos nos aprofundar em como integrar a API do iCloud Calendar ao seu aplicativo, incluindo autenticação, operações suportadas, limitações e ferramentas que você pode usar para facilitar a integração.
Quais protocolos e padrões o Apple iCloud Calendar utiliza?
O Apple iCloud Calendar utiliza o padrão CalDAV para comunicação de calendário. CalDAV é uma extensão do WebDAV que permite aos clientes gerenciar calendários e eventos em um servidor.
Os eventos são representados no formato ICS (iCalendar), que é um formato baseado em texto para dados de calendário. Isso significa que seu aplicativo pode se comunicar com os calendários do iCloud por HTTP usando requisições CalDAV e dados ICS.
O benefício é que essa não é uma implementação específica de dispositivo ou sistema operacional da Apple; você pode usá-la a partir de qualquer servidor rodando em qualquer plataforma.
A má notícia é que o iCloud não fornece uma API REST para calendários, portanto o CalDAV é a única forma de integrar o iCloud Calendar ao seu aplicativo.
Recomendamos que a integração seja servidor para servidor; por isso dizemos que o CalDAV é o único caminho viável.
Como autenticar com o iCloud?
Normalmente, quando você deseja integrar uma plataforma ao seu aplicativo (como o Google Calendar, por exemplo), é necessário criar uma conta de desenvolvedor nessa plataforma, criar um aplicativo, configurar escopos, adicionar usuários de teste, preencher as informações do seu aplicativo e enviá-lo para aprovação.
Após seguir todas essas etapas e obter aprovação, você pode direcionar o usuário final para a tela de OAuth da plataforma, onde ele deverá estar conectado à plataforma e conceder acesso explícito ao escopo solicitado pelo seu aplicativo. O usuário final também verá o nome do seu aplicativo e todas as informações fornecidas durante a configuração.
O Apple iCloud não funciona dessa forma, pois não possui um fluxo OAuth padrão como o Google Calendar ou o Outlook. Para conectar o iCloud Calendar de um usuário, você deve autenticar com o ID Apple dele usando autenticação básica via SSL. Como a maioria das contas do iCloud possui autenticação em dois fatores, o usuário precisa criar uma senha específica para o app através das configurações da conta Apple ID, em vez de usar a senha principal da conta Apple.
Seu aplicativo solicitará ao usuário o e-mail/ID Apple e essa senha específica de 16 caracteres. Com essas credenciais, você pode se conectar ao serviço CalDAV do iCloud.
Exemplo de como seu aplicativo solicitaria que o usuário inserisse o endereço de e-mail e a senha específica para o app.

Além dos motivos listados acima, a Apple exige senhas específicas para apps de terceiros como uma medida de segurança adicional, já que compartilhar sua senha do iCloud com um aplicativo de terceiros não é a melhor prática.
Na prática, o cabeçalho da sua requisição HTTP incluirá a senha codificada em Base64, neste formato: Authorization: Basic <app-specific-password-here>
Quais métodos a API do iCloud Calendar suporta?
O serviço CalDAV do iCloud é hospedado em caldav.icloud.com. Após autenticar, a seguinte lista de métodos está disponível:
- Listar os calendários de um usuário
- Operações CRUD em eventos
- Buscar eventos específicos
Para saber mais sobre o padrão CalDAV, leia o RFC 4791, que explica todos os métodos, filtros e muito mais.
Abaixo, vou resumir as informações mais importantes que você precisa saber para a integração com o iCloud Calendar.
Verbos HTTP suportados:
|
Verbo HTTP |
O que faz no CalDAV |
Suporte no iCloud |
Observações |
|---|---|---|---|
|
OPTIONS |
Descobrir capacidades do servidor |
✅ |
Útil para depuração; não é necessário em tempo de execução. |
|
PROPFIND |
Procurar principais, |
✅ |
É necessário autenticar primeiro; use Depth 0 ou 1. |
|
MKCALENDAR |
Criar nova coleção de calendário |
✅ |
Requer permissões de escrita; veja Seção 5.3.1. |
|
REPORT |
Consultar dados ( |
✅ |
Todos os três relatórios são obrigatórios pelo padrão e estão presentes no iCloud. |
|
PUT |
Fazer upload / substituir um recurso |
✅ |
Deve enviar VCALENDAR completo; não há suporte a PATCH. |
|
DELETE |
Remover um evento ou calendário |
✅ |
Combine com |
|
COPY / MOVE |
Copiar ou mover eventos entre calendários |
✅ |
Sujeito às mesmas pré-condições do PUT. |
|
GET |
Buscar um único recurso |
✅ |
Retorna |
Propriedades de coleção de calendário
|
Propriedade |
Propósito |
Notas específicas do iCloud |
|---|---|---|
|
|
Descrição legível por humanos |
Totalmente suportado |
|
|
Fuso horário padrão para consultas |
Suportado |
|
|
Quais componentes (VEVENT, VTODO) o calendário aceita |
Eventos e tarefas ficam em calendários separados. |
|
|
MIME/versão permitidos (geralmente |
iCloud=default |
|
|
Tamanho máximo por evento |
Limite de ~20 MB no iCloud |
|
|
Vários limites do servidor |
Respeite para evitar erros 403/507. |
A OneCal Unified Calendar API está pronta para produção. Cadastre-se gratuitamente para integrar todos os provedores de calendário usando uma única API.
Quais bibliotecas você pode usar para facilitar a integração?
Lidar com CalDAV, ICS, XML e outras peculiaridades do iCloud Calendar não é o ideal ao integrá-lo ao seu aplicativo, pois você gastará muito tempo tentando entender cada método, converter XML para JSON e usá-lo na sua aplicação.
Para uma integração mais prática, recomendamos o uso das seguintes bibliotecas:
tsdav: Essencial se você estiver usando JavaScript/TypeScript como linguagem de programação. Com o tsdav, você pode se comunicar facilmente com o servidor do iCloud sem precisar usar sintaxe ou terminologia específica do CalDAV. Ele oferece uma API TypeScript de alto nível que encapsula todos os verbos HTTP e XML que você teria que escrever manualmente (PROPFIND, REPORT, MKCALENDAR, PUT, DELETE, etc). Veja mais na documentação do tsdav.ical-generator: Ao integrar o iCloud Calendar por meio do CalDAV, você precisa enviar e substituir arquivos .ics inteiros ao criar ou atualizar um evento. Escrever esses arquivos manualmente é propenso a erros, e cada VEVENT precisa de cabeçalhos corretos, UID, formatação de DTSTART/DTEND, strings RRULE, fusos horários, e mais. O ical-generator ajuda com tudo isso.ical.js: Um analisador/engine JavaScript puro criado pela equipe do Mozilla Calendar, usado para analisar respostas ICS para classes JS.
A tabela abaixo explica o papel do tsdav na integração com o iCloud Calendar:
|
Papel na stack |
O que o tsdav faz |
Por que é importante para o iCloud |
|---|---|---|
|
Cliente CalDAV / WebDAV |
Fornece uma API TypeScript de alto nível que encapsula todos os verbos HTTP e XML que você teria que escrever e converter manualmente. |
Permite que você foque na lógica de negócios em vez de gerar strings XML brutas e analisar respostas multistatus. |
|
Auxiliares de descoberta |
|
Elimina código boilerplate para a sequência de descoberta em dois passos exclusiva do iCloud. |
|
Wrappers de autenticação |
Auxiliares integrados para autenticação Basic e OAuth 2. Para o iCloud, você passa |
Não é necessário codificar credenciais em Base64 ou injetar headers manualmente. |
|
Auxiliares tipados para tarefas comuns |
|
Implementa CRUD rapidamente sem se preocupar com a sintaxe XML do RFC-4791. |
|
Suporte a token de sincronização |
|
Permite implementar polling para iCloud (que não tem push) com uma única linha. |
|
Compatibilidade com navegador + Node |
Funciona em código de servidor (Node) ou no navegador, graças ao uso isomórfico do fetch. |
Útil se parte do seu app rodar em extensão de navegador ou SPA. |
|
Projeto TS moderno e tipado |
Possui definições de tipo completas, módulos ES tree-shakable e poucas dependências. |
Fácil de integrar em pipelines de build modernos. |
tsdav não gera iCalendar. Use-o junto com ical-generator (ou outro gerador de ICS de sua escolha) para produzir as strings de payload dos eventos.
Exemplo de uma integração com o iCloud Calendar usando tsdav + ts
Neste exemplo, assumiremos que você já obteve o nome de usuário e a senha específica de app da Apple do usuário.
createClient Método que cria o DAVClient:
import { DAVCalendar, DAVClient, DAVNamespaceShort, DAVObject } from "tsdav";
const APPLE_DAV_URL = "https://caldav.icloud.com";
function createClient({
username,
password,
}: {
username: string;
password: string;
}) {
const client = new DAVClient({
serverUrl: APPLE_DAV_URL,
credentials: {
username,
password,
},
authMethod: "Basic",
defaultAccountType: "caldav",
});
return client;
}
constants Arquivo que contém constantes
/*
The prodId value is a required field that must appear on every calendar object.
The field is a globally-unique identifier for the software that
produced the file. tsdav might automatically generate that information for you,
but it might be best if you provide it manually.
You might find it useful when you have edge cases, you can use it to tell which
program wrote the data.
*/
export const PROD_ID = {
company: "your-company-name-here",
product: "your-product-name-here",
};getCalendars Método que busca todos os calendários
async getCalendars(
...params: Parameters<typeof DAVClient.prototype.fetchCalendars>
): Promise<DAVCalendar[]> {
// You can abstract this initialization into another method.
// For the sake of simplicity, we'll initialize the client on each method.
const client = createClient({
username: <email-here>,
password: <password-here>,
});
return client.fetchCalendars(...params);
}getCalendarById Método que busca um calendário pelo ID
async getCalendarById(calendarUrl: string): Promise<DAVCalendar> {
const calendars = await getCalendars();
const calendar = calendars.find((el) => el.url === calendarUrl);
if (!calendar) {
throw new Error(`Apple Calendar with id ${calendarUrl} not found`);
}
return calendar;
}getCalendarEvents Método para listar todos os eventos do calendário
async getCalendarEvents(
calendarUrl: string,
query: GetCalendarEventsQuery = {}
) {
const client = createClient({
username: <email-here>,
password: <password-here>,
});
const calendar = await getCalendarById(calendarUrl);
const events = await client.fetchCalendarObjects({
calendar,
timeRange: query.dateRange ?? undefined,
})
return { events, nextSyncToken: calendar.syncToken };
}getEventById Método que retorna um evento de calendário pelo seu ID
async getEventById(calendarUrl: string, eventId: string) {
const client = createClient({
username: <email-here>,
password: <password-here>,
});
const eventUrl = new URL(`${eventId}.ics`, calendarUrl).pathname;
const responses = await client.calendarMultiGet({
url: calendarUrl,
props: {
[`${DAVNamespaceShort.DAV}:getetag`]: {},
[`${DAVNamespaceShort.CALDAV}:calendar-data`]: {},
},
objectUrls: [eventUrl],
depth: "1",
})
if (responses.length === 0) {
throw new Error(
`Received no response while fetching ${eventUrl}`,
null
);
} else if (responses[0].status >= 400) {
throw new Error(
`Failed to get Apple event by id. Status: ${responses[0].statusText}`,
responses[0]
);
}
const response = responses[0];
const calendarObject: DAVObject = {
url: new URL(response.href ?? "", calendarUrl).href,
etag: `${response.props?.getetag}`,
data:
response.props?.calendarData?._cdata ?? response.props?.calendarData,
};
try {
return calendarObject;
} catch (err: any) {
this.logger.error("Failed to process Apple Response", {
message: err.message,
event: calendarObject,
});
return [];
}
}createEvent Método que cria um evento
async createEvent(calendarUrl: string, data: AppleEvent) {
const client = createClient({
username: <email-here>,
password: <password-here>,
});
const eventId = data.id ?? <generate-id-here>
const calendar = ical({
prodId: PROD_ID,
method: ICalCalendarMethod.REQUEST,
});
const event = calendar.createEvent({ ...data, id: eventId });
const response = await client.createCalendarObject({
calendar: {
url: calendarUrl,
},
filename: `${event.id()}.ics`,
iCalString: calendar.toString(),
})
if (!response.ok) {
throw new Error(
`Failed to create Apple event: ${response.statusText}`,
response
);
}
return { id: event.id(), eventWithExceptions };
}updateEvent Método que exclui um evento
async updateEvent(calendarUrl: string, eventId: string, data: AppleEvent) {
const client = createClient({
username: <email-here>,
password: <password-here>,
});
const originalEventData = await getEventById(calendarUrl, eventId);
const calendar = ical({
prodId: PROD_ID,
method: ICalCalendarMethod.REQUEST,
});
for (let event of originalEventData) {
if (event.status === ICalEventStatus.CANCELLED) continue;
if (event.id === eventId) {
calendar.createEvent({ ...event, ...data, id: eventId, url: null });
} else {
calendar.createEvent({ ...event, id: eventId, url: null });
}
}
const calendarObjectUrl = new URL(`${eventId}.ics`, calendarUrl);
const response = await
client.updateCalendarObject({
calendarObject: {
url: calendarObjectUrl.href,
data: calendar.toString(),
},
})
if (!response.ok) {
throw new Error(
`Failed to update Apple event: ${response.statusText}`,
response
);
}
return getEventById(calendarUrl, eventId);
}deleteEvent Método que exclui um evento pelo ID
async deleteEvent(calendarUrl: string, eventId: string) {
const client = createClient({
username: <email-here>,
password: <password-here>,
});
const calendarObjectUrl = new URL(`${eventId}.ics`, calendarUrl);
const response = await client.deleteCalendarObject({
calendarObject: {
url: calendarObjectUrl.href,
},
})
if (!response.ok) {
throw new Error(
`Failed to delete Apple event: ${response.statusText}`,
response
);
}
return { id: eventId };
}Quais limitações o Apple iCloud Calendar possui?
- Sem API REST ou respostas em JSON: Para se comunicar com a API do iCloud Calendar, você precisa usar CalDAV e trabalhar com arquivos .ics. Isso não é o ideal, pois a API do Outlook Calendar e a API do Google Calendar oferecem APIs REST que funcionam com JSON e são muito mais produtivas de utilizar. Você pode usar as bibliotecas que sugeri para facilitar a comunicação com a API do iCloud Calendar, mas isso dependerá da linguagem e do framework que você está usando, pois nem todos os frameworks possuem bibliotecas disponíveis que facilitam essa integração.
- Falta de documentação: Embora tenhamos incluído o link para a documentação oficial do CalDAV, é importante estar ciente de que nem todos os métodos funcionam ao se comunicar com a API do iCloud Calendar, então esteja preparado para imprevistos e muitos testes.
- Autenticação básica com senha específica de app: Como mencionado anteriormente, o iCloud não segue as convenções padrão do OAuth 2.0. Você precisa usar uma senha específica de app para autenticar e se comunicar com o iCloud Calendar.
- Sem suporte para webhooks/notificações push: Diferente do Google Calendar ou Outlook, o iCloud não possui a melhor API de calendário, pois não é possível registrar webhooks para ser notificado sobre alterações nos calendários. Aplicativos de terceiros não podem assinar atualizações em tempo real. Uma solução alternativa é fazer polling periódico e usar o relatório
sync-collectionpara obter as alterações de forma eficiente. - Sem suporte para métodos PATCH: Não é possível usar métodos PATCH para atualizar parcialmente eventos; em vez disso, é necessário fazer um PUT completo para atualizar eventos.
- Sem controle sobre convites: O iCloud Calendar lida automaticamente com convites para reuniões. Se você criar ou modificar um evento com participantes, o iCloud Calendar enviará os convites e atualizará os status dos convidados. Não é possível usar a Outbox/Inbox de agendamento do CalDAV para controlar convites manualmente.
Qual é a maneira mais fácil de integrar o iCloud Calendar ao meu aplicativo?
Integrar o iCloud Calendar ao seu aplicativo não é tarefa simples, pois ele não segue as convenções padrão de calendários, e muitos métodos e filtros do CalDAV não funcionam.
Uma forma mais fácil de integrar o iCloud Calendar ao seu aplicativo é usar uma API Unificada de Calendário.

Usar uma API Unificada de Calendário traz os seguintes benefícios:
- Integre o iCloud Calendar ao seu aplicativo usando uma API bem documentada e testada que segue padrões modernos.
- Gaste menos tempo desenvolvendo e mantendo a integração. No fim das contas, usar uma API Unificada de Calendário economiza tempo, pois o produto já resolve a maior parte dos problemas para você, desde a API até clientes, casos extremos, etc. Além disso, você não precisará manter a integração ou corrigir problemas que surgirem.
- Integre outros provedores de calendário além do iCloud Calendar ao seu aplicativo sem esforço adicional. A maioria das APIs Unificadas de Calendário se integram com os principais provedores, facilitando a integração com Google Calendar, Outlook e outros.
- Suporte a notificações push/webhooks sem precisar criar soluções personalizadas de polling. Criar sua própria solução de polling para iCloud é complicado, pois você terá que configurar filas e novos servidores para processar mensagens.

Use uma API Unificada de Calendário para integrar o iCloud Calendar ao seu aplicativo
Estamos quase prontos para lançar nossa API Unificada de Calendário da OneCal, que concederá todos os benefícios mencionados acima.
Você não precisa lidar com todas as armadilhas de integrar o iCloud Calendar à sua aplicação. Em vez disso, utilize nossa Unified Calendar API, que reúne anos de experiência e correções de bugs. Você pode se cadastrar gratuitamente na nossa plataforma, sem necessidade de cartão de crédito.
FAQ
Qual protocolo o iCloud Calendar usa?
O iCloud Calendar utiliza CalDAV sobre HTTP e armazena eventos no formato iCalendar (ICS).
O iCloud Calendar oferece uma API REST?
Não. CalDAV é a única maneira de ler e gravar dados do iCloud Calendar.
Como autenticar no iCloud Calendar?
Você deve passar o Apple ID do usuário (geralmente o e-mail) e uma senha específica de app de 16 caracteres via Basic Auth sobre SSL.
O iCloud Calendar suporta notificações push ou webhooks?
Não. É necessário fazer polling no servidor iCloud para detectar alterações.
Quais bibliotecas facilitam a integração?
tsdav (cliente CalDAV), ical-generator (gera arquivos ICS) e ical.js (analisa arquivos ICS) cuidam da maior parte dos detalhes técnicos.
Como evitar lidar diretamente com CalDAV e ICS?
Use uma API Unificada de Calendário como a OneCal Unified Calendar API, que encapsula iCloud, Google e Outlook em uma interface moderna baseada em JSON.