Meetvanta developer API

Authentication and scope

Create a workspace key as a verified owner/admin. Copy the secret once. Only its hash is stored. Send Authorization: Bearer mv_live_… from your server, never browser JavaScript or an embed. Scopes are events:read, availability:read, bookings:read, bookings:write, analytics:read and audit:read. Audit search/export requires a bounded UTC start/end window; see OpenAPI. Revocation, expiry, workspace archive, creator removal or loss of admin access denies future requests. An in-flight request already accepted may finish.

Routes

MethodPath (under /api/v1)
GET/audit
GET/audit/export
GET/event-types
GET/event-types/{id}
GET/event-types/{id}/availability
GET/bookings
POST/bookings
GET/bookings/{id}
POST/bookings/{id}/cancel
POST/bookings/{id}/reschedule
GET/analytics/booking-funnel
GET/public/{workspaceSlug}/{eventSlug}
GET/public/{workspaceSlug}/{eventSlug}/availability
POST/public/{workspaceSlug}/{eventSlug}/bookings

Pagination, errors and retry safety

List endpoints return data and nextCursor. Limit is 1–100 (default 25); use the returned cursor for the same tenant/resource. JSON bodies are bounded to 20 KB. Errors use application/problem+json with type, title, status and detail. 401 means inactive/missing key, 403 wrong scope, 404 inaccessible resource, 409 conflicting booking or changed idempotency content, and 429 means wait 60 seconds. Booking, cancel and reschedule POSTs require an 8–200 character Idempotency-Key. Reuse the same key/content until a result is known; never replay a key for a new request. Domain booking/outbox commits are atomic; completed retry responses are stable. Contacts and keys are absent from listing/error projections.

Availability and limits

Use inclusive startDate, exclusive endDate (YYYY-MM-DD, maximum 31 days), and an IANA timezone. UTC slot starts are authoritative; unverified configured calendars fail closed. Rate limits: 120 requests/key/minute, 600/workspace/minute; anonymous event routes share a 120 read or 20 write budget per event/minute. These are shared PostgreSQL fixed-window budgets, not process-local limits. Trusted deployment IP limits remain a release configuration gate. Anonymous routes need no API key; secret-link events remain accessible only to people who possess their exact link.

Server-side examples

// Node.js 24. Keep the key in a server-side environment variable.
const base = process.env.MEETVANTA_API_ORIGIN;
const response = await fetch(base + '/api/v1/event-types?limit=25', {
  headers: { Authorization: 'Bearer ' + process.env.MEETVANTA_API_KEY }
});
if (!response.ok) throw new Error('API status ' + response.status);
const { data, nextCursor } = await response.json();
console.log(data.map(event => ({ id: event.id, title: event.title })));
// Reuse key AND body after a timeout. Never generate a new key for a retry.
const key = crypto.randomUUID();
const response = await fetch(base + '/api/v1/bookings', {
  method: 'POST',
  headers: { Authorization: 'Bearer ' + process.env.MEETVANTA_API_KEY,
    'Content-Type': 'application/json', 'Idempotency-Key': key },
  body: JSON.stringify({ eventTypeId, start: availableStart, timezone: 'UTC',
    invitee: { name: 'Invitee', email: 'invitee@example.com' }, answers: [] })
}); // Treat returned management URLs as secret invitee capabilities.

Runnable repository example: scripts/developer-api-example.mjs (read-only listing). Pass eventTypeId and a server-returned available start to adapt the booking example; select a slot again after a conflict.

Webhook verification and recovery

Create a public HTTPS endpoint on port 443 and choose booking.confirmed, booking.canceled or booking.rescheduled. Verify the exact raw bytes using HMAC-SHA256 over webhook-id + "." + webhook-timestamp + "." + body, using the decoded whsec_ base64 secret. Require v1 signature and timestamp within five minutes; compare in constant time. IDs and body bytes stay stable across retries, timestamps refresh. Store processed event IDs durably at your receiver; expect at-least-once and out-of-order delivery. Respond with any 2xx after durable processing. Failures retry for at least 24 hours from first claim, then become dead-letter entries. Owners/admins can inspect safe attempt history and request audited resend. Pause/archive or destination/filter edits invalidate affected queued deliveries. The receiver sample in scripts/webhook-consumer.mjs rejects invalid signatures and deduplicates persistently with SQLite; its no-op processing demonstrates the contract, not your business transaction.

Privacy and public readiness

Funnel browser events contain only bounded stage names and hashed ephemeral dedupe IDs, honor Do Not Track and store no contacts/cookies. Browser stage counts are observations, not unique-visitor attribution. Booking lifecycle and workflow states derive from durable records. Appointment payment and payment analytics are deferred; free booking remains available. Public deployment, real email/Calendar consent and controlled HTTPS receiver verification are separate acceptance gates.