Code Examples
Practical examples for using the WooCommerce Appointments REST API.
JavaScript Examples
Fetch Available Slots
// Fetch available slots for a product
async function getAvailableSlots(productId, startDate, endDate) {
const url = new URL('/wp-json/wc-appointments/v2/slots', window.location.origin);
url.searchParams.set('product_ids', productId);
url.searchParams.set('min_date', startDate);
url.searchParams.set('max_date', endDate);
url.searchParams.set('hide_unavailable', 'true');
const response = await fetch(url);
const data = await response.json();
return data.records || [];
}
// Usage
const slots = await getAvailableSlots(123, '2025-01-01', '2025-01-31');
console.log('Available slots:', slots);
Create Appointment
// Create a new appointment using Application Password
// For server-side or external applications
async function createAppointment(appointmentData, username, appPassword) {
const credentials = btoa(`${username}:${appPassword}`);
const response = await fetch('/wp-json/wc-appointments/v2/appointments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${credentials}`
},
body: JSON.stringify(appointmentData)
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message);
}
return await response.json();
}
// Usage with Application Password
const appointment = await createAppointment({
product_id: 123,
customer_id: 456,
start_date: '2025-12-01 10:00:00',
end_date: '2025-12-01 11:00:00',
status: 'confirmed'
}, 'username', 'app_password');
// Alternative: Create from WordPress admin (uses nonce)
async function createAppointmentFromAdmin(appointmentData) {
const response = await fetch('/wp-json/wc-appointments/v2/appointments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': wpApiSettings.nonce
},
body: JSON.stringify(appointmentData)
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message);
}
return await response.json();
}
List Appointments with Filters
// List appointments for a customer
async function getCustomerAppointments(customerId, dateFrom, dateTo) {
const url = new URL('/wp-json/wc-appointments/v1/appointments', window.location.origin);
url.searchParams.set('customer_id', customerId);
url.searchParams.set('date_from', dateFrom);
url.searchParams.set('date_to', dateTo);
const response = await fetch(url, {
headers: {
'X-WP-Nonce': wpApiSettings.nonce
}
});
return await response.json();
}
// Usage
const appointments = await getCustomerAppointments(
456,
'2025-01-01',
'2025-01-31'
);
Update Appointment Status
// Update appointment status
async function updateAppointmentStatus(appointmentId, newStatus) {
const response = await fetch(
`/wp-json/wc-appointments/v1/appointments/${appointmentId}`,
{
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': wpApiSettings.nonce
},
body: JSON.stringify({
status: newStatus
})
}
);
return await response.json();
}
// Usage
await updateAppointmentStatus(123, 'cancelled');
Server-Sent Events (SSE)
// Connect to SSE stream for real-time updates
function connectToSSE() {
const restBase = wpApiSettings?.root || wcAppointmentsReactCalendar?.restUrl;
const nonce = wcAppointmentsReactCalendar?.nonce;
const lastId = parseInt(localStorage.getItem('wca:lastEventId') || '0', 10);
const url = new URL(restBase.replace(/\/$/, '/') + 'wc-appointments/v2/sse');
if (nonce) url.searchParams.set('nonce', nonce);
if (lastId > 0) url.searchParams.set('since_id', String(lastId));
const eventSource = new EventSource(url.toString(), { withCredentials: true });
eventSource.addEventListener('appointment.created', (e) => {
const data = JSON.parse(e.data);
console.log('New appointment:', data);
localStorage.setItem('wca:lastEventId', data.id);
});
eventSource.addEventListener('appointment.updated', (e) => {
const data = JSON.parse(e.data);
console.log('Appointment updated:', data);
localStorage.setItem('wca:lastEventId', data.id);
});
eventSource.addEventListener('error', (e) => {
console.error('SSE error:', e);
eventSource.close();
setTimeout(connectToSSE, 5000);
});
return eventSource;
}
// Usage
const sse = connectToSSE();
PHP Examples
Get Available Slots
// Get available slots using WordPress HTTP API
function get_available_slots($product_id, $start_date, $end_date) {
$url = add_query_arg([
'product_ids' => $product_id,
'min_date' => $start_date,
'max_date' => $end_date,
'hide_unavailable' => true,
], rest_url('wc-appointments/v2/slots'));
$response = wp_remote_get($url);
if (is_wp_error($response)) {
return [];
}
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
return $data['records'] ?? [];
}
// Usage
$slots = get_available_slots(123, '2025-01-01', '2025-01-31');
Create Appointment via API
// Create appointment using WordPress HTTP API
function create_appointment_via_api($appointment_data) {
$url = rest_url('wc-appointments/v2/appointments');
$response = wp_remote_post($url, [
'headers' => [
'Content-Type' => 'application/json',
'X-WP-Nonce' => wp_create_nonce('wp_rest'),
],
'body' => json_encode($appointment_data),
'cookies' => $_COOKIE,
]);
if (is_wp_error($response)) {
return false;
}
$body = wp_remote_retrieve_body($response);
return json_decode($body, true);
}
// Usage
$appointment = create_appointment_via_api([
'product_id' => 123,
'customer_id' => 456,
'start' => '2025-12-01 10:00',
'end' => '2025-12-01 11:00',
'status' => 'confirmed',
]);
cURL Examples
Get Slots (Public - No Auth Required)
# Get available slots (no authentication needed)
curl "https://example.com/wp-json/wc-appointments/v2/slots?product_ids=123&min_date=2025-01-01&max_date=2025-01-31&hide_unavailable=true"
Create Appointment with Application Password
# Create appointment using Application Password (recommended for testing)
# Get Application Password from Users → Profile → Application Passwords
curl -X POST "https://example.com/wp-json/wc-appointments/v2/appointments" \
-u username:app_password \
-H "Content-Type: application/json" \
-d '{
"product_id": 123,
"customer_id": 456,
"start_date": "2025-12-01 10:00:00",
"end_date": "2025-12-01 11:00:00",
"status": "confirmed"
}'
Create Appointment with WooCommerce API Keys
# Create appointment using WooCommerce API keys (for production)
curl -X POST "https://example.com/wp-json/wc-appointments/v2/appointments" \
-u consumer_key:consumer_secret \
-H "Content-Type: application/json" \
-d '{
"product_id": 123,
"customer_id": 456,
"start_date": "2025-12-01 10:00:00",
"end_date": "2025-12-01 11:00:00",
"status": "confirmed"
}'
List Appointments
# List appointments using Application Password
curl -u username:app_password \
"https://example.com/wp-json/wc-appointments/v2/appointments?customer_id=456&date_from=2025-01-01&date_to=2025-01-31"
# Or using WooCommerce API keys
curl -u consumer_key:consumer_secret \
"https://example.com/wp-json/wc-appointments/v2/appointments?customer_id=456&date_from=2025-01-01&date_to=2025-01-31"
Update Appointment
# Update appointment status using Application Password
curl -X PATCH "https://example.com/wp-json/wc-appointments/v2/appointments/123" \
-u username:app_password \
-H "Content-Type: application/json" \
-d '{"status": "cancelled"}'
# Or using WooCommerce API keys
curl -X PATCH "https://example.com/wp-json/wc-appointments/v2/appointments/123" \
-u consumer_key:consumer_secret \
-H "Content-Type: application/json" \
-d '{"status": "cancelled"}'
Common Patterns
Pagination
// Fetch paginated results
async function fetchPaginated(endpoint, params = {}, page = 1) {
const url = new URL(endpoint, window.location.origin);
Object.entries(params).forEach(([key, value]) => {
url.searchParams.set(key, value);
});
url.searchParams.set('page', page);
url.searchParams.set('per_page', 10);
const response = await fetch(url);
const data = await response.json();
const totalPages = parseInt(response.headers.get('X-WP-TotalPages') || '1', 10);
return {
data,
page,
totalPages,
hasMore: page < totalPages
};
}
Error Handling
// Handle API errors
async function apiRequest(url, options = {}) {
try {
const response = await fetch(url, options);
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'API request failed');
}
return await response.json();
} catch (error) {
console.error('API Error:', error);
throw error;
}
}
Batch Operations
// Batch create/update/delete appointments
async function batchAppointments(operations) {
const response = await fetch('/wp-json/wc-appointments/v1/appointments/batch', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': wpApiSettings.nonce
},
body: JSON.stringify(operations)
});
return await response.json();
}
// Usage
const result = await batchAppointments({
create: [
{ product_id: 123, start: '2025-12-01 10:00', end: '2025-12-01 11:00' }
],
update: [
{ id: 456, status: 'confirmed' }
],
delete: [789]
});
Related Documentation
- Authentication - Setting up authentication
- Error Handling - Handling API errors
- Appointments Endpoints - Full appointment API reference
- Slots Endpoints - Getting available slots