Holds
The Holds API allows you to temporarily reserve appointment slots before confirming a booking. Holds prevent double-booking while patients complete their information.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST | /holds | Create a hold |
GET | /holds/{id} | Check hold status |
DELETE | /holds/{id} | Release a hold |
POST | /holds/{id}/confirm | Confirm booking |
Required scope: write_holds
The Hold Object
{
"id": "hold_123e4567-e89b-12d3-a456-426614174000",
"appointment_type_id": "type_456e7890-e89b-12d3-a456-426614174111",
"clinician_id": "cli_789a0123-e89b-12d3-a456-426614174222",
"location_id": "loc_012b3456-e89b-12d3-a456-426614174333",
"start_time": "2025-01-20T09:00:00Z",
"end_time": "2025-01-20T09:30:00Z",
"expires_at": "2025-01-15T10:15:00Z",
"status": "active",
"created_at": "2025-01-15T10:00:00Z"
}Attributes
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier (UUID) |
appointment_type_id | string | Appointment type being held |
clinician_id | string | Clinician for the slot |
location_id | string | Location (null for remote) |
start_time | string | Slot start time (ISO 8601) |
end_time | string | Slot end time (ISO 8601) |
expires_at | string | When hold expires (ISO 8601) |
status | string | active, confirmed, expired, released |
created_at | string | ISO 8601 creation timestamp |
⚠️
Holds expire after 15 minutes. Complete the booking before the hold expires, or the slot will become available again.
Create a Hold
POST /holdsTemporarily reserve an appointment slot.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
appointment_type_id | string | Yes | Appointment type ID |
clinician_id | string | Yes | Clinician ID |
date | string | Yes | Date (YYYY-MM-DD) |
start_time | string | Yes | Time (HH:MM) |
location_id | string | No | Location ID |
Request
curl -X POST "https://app.usejump.co.uk/functions/v1/api-v1/holds" \
-H "Authorization: Bearer pk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"appointment_type_id": "type_456e7890-e89b-12d3-a456-426614174111",
"clinician_id": "cli_789a0123-e89b-12d3-a456-426614174222",
"date": "2025-01-20",
"start_time": "09:00",
"location_id": "loc_012b3456-e89b-12d3-a456-426614174333"
}'Response
{
"data": {
"id": "hold_123e4567-e89b-12d3-a456-426614174000",
"appointment_type_id": "type_456e7890-e89b-12d3-a456-426614174111",
"clinician_id": "cli_789a0123-e89b-12d3-a456-426614174222",
"location_id": "loc_012b3456-e89b-12d3-a456-426614174333",
"start_time": "2025-01-20T09:00:00Z",
"end_time": "2025-01-20T09:30:00Z",
"expires_at": "2025-01-15T10:15:00Z",
"status": "active",
"created_at": "2025-01-15T10:00:00Z"
}
}Errors
| Status | Description |
|---|---|
409 | Slot already taken or held |
Check Hold Status
GET /holds/{id}Check if a hold is still active.
Request
curl -X GET "https://app.usejump.co.uk/functions/v1/api-v1/holds/hold_123e4567" \
-H "Authorization: Bearer pk_live_your_api_key"Response
{
"data": {
"id": "hold_123e4567-e89b-12d3-a456-426614174000",
"status": "active",
"expires_at": "2025-01-15T10:15:00Z"
}
}Release a Hold
DELETE /holds/{id}Release a hold before it expires, making the slot available again.
Request
curl -X DELETE "https://app.usejump.co.uk/functions/v1/api-v1/holds/hold_123e4567" \
-H "Authorization: Bearer pk_live_your_api_key"Response
{
"data": {
"message": "Hold released"
}
}Confirm a Hold
POST /holds/{id}/confirmConvert a hold into an actual appointment. The hold must still be active.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
patient_id | string | Yes | Patient ID |
attendee_name | string | No | Attendee's name |
attendee_email | string | No | Attendee's email |
attendee_phone | string | No | Attendee's phone |
notes | string | No | Appointment notes |
Request
curl -X POST "https://app.usejump.co.uk/functions/v1/api-v1/holds/hold_123e4567/confirm" \
-H "Authorization: Bearer pk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"patient_id": "pat_789a0123-e89b-12d3-a456-426614174444",
"attendee_name": "Sarah Johnson",
"attendee_email": "sarah@example.com",
"attendee_phone": "+44 7700 900123",
"notes": "First visit"
}'Response
Returns the created appointment:
{
"data": {
"id": "apt_555e6666-e89b-12d3-a456-426614174555",
"patient_id": "pat_789a0123-e89b-12d3-a456-426614174444",
"clinician_profile_id": "cli_789a0123-e89b-12d3-a456-426614174222",
"appointment_type_id": "type_456e7890-e89b-12d3-a456-426614174111",
"location_id": "loc_012b3456-e89b-12d3-a456-426614174333",
"start_time": "2025-01-20T09:00:00Z",
"end_time": "2025-01-20T09:30:00Z",
"status": "confirmed",
"attendee_name": "Sarah Johnson",
"attendee_email": "sarah@example.com",
"attendee_phone": "+44 7700 900123",
"notes": "First visit",
"created_at": "2025-01-15T10:05:00Z"
}
}Errors
| Status | Description |
|---|---|
404 | Hold not found or expired |
Complete Booking Flow
// Step 1: Query availability
const slots = await api.get('/availability', {
params: {
appointment_type_id: 'type_123',
start_date: '2025-01-20',
end_date: '2025-01-27'
}
});
// Step 2: User selects a slot
const selectedSlot = slots.data[0];
// Step 3: Create a hold
const hold = await api.post('/holds', {
appointment_type_id: 'type_123',
clinician_id: selectedSlot.clinician_id,
location_id: selectedSlot.location_id,
date: '2025-01-20',
start_time: '09:00'
});
// Step 4: Display countdown timer
const expiresAt = new Date(hold.data.expires_at);
// Show: "Complete booking within X minutes"
// Step 5: Collect patient information
// ... form submission ...
// Step 6: Confirm the hold
const appointment = await api.post(`/holds/${hold.data.id}/confirm`, {
patient_id: 'pat_789',
attendee_name: 'Sarah Johnson',
attendee_email: 'sarah@example.com'
});
// Success! Appointment is booked
console.log('Appointment confirmed:', appointment.data.id);Related Resources
- Availability - Query available slots
- Appointments - View/manage appointments
- Appointment Types - Service types
- Patients - Patient records