LinkyCal API Documentation
Everything you need to integrate forms, booking, and contact management into your product.
Installation
The fastest way to add LinkyCal to your site is with the embeddable widgets. Drop in a script tag and initialize with your project slug.
<!-- Booking Widget -->
<script src="https://cdn.linkycal.com/widgets/booking.js"></script>
<script>
LinkyCal.booking({
projectSlug: "your-project",
container: "#booking-widget"
});
</script>
<!-- Form Widget -->
<script src="https://cdn.linkycal.com/widgets/form.js"></script>
<script>
LinkyCal.form({
projectSlug: "your-project",
formSlug: "contact",
container: "#form-widget"
});
</script>
Quick Start
Get up and running in four steps:
- Create a project in the dashboard
- Create an event type or form
- Get your API key from MCP & APIs in the dashboard sidebar
- Start making API calls
# Check available slots
curl -H "Authorization: Bearer lc_live_your_api_key" \
"https://linkycal.com/api/v1/availability/your-project?date=2026-03-24&timezone=UTC&eventTypeSlug=consultation"
How It Works
Every interaction with LinkyCal follows a straightforward request/response flow:
- Client sends request to LinkyCal API
- Server validates input and checks availability/form config
- Action is performed (booking created, form step submitted, etc.)
- Response returned with result
- Optional: workflow triggers fire (email, webhook, tag)
Create Response
POST /api/v1/forms/:projectSlug/:formSlug/responses
Start a new form response. Returns the response object and full form config including all steps and fields.
curl -X POST "https://linkycal.com/api/v1/forms/acme/contact/responses" \
-H "Content-Type: application/json"
{
"response": {
"id": "resp_a1b2c3d4",
"formId": "form_x1y2z3",
"currentStepIndex": 0,
"status": "in_progress"
},
"form": {
"id": "form_x1y2z3",
"name": "Contact Form",
"steps": [
{
"id": "step_1",
"title": "Your Details",
"fields": [
{ "id": "fld_1", "type": "text", "label": "Full Name", "required": true },
{ "id": "fld_2", "type": "email", "label": "Email", "required": true }
]
}
]
}
}
Submit Step
PATCH /api/v1/forms/:projectSlug/:formSlug/responses/:responseId/steps/:stepIndex
Submit field values for a specific step. Steps must be submitted in order (0, 1, 2...). When the last step is submitted, the response is automatically marked as completed.
curl -X PATCH "https://linkycal.com/api/v1/forms/acme/contact/responses/resp_a1b2c3d4/steps/0" \
-H "Content-Type: application/json" \
-d '{
"fields": [
{ "fieldId": "fld_1", "value": "Jane Smith" },
{ "fieldId": "fld_2", "value": "jane@example.com" }
]
}'
{
"response": {
"id": "resp_a1b2c3d4",
"status": "in_progress",
"currentStepIndex": 1,
"completedAt": null
}
}
Native HTML Form
POST /api/public/forms/:projectSlug/:formSlug/submit
Post a regular browser form directly to LinkyCal without any client-side JavaScript. LinkyCal returns a hosted thank-you page by default, or a redirect if you configure one in the form builder.
<form action="https://linkycal.com/api/public/forms/acme/contact/submit" method="post">
<input type="text" name="full_name" required />
<input type="email" name="email" required />
<textarea name="message"></textarea>
<button type="submit">Send</button>
</form>
Get Form Config
GET /api/widget/form/:projectSlug/:formSlug/config
Returns the full form structure with steps, fields, and validation rules. This is the same endpoint used internally by the form widget.
curl "https://linkycal.com/api/widget/form/acme/contact/config"
{
"form": {
"id": "form_x1y2z3",
"name": "Contact Form",
"slug": "contact",
"steps": [
{
"id": "step_1",
"title": "Your Details",
"fields": [
{ "id": "fld_1", "type": "text", "label": "Full Name", "required": true },
{ "id": "fld_2", "type": "email", "label": "Email", "required": true },
{ "id": "fld_3", "type": "phone", "label": "Phone", "required": false }
]
}
]
}
}
Check Availability
GET /api/v1/availability/:projectSlug
Returns available time slots for a given event type on a specific date. Use this to display available times to your users before creating a booking.
curl -H "Authorization: Bearer lc_live_your_api_key" \
"https://linkycal.com/api/v1/availability/acme?date=2026-03-24&timezone=UTC&eventTypeSlug=consultation"
{
"slots": [
{ "start": "2026-03-24T09:00:00Z", "end": "2026-03-24T09:30:00Z" },
{ "start": "2026-03-24T10:00:00Z", "end": "2026-03-24T10:30:00Z" }
],
"date": "2026-03-24",
"timezone": "UTC"
}
Create Booking
POST /api/v1/bookings
Create a new booking for an available time slot. The system validates slot availability before confirming. A confirmation email is automatically sent to the guest.
curl -X POST "https://linkycal.com/api/v1/bookings" \
-H "Authorization: Bearer lc_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"projectSlug": "acme",
"eventTypeSlug": "consultation",
"startTime": "2026-03-24T09:00:00Z",
"name": "Jane Smith",
"email": "jane@example.com",
"phone": "+1-555-0123",
"notes": "Looking forward to our meeting",
"timezone": "America/New_York"
}'
{
"booking": {
"id": "bk_abc123",
"eventTypeId": "et_xyz789",
"name": "Jane Smith",
"email": "jane@example.com",
"phone": "+1-555-0123",
"startTime": "2026-03-24T09:00:00Z",
"endTime": "2026-03-24T09:30:00Z",
"timezone": "America/New_York",
"status": "confirmed",
"notes": "Looking forward to our meeting",
"createdAt": "2026-03-23T20:00:00Z"
}
}
Cancel Booking
PATCH /api/projects/:projectId/bookings/:bookingId/cancel
Cancel an existing booking. The booking status is set to cancelled. If connected to Google Calendar, the calendar event is also removed.
curl -X PATCH "https://linkycal.com/api/projects/proj_123/bookings/bk_abc123/cancel" \
-H "Cookie: session=your_session_cookie"
{
"booking": {
"id": "bk_abc123",
"status": "cancelled",
"cancelledAt": "2026-03-24T08:00:00Z"
}
}
List Contacts
GET /api/projects/:projectId/contacts
Retrieve all contacts for a project, with optional search and tag filtering.
{
"contacts": [
{
"id": "ct_m1n2o3",
"name": "Jane Smith",
"email": "jane@example.com",
"phone": "+1-555-0123",
"tags": ["lead", "vip"],
"createdAt": "2026-03-20T10:00:00Z"
}
]
}
Create Contact
POST /api/projects/:projectId/contacts
Create a new contact in your project. Contacts are also created automatically when a form is submitted or a booking is made.
curl -X POST "https://linkycal.com/api/projects/proj_123/contacts" \
-H "Content-Type: application/json" \
-H "Cookie: session=your_session_cookie" \
-d '{
"name": "Jane Smith",
"email": "jane@example.com",
"phone": "+1-555-0123",
"notes": "Met at conference"
}'
{
"contact": {
"id": "ct_p4q5r6",
"name": "Jane Smith",
"email": "jane@example.com",
"phone": "+1-555-0123",
"notes": "Met at conference",
"createdAt": "2026-03-24T14:00:00Z"
}
}
Update Contact
PUT /api/projects/:projectId/contacts/:contactId
Update an existing contact's information. Only provided fields are updated.
curl -X PUT "https://linkycal.com/api/projects/proj_123/contacts/ct_p4q5r6" \
-H "Content-Type: application/json" \
-H "Cookie: session=your_session_cookie" \
-d '{
"name": "Jane Smith-Doe",
"notes": "Updated: now a paying customer"
}'
{
"contact": {
"id": "ct_p4q5r6",
"name": "Jane Smith-Doe",
"email": "jane@example.com",
"phone": "+1-555-0123",
"notes": "Updated: now a paying customer",
"updatedAt": "2026-03-24T15:00:00Z"
}
}
Booking Widget
Embed a fully functional booking experience on any page. The widget handles event type selection, date/time picking, and form submission.
<div id="booking-widget"></div>
<script src="https://cdn.linkycal.com/widgets/booking.js"></script>
<script>
LinkyCal.booking({
projectSlug: "acme",
container: "#booking-widget",
eventTypeSlug: "consultation",
theme: {
primaryColor: "#1B4332"
}
});
</script>
Form Widget
Embed multi-step forms directly on your site. The widget renders each step in sequence and handles validation, submission, and completion state.
<div id="form-widget"></div>
<script src="https://cdn.linkycal.com/widgets/form.js"></script>
<script>
LinkyCal.form({
projectSlug: "acme",
formSlug: "contact",
container: "#form-widget",
theme: {
primaryColor: "#1B4332"
}
});
</script>
Customization
Both widgets accept a theme object to match your brand. Override colors, border radius, and fonts.
LinkyCal.booking({
projectSlug: "acme",
container: "#booking-widget",
theme: {
primaryColor: "#1B4332",
borderRadius: "12px",
fontFamily: "Inter, sans-serif"
}
});
Triggers
Workflows start with a trigger. When the trigger event occurs, all connected actions execute in sequence.
Actions
Actions are the steps executed when a workflow is triggered. Chain multiple actions together with conditions and delays.
Webhook Events
When a workflow's webhook action fires, it sends a POST request to your configured URL with a JSON payload describing the event.
{
"event": "form_submitted",
"timestamp": "2026-03-24T14:00:00Z",
"data": {
"formId": "form_x1y2z3",
"responseId": "resp_a1b2c3d4",
"contactId": "ct_m1n2o3"
}
}
MCP Server
LinkyCal ships a built-in Model Context Protocol server, so AI agents like Claude can check availability, book meetings, manage contacts, and inspect forms on your behalf. It speaks Streamable HTTP at a single endpoint:
https://linkycal.com/api/mcp
Sessions authenticate with a project API key passed as a Bearer token. Every tool is hard-scoped to that key's project — agents never pass a project ID and can never reach data outside the project the key belongs to.
Connecting
Create an API key in the dashboard under MCP & APIs, then register the server with your MCP client. With Claude Code:
claude mcp add --transport http linkycal https://linkycal.com/api/mcp \
--header "Authorization: Bearer lc_live_a1b2c3d4e5f6..."
For other MCP clients, add the server to your configuration file:
{
"mcpServers": {
"linkycal": {
"type": "http",
"url": "https://linkycal.com/api/mcp",
"headers": {
"Authorization": "Bearer lc_live_a1b2c3d4e5f6..."
}
}
}
}
Available Tools
The server exposes 30 tools mirroring the REST API, grouped by domain. Read tools return JSON; write tools enforce the same plan limits and validation as the dashboard.
API Keys
Create API keys in the dashboard under MCP & APIs. Include your key in the Authorization header as a Bearer token with every request.
curl -H "Authorization: Bearer lc_live_a1b2c3d4e5f6..." \
"https://linkycal.com/api/v1/availability/your-project?date=2026-03-24&eventTypeSlug=consultation"
Rate Limits
The API enforces per-IP rate limits to ensure fair usage. If you exceed the limit, you'll receive a 429 Too Many Requests response.
Error Handling
All errors return a JSON object with a descriptive error field. Use the HTTP status code to determine the type of error.
{
"error": "Descriptive error message"
}
Common status codes:
Pagination
Currently, list endpoints return all results. Cursor-based pagination will be added in a future release with cursor and limit query parameters.
Webhooks
Configure webhooks via workflow actions to receive real-time notifications about events in your project. Create a workflow with a trigger (e.g. form_submitted) and add a webhook action pointing to your URL.
{
"trigger": "booking_created",
"actions": [
{
"type": "webhook",
"config": {
"url": "https://your-app.com/webhooks/linkycal",
"method": "POST",
"headers": {
"X-Webhook-Secret": "your_secret"
}
}
}
]
}
Ready to integrate?
Get your API key and start building with LinkyCal's forms, booking, and contact APIs today.