Get Service
curl --request GET \
--url https://api.example.com/api/calendar/v1/public/org/{org_slug}/service/{service_slug} \
--header 'x-kordless-key: <x-kordless-key>'{
"401": {},
"404": {},
"429": {},
"organization": {
"id": "<string>",
"name": "<string>",
"slug": "<string>",
"branding": {}
},
"service": {
"key": "<string>",
"name": "<string>",
"slug": "<string>",
"description": "<string>",
"category": "<string>",
"duration": 123,
"price": 123,
"currency": "<string>",
"isBookablePublic": true,
"metadata": {}
},
"calendarSettings": {
"duration_minutes": 123,
"slot_interval_minutes": 123,
"buffer_before": 123,
"buffer_after": 123,
"booking_window_days": 123,
"timezone": "<string>",
"location": {},
"max_parallel_bookings": 123,
"cancellation_policy": {}
}
}Services
Get Service
Get service details and calendar settings
GET
/
api
/
calendar
/
v1
/
public
/
org
/
{org_slug}
/
service
/
{service_slug}
Get Service
curl --request GET \
--url https://api.example.com/api/calendar/v1/public/org/{org_slug}/service/{service_slug} \
--header 'x-kordless-key: <x-kordless-key>'{
"401": {},
"404": {},
"429": {},
"organization": {
"id": "<string>",
"name": "<string>",
"slug": "<string>",
"branding": {}
},
"service": {
"key": "<string>",
"name": "<string>",
"slug": "<string>",
"description": "<string>",
"category": "<string>",
"duration": 123,
"price": 123,
"currency": "<string>",
"isBookablePublic": true,
"metadata": {}
},
"calendarSettings": {
"duration_minutes": 123,
"slot_interval_minutes": 123,
"buffer_before": 123,
"buffer_after": 123,
"booking_window_days": 123,
"timezone": "<string>",
"location": {},
"max_parallel_bookings": 123,
"cancellation_policy": {}
}
}Endpoint
GET https://api.kordless.ai/api/calendar/v1/public/org/{org_slug}/service/{service_slug}
Authentication
Your API key
Path Parameters
Your organization slugExample:
acme-salonThe service slugExample:
haircutResponse
Service details
Show Service Object
Show Service Object
Unique service identifier
Service display name
URL-safe service identifier
Service description
Service category
Duration in minutes
Price (if displayed)
Currency code
Whether publicly bookable
Additional service metadata
Calendar configuration for this service
Show Calendar Settings
Show Calendar Settings
Appointment duration in minutes
Time between available slot start times
Buffer time before appointments (minutes)
Buffer time after appointments (minutes)
How far in advance bookings can be made
Default timezone for this service
Where appointments take place
type:onsite,phone,meet_url, orcustomvalue: Address, phone number, or meeting link
Maximum concurrent bookings
Cancellation policy details
noticeHours: Required notice for cancellationpolicyText: Policy description
Examples
curl https://api.kordless.ai/api/calendar/v1/public/org/acme-salon/service/haircut \
-H "x-kordless-key: your_api_key"
Response Example
{
"organization": {
"id": "org_abc123",
"name": "Acme Salon",
"slug": "acme-salon",
"branding": {
"primaryColor": "#6366f1",
"logo": "https://storage.example.com/acme-logo.png",
"companyName": "Acme Salon & Spa"
}
},
"service": {
"key": "haircut",
"name": "Haircut",
"slug": "haircut",
"description": "Professional haircut with wash and style",
"category": "Hair",
"duration": 60,
"price": 45.00,
"currency": "USD",
"isBookablePublic": true,
"metadata": {}
},
"calendarSettings": {
"duration_minutes": 60,
"slot_interval_minutes": 30,
"buffer_before": 0,
"buffer_after": 15,
"booking_window_days": 30,
"timezone": "America/New_York",
"location": {
"type": "onsite",
"value": "123 Main St, Suite 100, New York, NY 10001"
},
"max_parallel_bookings": 1,
"cancellation_policy": {
"noticeHours": 24,
"policyText": "Please cancel at least 24 hours in advance to avoid a cancellation fee."
}
}
}
Building a Service Detail Page
function ServiceDetail({ orgSlug, serviceSlug, onBook }) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
getService(orgSlug, serviceSlug)
.then(setData)
.finally(() => setLoading(false));
}, [orgSlug, serviceSlug]);
if (loading) return <Spinner />;
if (!data) return <NotFound />;
const { organization, service, calendarSettings } = data;
return (
<div className="service-detail">
<header>
<h1>{service.name}</h1>
<p className="org-name">{organization.name}</p>
</header>
<section className="details">
<p className="description">{service.description}</p>
<div className="info-grid">
<div className="info-item">
<span className="label">Duration</span>
<span className="value">{service.duration} minutes</span>
</div>
{service.price && (
<div className="info-item">
<span className="label">Price</span>
<span className="value">
${service.price.toFixed(2)} {service.currency}
</span>
</div>
)}
{calendarSettings.location && (
<div className="info-item">
<span className="label">Location</span>
<span className="value">
{calendarSettings.location.type === 'onsite' && '📍 '}
{calendarSettings.location.type === 'phone' && '📞 '}
{calendarSettings.location.type === 'meet_url' && '💻 '}
{calendarSettings.location.value}
</span>
</div>
)}
</div>
{calendarSettings.cancellation_policy?.policyText && (
<div className="cancellation-policy">
<h3>Cancellation Policy</h3>
<p>{calendarSettings.cancellation_policy.policyText}</p>
</div>
)}
</section>
<button onClick={onBook} className="book-button">
Book {service.name}
</button>
</div>
);
}
Using Calendar Settings
The calendar settings help you build accurate booking experiences:const { calendarSettings } = await getService(orgSlug, serviceSlug);
// Calculate booking window
const maxBookingDate = new Date();
maxBookingDate.setDate(maxBookingDate.getDate() + calendarSettings.booking_window_days);
// Show location appropriately
function formatLocation(location) {
switch (location.type) {
case 'onsite':
return `In-person at ${location.value}`;
case 'phone':
return `Phone call to ${location.value}`;
case 'meet_url':
return `Video call: ${location.value}`;
default:
return location.value;
}
}
// Display cancellation policy
if (calendarSettings.cancellation_policy) {
const { noticeHours, policyText } = calendarSettings.cancellation_policy;
showPolicy({
title: `${noticeHours}-hour cancellation notice required`,
details: policyText
});
}
Errors
Invalid or missing API key
{
"detail": "Missing x-kordless-key header"
}
Organization or service not found
{
"detail": "Service not found"
}
Rate limit exceeded
Related Endpoints
Get Organization
Get all services
Get Availability
Query available time slots
Create Booking
Book this service
Bookings Overview
Learn about bookings
⌘I

