# Errors Source: https://docs.novacal.io/api-reference/errors Understand Novacal API error responses, HTTP status codes, and the JSON error format returned when requests fail or validation does not pass. The API uses standard HTTP status codes and returns error responses in a consistent JSON format. ## Error Response Format All error responses follow this structure: ```json theme={null} { "success": false, "error": { "code": "error_code", "message": "Human-readable error message", "details": {} } } ``` The `details` field is optional and typically only included for validation errors. ## Error Codes ### 401 Unauthorized Returned when authentication is required but not provided or invalid. ```json theme={null} { "success": false, "error": { "code": "unauthenticated", "message": "Unauthenticated." } } ``` ### 403 Forbidden Returned when the authenticated user doesn't have sufficient permissions to perform the requested action. ```json theme={null} { "success": false, "error": { "code": "access_denied", "message": "Access denied." } } ``` Or when the user lacks required abilities: ```json theme={null} { "success": false, "error": { "code": "missing_ability", "message": "Insufficient privileges." } } ``` ### 404 Not Found Returned when the requested resource doesn't exist. ```json theme={null} { "success": false, "error": { "code": "resource_not_found", "message": "Resource not found." } } ``` Or: ```json theme={null} { "success": false, "error": { "code": "not_found", "message": "Not found." } } ``` ### 405 Method Not Allowed Returned when the HTTP method used is not allowed for the requested endpoint. ```json theme={null} { "success": false, "error": { "code": "method_not_allowed", "message": "Method not allowed." } } ``` ### 422 Unprocessable Content Returned when the request data fails validation. ```json theme={null} { "success": false, "error": { "code": "validation_failed", "message": "The given data was invalid.", "details": { "name": [ "The name field is required." ], "slug": [ "The slug has already been taken." ] } } } ``` ### 500 Internal Server Error Returned when an unexpected server error occurs. ```json theme={null} { "success": false, "error": { "code": "internal_server_error", "message": "Internal server error." } } ``` ### Other HTTP Exceptions For other HTTP exceptions, the API returns: ```json theme={null} { "success": false, "error": { "code": "http_exception", "message": "An error occurred." } } ``` The status code will match the HTTP exception status code. # Introduction Source: https://docs.novacal.io/api-reference/introduction Learn how the Novacal API works, how authentication is handled, and what to expect from requests and responses. ## 1. Base URL The Novacal API follows standard REST conventions and is available only over HTTPS to protect request data and credentials in transit. Plain HTTP is not supported. Use the following base URL for all API requests: ```bash theme={null} https://api.novacal.io ``` ## 2. Create an API key The Novacal API uses API keys to authenticate requests. If a request is sent without a valid API key, the API will return an authentication error. Create an API key from the [API Keys settings page](https://app.novacal.io/settings/api-keys), then include it as a bearer token in your request headers: ```bash theme={null} Authorization: Bearer YOUR_API_KEY ``` ## 3. Test authentication Make a simple authenticated request to confirm your API key is working: ```bash theme={null} curl --request GET \ --url https://api.novacal.io/v1/users/me \ --header "Authorization: Bearer YOUR_API_KEY" \ --header "Accept: application/json" ``` If the request succeeds, your API key is valid and you are ready to continue. ## Response format Successful responses use this shape: ```json theme={null} { "success": true, "data": {} } ``` ## Rate limits The default limit is `60 requests per minute` per API key. If you exceed that, the API returns `429 Too Many Requests`. ## Next steps * Connect an MCP client with [MCP](/api-reference/mcp) * Explore the full [Events reference](/api-reference/v1/events/get) * Explore the full [Event Types reference](/api-reference/v1/event-types/get) * Review [Errors](/api-reference/errors) # MCP Source: https://docs.novacal.io/api-reference/mcp Connect Novacal to MCP-compatible clients using the hosted Novacal MCP server, enabling authenticated integration between Novacal and supported AI tools through a remote MCP endpoint. ## Hosted endpoint Use the hosted Novacal MCP server at: ```txt theme={null} https://mcp.novacal.io/mcp ``` The server uses Streamable HTTP and is intended for MCP-compatible clients. ## Authentication The MCP server uses OAuth for the MCP connection. During the first connection, you will be sent to a Novacal authorize page. On that page, enter your Novacal API key from: [https://app.novacal.io/settings/api-keys](https://app.novacal.io/settings/api-keys) The MCP server verifies the key with the Novacal API, stores it, and then uses it for future tool calls on your behalf. ## Set up in Claude To connect Novacal in Claude: 1. Open Claude and add a new custom connector. 2. Enter the MCP server URL: ```txt theme={null} https://mcp.novacal.io/mcp ``` 3. Choose `OAuth` as the authentication method. 4. Leave `Client ID` and `Client Secret` empty. 5. Continue the OAuth flow. 6. When the Novacal authorize page opens, paste your Novacal API key. 7. Finish the connection. ## Available tools The current MVP toolset includes: * `get_event_types` * `get_event_type` * `create_event_type` * `get_availability` * `get_events` * `create_event` * `cancel_event` * `reschedule_event` ## Example prompts * `Show my Novacal event types.` * `Show my Novacal event types and include their IDs.` * `Get my upcoming Novacal events.` * `Check my availability for event type 123 from 2026-06-01 to 2026-06-07.` * `Create a new one-on-one event type named Intro Call, 30 minutes long, hidden from profile, with color #2563EB.` * `Cancel Novacal event 456 because the attendee requested to reschedule.` * `Reschedule Novacal event 456 to June 2, 2026 at 14:00 Europe/Belgrade.` ## Notes * Each user should use their own Novacal API key. * If the saved API key is revoked or becomes invalid, reconnect and authorize again. # Get Availability Source: https://docs.novacal.io/api-reference/v1/availability/get GET /v1/availability Retrieve availability ranges for a Novacal event type across a selected date window so you can show bookable times in your app. ```bash cURL theme={null} curl --request GET \ --url 'https://api.novacal.io/v1/availability?start=2026-05-29&end=2026-05-30&event_type_id=123&timezone=UTC' \ --header 'Authorization: Bearer ' ``` Pass `timezone` as an optional IANA timezone, such as `Europe/Belgrade`, to receive availability ranges converted to that timezone. If omitted, the response uses `UTC`. # Create Booking Form Field Source: https://docs.novacal.io/api-reference/v1/booking-forms/create POST /v1/event-types/{eventType}/booking-forms Create a new booking form field for a Novacal event type, including label, field type, placeholder, required state, and options. # Delete Booking Form Field Source: https://docs.novacal.io/api-reference/v1/booking-forms/delete DELETE /v1/event-types/{eventType}/booking-forms/{field} Delete a booking form field from a Novacal event type by field ID and review the endpoint path, auth requirements, and success response. # Get Booking Form Fields Source: https://docs.novacal.io/api-reference/v1/booking-forms/get GET /v1/event-types/{eventType}/booking-forms List all booking form fields for a Novacal event type, including labels, input types, placeholders, display order, and options. # Update Booking Form Field Source: https://docs.novacal.io/api-reference/v1/booking-forms/update PUT /v1/event-types/{eventType}/booking-forms/{field} Update a Novacal booking form field and change its label, input type, placeholder, required state, active status, order, or options. # Update Booking Form Field Order Source: https://docs.novacal.io/api-reference/v1/booking-forms/update-order PUT /v1/event-types/{eventType}/booking-forms/update-order Reorder booking form fields for a Novacal event type by updating field positions in a single API request with ordered IDs. # Create Contact Source: https://docs.novacal.io/api-reference/v1/contacts/create POST /v1/contacts Add a contact to your Novacal account with a name, email, and timezone. ## What this endpoint is for Add someone to your contacts manually, rather than waiting for them to book. Only `email` is required. ## Notes * If you already have a contact with the same email, its name and timezone are updated instead of creating a duplicate. * The contact is attached to your account. It does not affect other users or teams. # Delete Contact Source: https://docs.novacal.io/api-reference/v1/contacts/delete DELETE /v1/contacts/{id} Delete a contact from your Novacal account. ## What this endpoint is for Permanently remove a contact from your account. This does not delete any events the person booked. ## Access You can only delete your own contacts. Deleting another account's contact returns `403 access_denied`. # Get Contact Source: https://docs.novacal.io/api-reference/v1/contacts/find GET /v1/contacts/{id} Retrieve a single Novacal contact by ID. ## What this endpoint is for Fetch a single contact when you already have its ID. ## Access You can only retrieve your own contacts. Requesting another account's contact returns `403 access_denied`. # Get Contacts Source: https://docs.novacal.io/api-reference/v1/contacts/get GET /v1/contacts List the contacts on your Novacal account, with search by name or email and pagination metadata. ## What this endpoint returns This endpoint returns your contacts. Results are always paginated: the contacts for the current page live in `data.data`, alongside `current_page`, `per_page`, and `total`. ## Filtering and pagination | Parameter | Description | | ---------- | ------------------------------------------------------------- | | `query` | Return only contacts whose name or email contains this string | | `page` | The page of results to return. Defaults to `1` | | `per_page` | Contacts per page, between 1 and 100. Defaults to `15` | ## Common use cases * Sync your Novacal contacts into a CRM * Look up a contact by email before creating a booking * Build an internal address book from your bookers # Update Contact Source: https://docs.novacal.io/api-reference/v1/contacts/update PUT /v1/contacts/{id} Update a Novacal contact's name, email, or timezone. ## What this endpoint is for Change a contact's details. Send only the fields you want to change. ## Access You can only update your own contacts. Updating another account's contact returns `403 access_denied`. # Create Event Type Source: https://docs.novacal.io/api-reference/v1/event-types/create POST /v1/event-types Create a new Novacal event type with settings for duration, availability, booking limits, buffers, redirects, and booking form fields. ## What you can create Use this endpoint to create a new event type that controls how people book time with you in Novacal. ## Configuration areas * Core details such as name, slug, and duration * Scheduling rules such as buffers, limits, and availability * Booking flow settings such as redirects and booking form fields # Delete Event Type Source: https://docs.novacal.io/api-reference/v1/event-types/delete DELETE /v1/event-types/{id} Delete a Novacal event type by ID and review the endpoint path, authentication requirements, and no-content success response. # Get Event Type Source: https://docs.novacal.io/api-reference/v1/event-types/find GET /v1/event-types/{id} Retrieve one Novacal event type by ID, including its scheduling settings, booking limits, visibility, and active booking form fields. ## What this endpoint is for Use this endpoint to retrieve one specific event type when you already know its ID. ## Returned details * Scheduling configuration and booking limits * Visibility and booking behavior settings * Active booking form fields associated with the event type # Get Event Types Source: https://docs.novacal.io/api-reference/v1/event-types/get GET /v1/event-types List the Novacal event types available to the authenticated user, including names, durations, visibility settings, and form fields. ## What this endpoint returns This endpoint lists the event types the authenticated user can access in Novacal. Use the optional `scope` query parameter when you only want one ownership type: * `scope=personal` returns event types owned by the authenticated user * `scope=team` returns team event types ## Common use cases * Populate an internal event type selector * Sync booking configuration into another system * Review visibility, duration, and booking form settings across event types # Update Event Type Source: https://docs.novacal.io/api-reference/v1/event-types/update PUT /v1/event-types/{id} Update an existing Novacal event type and change scheduling rules, limits, colors, visibility, redirects, and related configuration. ## When to use this endpoint Use this endpoint to update an existing event type without recreating it from scratch. ## Typical changes * Adjust duration, buffers, and scheduling limits * Update colors, visibility, or redirect behavior * Change configuration tied to the booking experience # Cancel Event Source: https://docs.novacal.io/api-reference/v1/events/cancel PUT /v1/events/{id}/cancel Cancel an existing Novacal event with the API, including the required public authentication flow and optional cancellation reason payload. This endpoint requires a public API bearer token. The authenticated API key identifies the caller integration. It does not replace the existing event booker. ## When to use this endpoint Use this endpoint to cancel a booked event from your own application or integration flow. ## Cancellation notes * Pass the correct event ID for the booking you want to cancel * Include a cancellation reason when your workflow needs to preserve context * Use the response payload to confirm the event status after the request succeeds ## Access The authenticated user must be the organizer or a host of the event. Canceling an event you do not host returns `403 access_denied`. # Book Event Source: https://docs.novacal.io/api-reference/v1/events/create POST /v1/events Book a new Novacal event with the public API by sending the event type, selected time, attendee answers, timezone, and location data. This endpoint requires a public API bearer token. The authenticated API key identifies the caller integration. The event booker is still created from the submitted booking payload, for example `form_field_answers.name` and `form_field_answers.email`. ## When to use this endpoint Use this endpoint when you want to create a new booking from your own product, widget, or backend workflow. Common use cases include: * Creating a booking after a customer selects a time in your app * Passing attendee answers collected in a custom booking flow * Saving the selected timezone and meeting location in the same request ## Authentication notes This route uses a public API bearer token. The token authenticates your integration, while the attendee details still come from the booking payload you submit. # Get Event Source: https://docs.novacal.io/api-reference/v1/events/find GET /v1/events/{id} Retrieve a single Novacal event by ID and inspect its booking details, timing, status, organizer, guests, and submitted form answers. ## What this endpoint is for Use this endpoint when you already have an event ID and need the full event payload for that specific booking. ## Typical use cases * Show booking details inside an admin view * Inspect the current event status before allowing a change * Read submitted answers, attendee details, and organizer information # Get Events Source: https://docs.novacal.io/api-reference/v1/events/get GET /v1/events List the Novacal events the authenticated user can access, including scheduling details, attendees, hosts, and current event status. ## What this endpoint returns This endpoint returns the events the authenticated user hosts or organizes. Use it to review scheduled meetings, sync event data into your own system, or build internal dashboards. Results are always paginated. The `data` object holds the events for the current page in `data.data`, alongside pagination metadata such as `current_page`, `last_page`, `per_page`, and `total`. ## Filtering and pagination | Parameter | Description | | ----------------- | --------------------------------------------------------------------------------------- | | `status` | `active` returns events that have not been canceled, `canceled` returns canceled events | | `start` | Only return events ending on or after this date, for example `2026-07-01` | | `end` | Only return events ending on or before this date. Must be after `start` | | `page` | The page of results to return. Defaults to `1` | | `per_page` | Events per page, between 1 and 100. Defaults to `15` | | `order_direction` | Sort direction for the event start time, `asc` or `desc`. Defaults to `asc` | ```bash theme={null} curl --request GET \ --url "https://api.novacal.io/v1/events?status=active&start=2026-07-01&end=2026-07-31&per_page=50" \ --header "Authorization: Bearer YOUR_API_KEY" \ --header "Accept: application/json" ``` Paginate by requesting the next page until `next_page_url` is `null`. ## Common use cases * Load a list of upcoming or past events * Sync Novacal bookings into a CRM or reporting workflow * Pull only the bookings for a given month with `start` and `end` * Reconcile cancellations by requesting `status=canceled` * Review attendee, host, and event status data before follow-up actions # Reschedule Event Source: https://docs.novacal.io/api-reference/v1/events/update PUT /v1/events/{id} Reschedule an existing Novacal event with the public API by updating the start time, end time, timezone, and allowed booking answers. This endpoint requires a public API bearer token. The authenticated API key identifies the caller integration. It does not replace the existing event booker. ## When to use this endpoint Use this endpoint when an existing booking needs to move to a different time or timezone without creating a brand new event record. ## Before you reschedule * Confirm you are targeting the correct event ID * Submit the updated scheduling fields you want to change * Keep in mind that the authenticated token identifies the integration, not the attendee ## Access The authenticated user must be the organizer or a host of the event. Rescheduling an event you do not host returns `403 access_denied`. # Get Team Source: https://docs.novacal.io/api-reference/v1/teams/find GET /v1/teams/{id} Retrieve a single Novacal team by ID, including its name, username, branding details, and other team profile information. # Get Teams Source: https://docs.novacal.io/api-reference/v1/teams/get GET /v1/teams List all Novacal teams the authenticated user belongs to and review the team data returned by the teams collection endpoint. # Get Current User Source: https://docs.novacal.io/api-reference/v1/users/me GET /v1/users/me Retrieve the currently authenticated Novacal user, including profile details such as name, email, timezone, avatar, and time format. # Update Current User Source: https://docs.novacal.io/api-reference/v1/users/update-me PUT /v1/users/me Update the authenticated Novacal user's profile, including username, email, name, avatar, timezone, week start, and time format. # Create Webhook Source: https://docs.novacal.io/api-reference/v1/webhooks/create POST /v1/webhooks Register a Novacal webhook to receive real-time notifications when events are booked, rescheduled, or canceled, with a signing secret to verify deliveries. ## What this endpoint is for Register a URL that Novacal calls whenever something happens to an event you host or organize. Webhooks let you react to bookings in real time instead of polling the events endpoint. ## Available events | Event | Sent when | | ------------------- | ------------------------------------------- | | `event.created` | A new event is booked | | `event.rescheduled` | An existing event moves to a different time | | `event.canceled` | An event is canceled | Subscribe to one or more events per webhook. You can register several webhooks pointing at different URLs. ## Delivery format Novacal sends a `POST` request with a JSON body: ```json theme={null} { "event": "event.created", "created_at": "2026-07-14T10:32:11+00:00", "data": { "id": "9b1f...", "event_type_id": 42, "start": "2026-07-20T09:00:00.000000Z", "end": "2026-07-20T09:30:00.000000Z", "status": "scheduled", "organizer": {}, "booker": {}, "guests": [] } } ``` The `data` object is the same event payload returned by the [Get Event](/api-reference/v1/events/find) endpoint. ## Verifying deliveries Every delivery carries two headers: | Header | Description | | --------------------- | ---------------------------------------------------------------------- | | `X-Novacal-Signature` | HMAC SHA-256 of the raw request body, keyed with your webhook `secret` | | `X-Novacal-Event` | The event name, for example `event.created` | Recompute the signature over the raw body and compare it before trusting a request: ```javascript theme={null} import crypto from "crypto"; const expected = crypto .createHmac("sha256", process.env.NOVACAL_WEBHOOK_SECRET) .update(rawBody) .digest("hex"); const valid = crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(request.headers["x-novacal-signature"]) ); ``` Always compare the signature against the **raw** request body, before any JSON parsing or re-serialization. ## Retries Respond with a `2xx` status code to acknowledge a delivery. Novacal retries a failed delivery up to three times with a short backoff, so your endpoint should be idempotent. # Delete Webhook Source: https://docs.novacal.io/api-reference/v1/webhooks/delete DELETE /v1/webhooks/{id} Delete a Novacal webhook to permanently stop event deliveries to its endpoint. ## What this endpoint is for Permanently remove a webhook. Novacal stops sending deliveries to it immediately. ## Before you delete * Deleting a webhook discards its signing secret. Registering the same URL again issues a new secret. * To stop deliveries temporarily, set `is_active` to `false` with the [Update Webhook](/api-reference/v1/webhooks/update) endpoint instead. ## Access You can only delete webhooks registered on your own account. Deleting another account's webhook returns `403 access_denied`. # Get Webhook Source: https://docs.novacal.io/api-reference/v1/webhooks/find GET /v1/webhooks/{id} Retrieve a single Novacal webhook by ID to inspect its target URL, subscribed events, signing secret, and active status. ## What this endpoint is for Use this endpoint when you already have a webhook ID and need its full record, including the signing secret used to verify deliveries. ## Typical use cases * Look up a signing secret when configuring your receiving endpoint * Check which events a webhook is subscribed to * Confirm whether a webhook is active before investigating missing deliveries ## Access You can only retrieve webhooks registered on your own account. Requesting another account's webhook returns `403 access_denied`. # Get Webhooks Source: https://docs.novacal.io/api-reference/v1/webhooks/get GET /v1/webhooks List the webhooks registered on your Novacal account, including their target URL, subscribed events, signing secret, and active status. ## What this endpoint returns This endpoint returns every webhook you have registered, newest first. Each entry includes its target URL, the events it is subscribed to, its signing secret, and whether it is currently active. ## Common use cases * Audit which endpoints are receiving Novacal deliveries * Retrieve a signing secret you need to verify incoming requests * Confirm which webhooks are paused before debugging a missing delivery # Update Webhook Source: https://docs.novacal.io/api-reference/v1/webhooks/update PUT /v1/webhooks/{id} Update a Novacal webhook to change its target URL, adjust which events it subscribes to, or pause deliveries without deleting it. ## What this endpoint is for Change an existing webhook without re-registering it. Send only the fields you want to change. ## What you can change * `url` — move deliveries to a different endpoint * `events` — replace the list of subscribed events * `is_active` — set to `false` to pause deliveries, and back to `true` to resume The signing secret does not change when you update a webhook, so your receiving endpoint keeps working. ## Pausing instead of deleting Set `is_active` to `false` while you deploy or debug your receiver. Novacal stops sending deliveries but keeps the webhook and its secret intact. ## Access You can only update webhooks registered on your own account. Updating another account's webhook returns `403 access_denied`.