Resumo
As APIs do Calendly permitem automatizar fluxos de trabalho de agendamento. Você se autentica com OAuth 2.0, acessa tipos de eventos e agendamentos via api.calendly.com, e recebe atualizações em tempo real via webhooks. Para testes, use o Apidog para validar payloads de webhook e testar sua integração sem criar agendamentos reais.
Introdução
O Calendly processa milhões de reuniões mensalmente. As pessoas o utilizam para chamadas de vendas, sessões de suporte, consultorias e entrevistas. A API permite incorporar esse poder de agendamento em seus próprios aplicativos.
O padrão comum: você deseja que os agendamentos do Calendly acionem ações em seu sistema. Um usuário agenda uma demonstração, e seu CRM é atualizado. Uma consultoria é agendada, e você envia um questionário. Uma reunião é cancelada, e você notifica sua equipe.
A API do Calendly lida com isso via webhooks. Quando eventos ocorrem (agendamento criado, cancelado, reagendado), o Calendly envia POSTs para seus endpoints. Você processa o payload e age.
Autenticação com OAuth 2.0
O Calendly usa OAuth 2.0 para acesso à API. Você não pode simplesmente usar uma chave de API.
Criar um aplicativo OAuth
- Vá para Calendly → Integrações → API & Webhooks
- Clique em “Criar Novo Aplicativo”
- Defina sua URI de redirecionamento (por exemplo,
https://yourapp.com/auth/calendly/callback) - Obtenha seu ID de cliente e segredo de cliente
O fluxo OAuth
Passo 1: Redirecionar usuário para autorizar
https://auth.calendly.com/oauth/authorize?
client_id=YOUR_CLIENT_ID&
response_type=code&
redirect_uri=https://yourapp.com/auth/calendly/callback
Passo 2: Usuário autoriza e é redirecionado de volta
https://yourapp.com/auth/calendly/callback?code=AUTHORIZATION_CODE
Passo 3: Trocar código por token de acesso
const response = await fetch('https://auth.calendly.com/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + Buffer.from(clientId + ':' + clientSecret).toString('base64')
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: authCode,
redirect_uri: 'https://yourapp.com/auth/calendly/callback'
})
})
const { access_token, refresh_token, expires_in } = await response.json()
Passo 4: Usar o token
curl -X GET "https://api.calendly.com/users/me" \
-H "Authorization: Bearer ACCESS_TOKEN"
Tokens de atualização
Tokens de acesso expiram após 2 horas. Use tokens de atualização para obter novos:
const response = await fetch('https://auth.calendly.com/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + Buffer.from(clientId + ':' + clientSecret).toString('base64')
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: storedRefreshToken
})
})
Obtendo informações do usuário
Obter usuário atual
curl -X GET "https://api.calendly.com/users/me" \
-H "Authorization: Bearer ACCESS_TOKEN"
Resposta:
{
"resource": {
"avatar_url": "https://calendly.com/avatar.jpg",
"created_at": "2024-01-15T10:00:00Z",
"current_organization": "https://api.calendly.com/organizations/ABC123",
"email": "you@example.com",
"name": "John Doe",
"scheduling_url": "https://calendly.com/johndoe",
"slug": "johndoe",
"timezone": "America/New_York",
"uri": "https://api.calendly.com/users/ABC123"
}
}
Obter associação à organização
curl -X GET "https://api.calendly.com/organization_memberships/me" \
-H "Authorization: Bearer ACCESS_TOKEN"
Tipos de evento
Tipos de evento são os modelos de reunião que os usuários criam (chamada de 30 min, consultoria de 60 min, etc.).
Listar tipos de evento
curl -X GET "https://api.calendly.com/event_types?user=https://api.calendly.com/users/ABC123" \
-H "Authorization: Bearer ACCESS_TOKEN"
Resposta:
{
"resource": {
"uri": "https://api.calendly.com/event_types/ETC123",
"active": true,
"booking_method": "instant",
"color": "#0066FF",
"created_at": "2024-01-15T10:00:00Z",
"description_html": "<p>30-minute consultation</p>",
"duration": 30,
"internal_note": "Use Zoom link",
"kind": "solo",
"name": "30 Min Consultation",
"pooling_type": null,
"profile": {
"name": "John Doe",
"type": "User",
"owner": "https://api.calendly.com/users/ABC123"
},
"scheduling_url": "https://calendly.com/johndoe/30min",
"slug": "30min",
"type": "StandardEventType"
},
"pagination": {
"count": 1,
"next_page": null
}
}
Obter um tipo de evento específico
curl -X GET "https://api.calendly.com/event_types/ETC123" \
-H "Authorization: Bearer ACCESS_TOKEN"
Eventos agendados (agendamentos)
Eventos são os agendamentos reais feitos através do Calendly.
Listar eventos agendados
curl -X GET "https://api.calendly.com/scheduled_events?user=https://api.calendly.com/users/ABC123" \
-H "Authorization: Bearer ACCESS_TOKEN"
Filtrar por intervalo de datas:
curl -X GET "https://api.calendly.com/scheduled_events?min_start_time=2026-03-01T00:00:00Z&max_start_time=2026-03-31T23:59:59Z" \
-H "Authorization: Bearer ACCESS_TOKEN"
Resposta:
{
"resource": {
"uri": "https://api.calendly.com/scheduled_events/ABC123",
"status": "active",
"tracking": {
"utm_campaign": "spring_sale",
"utm_source": "email",
"utm_medium": "newsletter"
},
"created_at": "2026-03-24T10:00:00Z",
"end_time": "2026-03-25T11:00:00Z",
"event_type": "https://api.calendly.com/event_types/ETC123",
"invitees_counter": {
"active": 1,
"limit": 1,
"total": 1
},
"location": {
"type": "zoom",
"join_url": "https://zoom.us/j/123456789"
},
"start_time": "2026-03-25T10:30:00Z",
"updated_at": "2026-03-24T10:00:00Z"
}
}
Obter detalhes do evento
curl -X GET "https://api.calendly.com/scheduled_events/EVENT_ID" \
-H "Authorization: Bearer ACCESS_TOKEN"
Obter convidados para um evento
curl -X GET "https://api.calendly.com/scheduled_events/EVENT_ID/invitees" \
-H "Authorization: Bearer ACCESS_TOKEN"
Resposta:
{
"resource": [
{
"cancel_url": "https://calendly.com/cancellations/ABC123",
"created_at": "2026-03-24T10:00:00Z",
"email": "jane@example.com",
"event": "https://api.calendly.com/scheduled_events/ABC123",
"name": "Jane Smith",
"new_invitee": null,
"old_invitee": null,
"reschedule_url": "https://calendly.com/reschedulings/ABC123",
"status": "active",
"text_reminder_number": "+15551234567",
"timezone": "America/New_York",
"tracking": {
"utm_campaign": null,
"utm_source": null
},
"updated_at": "2026-03-24T10:00:00Z",
"uri": "https://api.calendly.com/scheduled_event_invitees/INV123",
"canceled": null
}
]
}
Webhooks para atualizações em tempo real
Webhooks notificam seu aplicativo sobre eventos de agendamento em tempo real.
Criar uma assinatura de webhook
curl -X POST "https://api.calendly.com/webhook_subscriptions" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/webhooks/calendly",
"events": [
"invitee.created",
"invitee.canceled",
"invitee.rescheduled"
],
"organization": "https://api.calendly.com/organizations/ORG123",
"scope": "organization"
}'
Eventos disponíveis:
invitee.created- Novo agendamento criadoinvitee.canceled- Agendamento canceladoinvitee.rescheduled- Agendamento reagendado
Listar assinaturas de webhook
curl -X GET "https://api.calendly.com/webhook_subscriptions?organization=https://api.calendly.com/organizations/ORG123" \
-H "Authorization: Bearer ACCESS_TOKEN"
Excluir um webhook
curl -X DELETE "https://api.calendly.com/webhook_subscriptions/WEBHOOK_ID" \
-H "Authorization: Bearer ACCESS_TOKEN"
Manipulando payloads de webhook
Verificar assinaturas de webhook
O Calendly assina os webhooks com uma assinatura no cabeçalho Calendly-Webhook-Signature:
import crypto from 'crypto'
function verifySignature(payload, signature, secret) {
const [t, v1] = signature.split(',')
const timestamp = t.split('=')[1]
const hash = v1.split('=')[1]
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(timestamp + '.' + payload)
.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(hash),
Buffer.from(expectedSignature)
)
}
app.post('/webhooks/calendly', (req, res) => {
const signature = req.headers['calendly-webhook-signature']
const payload = JSON.stringify(req.body)
if (!verifySignature(payload, signature, process.env.CALENDLY_WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature')
}
// Process webhook
handleWebhook(req.body)
res.status(200).send('OK')
})
Processar eventos de agendamento
function handleWebhook(payload) {
const { event, payload: data } = payload
switch (event) {
case 'invitee.created':
console.log(`New booking: ${data.event.start_time}`)
console.log(`Invitee: ${data.email}`)
// Add to CRM, send confirmation email, etc.
syncToCRM(data)
break
case 'invitee.canceled':
console.log(`Booking canceled: ${data.event.uri}`)
// Update CRM, notify team, etc.
removeFromCRM(data)
break
case 'invitee.rescheduled':
console.log(`Booking rescheduled: ${data.event.start_time}`)
// Update calendar, notify team, etc.
updateCRM(data)
break
}
}
Testando com Apidog
A API do Calendly requer OAuth, o que complica os testes. O Apidog simplifica isso.

1. Simular respostas OAuth
Durante o desenvolvimento, não passe pelo fluxo OAuth completo toda vez. Simule a resposta do token:
{
"access_token": "mock_access_token",
"refresh_token": "mock_refresh_token",
"expires_in": 7200,
"created_at": 1700000000
}
2. Testar manipuladores de webhook
Crie payloads de webhook simulados:
{
"created_at": "2026-03-24T10:00:00Z",
"event": "invitee.created",
"payload": {
"email": "test@example.com",
"name": "Test User",
"event": {
"start_time": "2026-03-25T10:30:00Z",
"end_time": "2026-03-25T11:00:00Z",
"event_type": {
"name": "30 Min Consultation"
}
}
}
}
Envie para seu endpoint de webhook e verifique o processamento.
3. Variáveis de ambiente
CALENDLY_CLIENT_ID: abc123
CALENDLY_CLIENT_SECRET: xyz789
CALENDLY_ACCESS_TOKEN: stored_token
CALENDLY_REFRESH_TOKEN: stored_refresh
CALENDLY_WEBHOOK_SECRET: webhook_signing_secret
4. Validar assinaturas de webhook
pm.test('Webhook signature is valid', () => {
const signature = pm.request.headers.get('Calendly-Webhook-Signature')
pm.expect(signature).to.exist
const payload = pm.request.body.raw
const secret = pm.environment.get('CALENDLY_WEBHOOK_SECRET')
// Verify signature
const valid = verifySignature(payload, signature, secret)
pm.expect(valid).to.be.true
})
Teste os webhooks do Calendly com o Apidog - grátis
Erros comuns e soluções
401 Não Autorizado
Causa: Token inválido ou expirado.
Solução:
- Verifique se o token não expirou (expira em 2 horas)
- Use o token de atualização para obter um novo token de acesso
- Garanta que o cabeçalho Authorization seja
Bearer {token}
403 Proibido
Causa: Escopo OAuth insuficiente.
Solução: O token OAuth precisa de escopos apropriados. Ao solicitar autorização, inclua os escopos necessários. Os escopos do Calendly são implícitos com base no que o usuário autoriza.
404 Não Encontrado
Causa: O recurso não existe ou o usuário não tem acesso.
Solução:
- Verifique se a URI do recurso está correta
- Garanta que o usuário autenticado tenha acesso ao recurso
- Verifique se o tipo de evento ou ID do evento é válido
422 Entidade Não Processável
Causa: Erro de validação na requisição.
Solução: Verifique a resposta para detalhes:
{
"title": "Validation Error",
"message": "Invalid parameter: url must be a valid HTTPS URL"
}
Alternativas e comparações
| Recurso | Calendly | Acuity | Cal.com | Calendly |
|---|---|---|---|---|
| Camada gratuita | Limitada | Limitada | Auto-hospedado grátis | ✓ |
| Acesso à API | ✓ | ✓ | ✓ | ✓ |
| Webhooks | ✓ | ✓ | ✓ | ✓ |
| OAuth | ✓ | Chave de API | Chave de API | OAuth |
| Agendamento em equipe | ✓ | ✓ | ✓ | ✓ |
| Código aberto | Não | Não | Sim | Não |
O Calendly possui a documentação de API e o fluxo OAuth mais polidos. O Cal.com é a alternativa de código aberto com autenticação por chave de API mais simples.
Casos de uso do mundo real
Integração com CRM de vendas. Uma empresa SaaS B2B incorpora o Calendly em sua página de preços. Quando alguém agenda uma demonstração, o webhook aciona:
- Criação de lead no Salesforce
- Envio de notificação Slack para a equipe de vendas
- Adição à sequência de automação de marketing
- Registro de atividade na plataforma de sucesso do cliente
Plataforma de consultoria. Uma plataforma de serviços jurídicos permite que clientes agendem consultorias com advogados. A integração da API:
- Sincroniza agendamentos com o sistema de agendamento interno
- Gera links de reunião do Zoom
- Envia questionário de admissão 24 horas antes
- Cria arquivo de caso quando a reunião é concluída
Agendamento de entrevistas. Uma plataforma de recrutamento usa o Calendly para entrevistas de candidatos. Webhooks:
- Atualizam o ATS com detalhes da entrevista
- Notificam o gerente de contratação por e-mail
- Enviam convites de calendário para todos os participantes
- Rastreiam ausências para acompanhamento
Conclusão
Aqui está o que você aprendeu:
- O Calendly usa OAuth 2.0 para autenticação de API
- Acesse tipos de eventos e eventos agendados via API
- Webhooks fornecem notificações de agendamento em tempo real
- Sempre verifique as assinaturas de webhook para segurança
- Teste com o Apidog antes de conectar a calendários reais
Seus próximos passos:
- Crie um aplicativo OAuth no Calendly
- Implemente o fluxo OAuth
- Configure uma assinatura de webhook
- Teste com payloads simulados no Apidog
- Implante em produção
Teste os webhooks do Calendly com o Apidog - grátis
Perguntas Frequentes
Preciso de um plano pago do Calendly para usar a API?Não. A API está disponível em todos os planos, incluindo o gratuito. No entanto, os planos gratuitos têm recursos limitados. Webhooks estão disponíveis em todos os planos.
Qual a diferença entre webhooks de nível de usuário e de nível de organização?Webhooks de nível de usuário capturam eventos apenas para um usuário. Webhooks de nível de organização capturam eventos para todos os membros da equipe. A maioria das integrações usa o escopo de organização.
Como obtenho o segredo de assinatura do webhook?Quando você cria um webhook via API, a resposta inclui uma signing_key. Armazene isso com segurança. É usado para verificar as assinaturas do webhook.
Posso criar agendamentos via API?Não. O Calendly não possui um endpoint de API para criar agendamentos. Os agendamentos devem ocorrer através da UI do Calendly ou de widgets incorporados. A API é somente leitura para agendamentos.
Como lido com conversões de fuso horário?Todos os timestamps na API estão em UTC (ISO 8601). Converta para a hora local em seu aplicativo. O fuso horário do usuário está disponível no recurso de usuário.
Qual é o limite de taxa?O Calendly não documenta publicamente os limites de taxa. Use padrões de requisição razoáveis. Se você atingir os limites, implemente um backoff exponencial.
Posso obter agendamentos históricos?Sim. Use min_start_time e max_start_time para consultar eventos históricos. Não há limite de quão longe no passado você pode consultar.
Como testo o fluxo OAuth localmente?Use um serviço de tunelamento como o ngrok para expor seu servidor local. Defina a URI de redirecionamento para sua URL ngrok. Complete o fluxo OAuth em um navegador, então inspecione o callback.
