Para programadores

API, webhooks e widget, grátis

Consulte horários livres, crie e cancele reservas a partir do seu software, receba um aviso assinado de cada alteração e ponha a sua agenda no seu site. O que outros cobram, aqui é grátis.

Começar grátis · Ir para API e webhooks

Autenticação

Crie uma chave em Definições → API e webhooks. Escolha «Só ler» (tipos de reunião, disponibilidade e reservas) ou «Ler e reservar» (também reservar, alterar, cancelar e criar links de uso único). A chave só é mostrada uma vez.

Envie-a no cabeçalho X-API-Key. Todas as rotas estão em https://calendavibe.com/api/v1. Uma chave só vê e altera os dados da sua própria conta.

Os seus tipos de reunião

curl https://calendavibe.com/api/v1/event-types \
  -H "X-API-Key: cvwh_…"

Rotas

RotaO que fazChave
GET /meA sua conta e o tipo de chaveSó ler
GET /event-typesOs seus tipos de reunião, com o link públicoSó ler
GET /event-types/{id}/slots?from&to&timezoneOs horários livres, tal como a sua página os ofereceSó ler
GET /bookings?status=upcoming|past|cancelled|allAs suas reservas (paginadas com cursor)Só ler
GET /bookings/{id}Uma reservaSó ler
POST /bookingsReservar um horárioLer e reservar
POST /bookings/{id}/rescheduleMudar a horaLer e reservar
POST /bookings/{id}/cancelCancelarLer e reservar
POST /single-use-linksUm link que aceita uma única reservaLer e reservar

Reservar (com Idempotency-Key, para não duplicar se repetir o pedido)

curl -X POST https://calendavibe.com/api/v1/bookings \
  -H "X-API-Key: cvwh_…" -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-1234" \
  -d '{
    "eventTypeId": "ckx…",
    "startTime": "2026-11-03T09:00:00.000Z",
    "guest": { "name": "Ana García", "email": "ana@example.com", "timezone": "Europe/Madrid", "locale": "es" },
    "consent": true
  }'

Regras das reservas

Uma reserva pela API segue as mesmas regras que a sua página: só horários realmente livres (também no seu calendário), e o convidado recebe os seus emails e aparece nos seus contactos.

Envie consent: true quando o convidado tiver aceitado o tratamento dos seus dados no seu formulário.

Se dois sistemas pedirem o mesmo horário ao mesmo tempo, o segundo recebe 409 SLOT_UNAVAILABLE e escolhe outro. Com a mesma Idempotency-Key, um pedido repetido devolve a mesma reserva durante 24 horas.

Uma reunião paga não se reserva pela API: a resposta é 402 PAYMENT_REQUIRED com bookingUrl, o link para o convidado reservar e pagar.

Limites

Plano grátis: 60 chamadas por minuto e 10.000 por dia por conta, e até 10 webhooks. Com o Closevibe, mais.

Acima do limite, a resposta é 429 com o cabeçalho Retry-After.

Os erros têm sempre a forma { "error": { "code", "message" } }.

Webhooks

Em Definições → API e webhooks, adicione um URL de destino (https e público) e escolha os avisos: Nova reserva (meeting.booked), Cancelamento (meeting.cancelled), Mudança de hora (meeting.rescheduled) e Pagamento recebido (meeting.paid).

Cada aviso é um POST com os dados da reserva, nunca o link privado do convidado. Se o seu servidor falhar, tentamos de novo após 1 min, 5 min, 30 min, 2 h, 6 h e 12 h. Após 20 falhas seguidas, o URL é desativado e avisamos por email.

Verifique a assinatura: o cabeçalho X-Webhook-Signature é sha256= seguido do HMAC-SHA256 do corpo tal como chega, com o segredo de assinatura desse URL.

Um aviso

{
  "id": "evt_…",
  "event": "meeting.booked",
  "createdAt": "2026-11-01T10:15:00.000Z",
  "data": {
    "booking": {
      "id": "ckx…", "status": "CONFIRMED",
      "eventType": { "id": "ckx…", "slug": "primera-consulta", "name": "Primera consulta", "duration": 30 },
      "startTime": "2026-11-03T09:00:00.000Z", "endTime": "2026-11-03T09:30:00.000Z", "timezone": "Europe/Madrid",
      "guest": { "name": "Ana García", "email": "ana@example.com", "phone": null, "timezone": "Europe/Madrid", "locale": "es", "notes": null },
      "answers": [{ "question": "Motivo", "answer": "Revisión" }],
      "meetingUrl": "https://meet.google.com/…", "payment": null
    }
  }
}

Verificar a assinatura (Node.js)

const crypto = require('crypto');

// rawBody: the request body exactly as received (a Buffer or string, before JSON.parse).
function isFromCalendaVibe(rawBody, header, secret) {
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  return header && expected.length === header.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(header));
}

Widget para o seu site

Na página ou numa janela pop-up (botão ou bolha), com a sua cor e o seu idioma. Se já conhece o visitante, passe o nome e o email e aparecerão preenchidos. No telemóvel, a janela ocupa o ecrã inteiro e fecha-se com o X ou Esc.

Quando alguém reserva dentro do widget, a sua página recebe o evento calendavibe:booked com a hora e o tipo de reunião.

Na página

<div class="calendavibe-inline" data-url="https://calendavibe.com/ana/primera-consulta"
     data-color="#6d28d9" data-lang="es"></div>
<script src="https://calendavibe.com/embed.js" async></script>

Janela pop-up a partir de um botão ou de uma bolha

<a href="https://calendavibe.com/ana/primera-consulta" data-calendavibe-popup
   data-color="#6d28d9" data-name="Ana García" data-email="ana@example.com">Reservar</a>

<script src="https://calendavibe.com/embed.js" async
        data-calendavibe-bubble="https://calendavibe.com/ana" data-text="Reservar" data-color="#6d28d9"></script>

Perguntas frequentes

Tem algum custo?

Não. A API, os webhooks e o widget são grátis no plano grátis, com os limites acima.

Funciona com o Zapier ou o Make?

Sim: use o módulo HTTP deles com a sua chave para a API, e um webhook do CalendaVibe como acionador.

Posso cobrar uma reunião pela API?

Não: o convidado paga na sua página. A API devolve-lhe o link para lho enviar.