Kulcare Docs
DeveloperCare plansClinical

Public Appointments API

Overview

This API allows patients to book appointments without authentication. It supports both telemedicine and in-person appointments with OTP verification flow.

Related GitHub Issue: #1025


Endpoints Summary

#EndpointMethodAuthStatus
1/clinical/public_appointments/time_slotsGETNo✅ Done
2/clinical/public_appointments/send_codePOSTNo✅ Done
3/clinical/public_appointmentsPOSTNo✅ Done
4/clinical/public_appointments/:id/verifyPOSTNo✅ Done
5/clinical/public_appointments/:id/resend_codePOSTNo✅ Done
6/clinical/public_appointments/:idPUTNo✅ Done
7/clinical/public_appointments/availabilityGETNo✅ Done
8/clinical/facility_listings/:unique_idGETNo✅ Done
9/clinical/telemedicine_ordersPOSTJWT✅ Done
10/clinical/telemedicine_orders/:idGETJWT✅ Done
11/clinical/appointment_ordersPOSTJWT✅ Done
12/clinical/appointment_orders/:idGETJWT✅ Done
13/billing/webhooksPOSTNo✅ Done

Common Headers

Content-Type: application/json
Accept: application/json
X-Request-ID: <uuid> (optional)

1. Get Time Slots

Get available time slots for a practitioner on a specific date.

Endpoint

GET /clinical/public_appointments/time_slots

Request Headers

Content-Type: application/json

Query Parameters

ParameterTypeRequiredDescription
facility_idUUID✅ YesFacility UUID
practitioner_idUUID✅ YesPractitioner UUID
dateString✅ YesDate in YYYY-MM-DD format
appointment_typeStringNofixed (default), telemedicine, walk_in

Example Request

GET /clinical/public_appointments/time_slots?facility_id=550e8400-e29b-41d4-a716-446655440000&practitioner_id=660e8400-e29b-41d4-a716-446655440001&date=2026-03-10&appointment_type=fixed

Success Response

Status Code: 200 OK

{
  "data": {
    "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "date": "2026-03-10",
    "timezone": "Asia/Kolkata",
    "fees": 500,
    "telemedicine_fees": 300,
    "slots": [
      {
        "start_at": "2026-03-10T09:00:00Z",
        "end_at": "2026-03-10T09:15:00Z",
        "status": "available"
      },
      {
        "start_at": "2026-03-10T09:15:00Z",
        "end_at": "2026-03-10T09:30:00Z",
        "status": "available"
      },
      {
        "start_at": "2026-03-10T09:30:00Z",
        "end_at": "2026-03-10T09:45:00Z",
        "status": "booked"
      }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

Response Fields

FieldTypeDescription
practitioner_idUUIDPractitioner ID
facility_idUUIDFacility ID
dateStringDate requested
feesIntegerConsultation fee in paise (500 = ₹5)
telemedicine_feesIntegerTelemedicine fee in paise
slots[].start_atISO8601Slot start time (UTC)
slots[].end_atISO8601Slot end time (UTC)
slots[].statusString"available" or "booked"
timezoneStringIANA timezone for display (e.g., "Asia/Kolkata")

Error Responses

1. Validation Error - Missing Parameters

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Validation failed",
    "details": [
      { "field": "facility_id", "message": "Facility is required" },
      { "field": "practitioner_id", "message": "Practitioner is required" },
      { "field": "date", "message": "Date is required" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

2. Invalid Date Format

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Invalid date format",
    "details": [
      { "field": "date", "message": "Date must be in YYYY-MM-DD format" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

3. Facility Not Found

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Facility not found",
    "details": [
      { "field": "facility_id", "message": "Couldn't find Facility with id" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

4. Practitioner Not Found

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Practitioner not found",
    "details": [
      { "field": "practitioner_id", "message": "Couldn't find Practitioner with id" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

2. Send OTP Code

Send verification code to patient's phone number.

Endpoint

POST /clinical/public_appointments/send_code

Request Headers

Content-Type: application/json

Request Payload

{
  "facility_id": "UUID (required)",
  "practitioner_id": "UUID (required)",
  "phone_number": "string (required)",
  "country_code": "string (optional, default: 91)",
  "patient_name": "string (optional)",
  "appointment_type": "string (optional)",
  "payment_option": "string (optional)",
  "preferred_time": "ISO8601 (optional)"
}

Request Parameters

ParameterTypeRequiredDescription
facility_idUUID✅ YesFacility UUID
practitioner_idUUID✅ YesPractitioner UUID
phone_numberString✅ YesPhone number (e.g., "9876543210")
country_codeStringNoCountry code (e.g., "91" or "+91", defaults to "+91")
patient_nameStringNoPatient name
appointment_typeStringNotelemedicine, fixed, walk_in
payment_optionStringNoBEFORE, AFTER, NO
preferred_timeISO8601NoPreferred appointment time

Example Request

curl -X POST https://api.kulcare.com/clinical/public_appointments/send_code \
  -H "Content-Type: application/json" \
  -d '{
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
    "phone_number": "9876543210",
    "country_code": "91",
    "patient_name": "John Doe",
    "appointment_type": "TELEMEDICINE",
    "payment_option": "BEFORE",
    "preferred_time": "2026-03-10T10:00:00.000Z"
  }'

Success Response

Status Code: 201 Created

{
  "data": {
    "id": "770e8400-e29b-41d4-a716-446655440002",
    "patient_name": "John Doe",
    "phone_number": "9876543210",
    "country_code": "+91",
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
    "appointment_type": "telemedicine",
    "payment_option": "BEFORE",
    "preferred_time": "2026-03-10T10:00:00.000Z",
    "verified": false,
    "verification_attempts": 0,
    "created_at": "2026-03-06T10:00:00.000Z",
    "updated_at": "2026-03-06T10:00:00.000Z"
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

Error Responses

1. Validation Error - Missing Phone Number

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Phone number is required",
    "details": [
      { "field": "phone_number", "message": "Phone number is required" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

2. Invalid Phone Number

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Invalid phone number",
    "details": [
      { "field": "phone_number", "message": "Phone number must be at least 10 digits" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

3. Facility Not Found

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Facility not found",
    "details": [
      { "field": "facility_id", "message": "Couldn't find Facility with id" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

3. Create Appointment Verification

Create a new appointment verification and send SMS code.

Endpoint

POST /clinical/public_appointments

Request Headers

Content-Type: application/json

Request Payload

{
  "facility_id": "UUID (required)",
  "practitioner_id": "UUID (optional)",
  "patient_name": "string (optional)",
  "phone_number": "string (required)",
  "country_code": "string (optional)",
  "email": "string (optional)",
  "gender": "string (optional)",
  "address": "string (optional)",
  "date_of_birth": "string (optional)",
  "preferred_time": "ISO8601 (optional)",
  "appointment_type": "string (optional)",
  "payment_option": "string (optional)",
  "reason_for_visit": "string (optional)",
  "notes": "string (optional)",
  "utm_source": "string (optional)",
  "utm_medium": "string (optional)",
  "utm_campaign": "string (optional)",
  "utm_content": "string (optional)",
  "utm_term": "string (optional)"
}

Request Parameters

ParameterTypeRequiredDescription
facility_idUUID✅ YesFacility UUID
practitioner_idUUIDNoPractitioner UUID (or clinic_doctor_id legacy)
clinic_doctor_idUUIDNoLegacy - maps to practitioner_id
patient_nameStringNoPatient name (defaults to "Patient")
phone_numberString✅ YesPhone number
country_codeStringNoCountry code (91 → +91)
emailStringNoPatient email
genderStringNomale, female, other
addressStringNoPatient address
date_of_birthDateNoDOB in YYYY-MM-DD
preferred_timeISO8601NoPreferred time
appointment_typeStringNotelemedicine, fixed, walk_in
payment_optionStringNoBEFORE, AFTER, NO
reason_for_visitStringNoReason for visit
notesStringNoAdditional notes
utm_sourceStringNoUTM source
utm_mediumStringNoUTM medium
utm_campaignStringNoUTM campaign
utm_contentStringNoUTM content
utm_termStringNoUTM term

Example Request

{
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
  "patient_name": "John Doe",
  "phone_number": "9876543210",
  "country_code": "91",
  "email": "john@example.com",
  "gender": "male",
  "age": 30,
  "date_of_birth": "1996-03-03",
  "preferred_time": "2026-03-10T10:00:00.000Z",
  "appointment_type": "TELEMEDICINE",
  "payment_option": "BEFORE",
  "reason_for_visit": "General Consultation",
  "notes": "First visit"
}

Success Response

Status Code: 201 Created

{
  "data": {
    "id": "770e8400-e29b-41d4-a716-446655440002",
    "patient_name": "John Doe",
    "phone_number": "9876543210",
    "country_code": "+91",
    "email": "john@example.com",
    "gender": "male",
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
    "appointment_type": "telemedicine",
    "payment_option": "BEFORE",
    "preferred_time": "2026-03-10T10:00:00.000Z",
    "verified": false,
    "verification_attempts": 0,
    "created_at": "2026-03-06T10:00:00.000Z",
    "updated_at": "2026-03-06T10:00:00.000Z"
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

Error Responses

1. Validation Error - Missing Required Fields

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Validation failed",
    "details": [
      { "field": "facility_id", "message": "Facility is required" },
      { "field": "phone_number", "message": "Phone number is required" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

2. Invalid Appointment Type

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Invalid appointment type",
    "details": [
      { "field": "appointment_type", "message": "Invalid appointment type. Must be one of: telemedicine, fixed, walk_in" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

4. Verify OTP Code

Verify the appointment with SMS code.

Endpoint

POST /clinical/public_appointments/:id/verify

Path Parameters

ParameterTypeDescription
idUUIDAppointment verification ID (from send_code response)

Request Headers

Content-Type: application/json

Request Payload

{
  "verification_code": "string (required)"
}
ParameterTypeRequiredDescription
verification_codeString✅ Yes6-digit OTP code

Example Request

curl -X POST https://api.kulcare.com/clinical/public_appointments/770e8400-e29b-41d4-a716-446655440002/verify \
  -H "Content-Type: application/json" \
  -d '{
    "verification_code": "123456"
  }'

Success Response

Status Code: 200 OK

{
  "data": {
    "id": "770e8400-e29b-41d4-a716-446655440002",
    "patient_name": "John Doe",
    "phone_number": "9876543210",
    "country_code": "+91",
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
    "verified": true,
    "verified_at": "2026-03-06T10:05:00.000Z",
    "verification_attempts": 1,
    "created_at": "2026-03-06T10:00:00.000Z",
    "updated_at": "2026-03-06T10:05:00.000Z"
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

Error Responses

1. Invalid Verification Code

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Invalid verification code",
    "details": [
      { "field": "verification_code", "message": "Invalid verification code" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

2. Verification Expired

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Verification has expired",
    "details": [
      { "field": "verification_code", "message": "Verification code has expired. Please request a new code." }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

3. Maximum Attempts Exceeded

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Maximum verification attempts exceeded",
    "details": [
      { "field": "verification_code", "message": "Too many failed attempts. Please request a new code." }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

4. Verification Not Found

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Verification not found",
    "details": [
      { "field": "id", "message": "Couldn't find AppointmentVerification" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

5. Already Verified

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Already verified",
    "details": [
      { "field": "verification_code", "message": "This verification has already been completed" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

5. Resend OTP Code

Resend verification code for an existing verification.

Endpoint

POST /clinical/public_appointments/:id/resend_code

Path Parameters

ParameterTypeDescription
idUUIDAppointment verification ID

Example Request

curl -X POST https://api.kulcare.com/clinical/public_appointments/770e8400-e29b-41d4-a716-446655440002/resend_code \
  -H "Content-Type: application/json"

Success Response

Status Code: 200 OK

{
  "data": {
    "id": "770e8400-e29b-41d4-a716-446655440002",
    "patient_name": "John Doe",
    "phone_number": "9876543210",
    "country_code": "+91",
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
    "verified": false,
    "verification_attempts": 1,
    "created_at": "2026-03-06T10:00:00.000Z",
    "updated_at": "2026-03-06T10:10:00.000Z"
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

Error Responses

1. Verification Not Found

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Verification not found",
    "details": [
      { "field": "id", "message": "Couldn't find AppointmentVerification" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

6. Update Appointment

Update verification details and create appointment after verification.

Endpoint

PUT /clinical/public_appointments/:id

Path Parameters

ParameterTypeDescription
idUUIDAppointment verification ID

Request Payload

{
  "patient_name": "string (optional)",
  "email": "string (optional)",
  "gender": "string (optional)",
  "age": "integer (optional)",
  "date_of_birth": "string (optional)",
  "preferred_time": "ISO8601 (optional)",
  "preferred_start_time": "ISO8601 (optional)",
  "preferred_end_time": "ISO8601 (optional)",
  "reason_for_visit": "string (optional)",
  "notes": "string (optional)"
}
ParameterTypeRequiredDescription
patient_nameStringNoPatient name (or name legacy)
nameStringNoLegacy - maps to patient_name
emailStringNoPatient email
genderStringNomale, female, other
ageIntegerNoPatient age
date_of_birthDateNoDOB in YYYY-MM-DD
preferred_timeISO8601NoPreferred appointment time
preferred_start_timeISO8601NoPreferred slot start time
preferred_end_timeISO8601NoPreferred slot end time
reason_for_visitStringNoReason for visit
notesStringNoAdditional notes

Example Request

curl -X PUT https://api.kulcare.com/clinical/public_appointments/770e8400-e29b-41d4-a716-446655440002 \
  -H "Content-Type: application/json" \
  -d '{
    "patient_name": "John Doe",
    "email": "john@example.com",
    "gender": "male",
    "age": 30,
    "date_of_birth": "1996-03-03",
    "preferred_time": "2026-03-10T10:00:00.000Z",
    "reason_for_visit": "Consultation",
    "notes": "First visit"
  }'

Success Response

Status Code: 200 OK

{
  "data": {
    "verification": {
      "id": "770e8400-e29b-41d4-a716-446655440002",
      "patient_name": "John Doe",
      "phone_number": "9876543210",
      "country_code": "+91",
      "email": "john@example.com",
      "gender": "male",
      "facility_id": "550e8400-e29b-41d4-a716-446655440000",
      "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
      "appointment_id": "880e8400-e29b-41d4-a716-446655440003",
      "verified": true,
      "verified_at": "2026-03-06T10:05:00.000Z",
      "created_at": "2026-03-06T10:00:00.000Z",
      "updated_at": "2026-03-06T10:15:00.000Z"
    },
    "appointment": {
      "id": "880e8400-e29b-41d4-a716-446655440003",
      "patient_id": "990e8400-e29b-41d4-a716-446655440004",
      "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
      "facility_id": "550e8400-e29b-41d4-a716-446655440000",
      "status": "scheduled",
      "appointment_type": "telemedicine",
      "start_time": "2026-03-10T10:00:00.000Z",
      "end_time": "2026-03-10T10:30:00.000Z",
      "created_at": "2026-03-06T10:15:00.000Z",
      "updated_at": "2026-03-06T10:15:00.000Z"
    }
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

Error Responses

1. Verification Not Verified

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Verification required",
    "details": [
      { "field": "verification", "message": "Phone number must be verified before creating appointment" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

2. Slot Not Available

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Slot not available",
    "details": [
      { "field": "preferred_time", "message": "Selected time slot is not available" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

7. Get Facility Listing

Get facility details by unique_id. This is a public endpoint for displaying facility information.

Endpoint

GET /clinical/facility_listings/:unique_id

Path Parameters

ParameterTypeDescription
unique_idStringFacility unique identifier

Example Request

GET /clinical/facility_listings/ABC123XYZ

Success Response

Status Code: 200 OK

{
  "data": {
    "facility": {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "City Hospital",
      "address": "123 Main Street",
      "city": "Mumbai",
      "state": "Maharashtra",
      "pincode": "400001",
      "phone": "+91-9876543210",
      "logo_url": "https://cdn.kulcare.com/facilities/logo.png",
      "cover_image_url": "https://cdn.kulcare.com/facilities/cover.jpg"
    },
    "common_doctors": [
      {
        "id": "660e8400-e29b-41d4-a716-446655440001",
        "name": "Dr. John Smith",
        "speciality": "General Physician",
        "experience_years": 15,
        "qualification": "MBBS, MD",
        "photo_url": "https://cdn.kulcare.com/doctors/photo.jpg",
        "rating": 4.8,
        " consultation_fees": 500
      }
    ],
    "facility_group_locations": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440001",
        "name": "City Hospital - Branch 2",
        "address": "456 Secondary Street",
        "city": "Mumbai"
      }
    ],
    "facility_schedules": [
      {
        "day": "monday",
        "open_time": "09:00",
        "close_time": "18:00",
        "is_available": true
      }
    ],
    "reviews": [
      {
        "id": "review-001",
        "patient_name": "Anonymous",
        "rating": 5,
        "comment": "Excellent service!",
        "created_at": "2026-02-15T10:00:00.000Z"
      }
    ],
    "average_rating": 4.5,
    "total_reviews": 120,
    "facility_services_list": [
      {
        "id": "service-001",
        "name": "General Checkup",
        "description": " routine health checkup"
      }
    ],
    "facility_procedures": [
      {
        "id": "procedure-001",
        "name": "Blood Test",
        "description": "Complete blood count",
        "price": 500
      }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

Response Fields

FieldTypeDescription
facilityObjectBasic facility information
facility.idUUIDFacility ID
facility.nameStringFacility name
facility.addressStringFacility address
facility.cityStringCity
facility.stateStringState
facility.pincodeStringPincode
facility.phoneStringContact phone
facility.logo_urlStringLogo image URL
facility.cover_image_urlStringCover image URL
common_doctorsArrayList of doctors at this facility
facility_group_locationsArrayOther locations in the same group
facility_schedulesArrayWeekly schedule
reviewsArrayRecent reviews
average_ratingFloatAverage rating (0-5)
total_reviewsIntegerTotal number of reviews
facility_services_listArrayServices offered
facility_proceduresArrayProcedures available with prices

Error Responses

1. Facility Not Found

Status Code: 404 Not Found

{
  "data": null,
  "error": {
    "code": "not_found",
    "message": "Facility not found"
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

8. Check Practitioner Availability

Check if a practitioner is available for appointments.

Endpoint

GET /clinical/public_appointments/availability

Query Parameters

ParameterTypeRequiredDescription
facility_idUUID✅ YesFacility UUID
practitioner_idUUID✅ YesPractitioner UUID
dateDateNoDate in YYYY-MM-DD format
appointment_typeStringNoType: walk_in (default), fixed, telemedicine

Success Response

Status Code: 200 OK

{
  "data": {
    "available": true,
    "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "date": "2026-03-10"
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

9. Create Telemedicine Order

Create a Razorpay order for telemedicine consultation. Requires JWT authentication.

Endpoint

POST /clinical/telemedicine_orders

Request Headers

Content-Type: application/json
Authorization: Bearer <jwt_token>

Request Payload

{
  "practitioner_id": "UUID (required)",
  "patient_id": "UUID (required)",
  "facility_id": "UUID (required)",
  "appointment_verification_id": "UUID (optional)",
  "existing_appointment_id": "UUID (optional)",
  "appointment_id": "UUID (optional)",
  "slot_start_time": "ISO8601 (optional)",
  "slot_end_time": "ISO8601 (optional)",
  "appointment_type": "string (optional)",
  "payment_option": "string (optional)",
  "reason_for_visit": "string (optional)",
  "international_payment": "boolean (optional)",
  "amount": "integer (optional)"
}
ParameterTypeRequiredDescription
practitioner_idUUID✅ YesPractitioner UUID
patient_idUUID✅ YesPatient UUID
facility_idUUID✅ YesFacility UUID
appointment_verification_idUUIDNoFrom public appointment flow
existing_appointment_idUUIDNoExisting appointment ID
appointment_idUUIDNoAppointment ID
slot_start_timeISO8601NoSlot start time
slot_end_timeISO8601NoSlot end time
appointment_typeStringNotelemedicine (default)
payment_optionStringNoBEFORE (default), AFTER, NO
reason_for_visitStringNoReason for visit
international_paymentBooleanNoEnable international payments
amountIntegerNoAmount in paise (auto-calculated if not provided)

Example Request

curl -X POST https://api.kulcare.com/clinical/telemedicine_orders \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{
    "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
    "patient_id": "990e8400-e29b-41d4-a716-446655440004",
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "appointment_verification_id": "770e8400-e29b-41d4-a716-446655440002",
    "slot_start_time": "2026-03-10T10:00:00.000Z",
    "slot_end_time": "2026-03-10T10:30:00.000Z",
    "appointment_type": "telemedicine",
    "payment_option": "BEFORE",
    "reason_for_visit": "General Consultation"
  }'

Success Response

Status Code: 201 Created

{
  "data": {
    "id": "aa0e8400-e29b-41d4-a716-446655440005",
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "patient_id": "990e8400-e29b-41d4-a716-446655440004",
    "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
    "razorpay_order_id": "order_abc123",
    "amount": 30000,
    "currency": "INR",
    "status": "pending",
    "appointment_type": "telemedicine",
    "payment_option": "BEFORE",
    "slot_start_time": "2026-03-10T10:00:00.000Z",
    "slot_end_time": "2026-03-10T10:30:00.000Z",
    "reason_for_visit": "General Consultation",
    "international_payment": false,
    "created_at": "2026-03-06T10:00:00.000Z",
    "updated_at": "2026-03-06T10:00:00.000Z"
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "razorpay_order_id": "order_abc123"
  }
}

Error Responses

1. Authentication Required

Status Code: 401 Unauthorized

{
  "data": null,
  "error": {
    "code": "unauthorized",
    "message": "You need to sign in or sign up before continuing."
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

2. Validation Error - Missing Required Fields

Status Code: 422 Unprocessable Entity

{
  "data": null,
  "error": {
    "code": "validation_failed",
    "message": "Validation failed",
    "details": [
      { "field": "practitioner_id", "message": "Practitioner is required" },
      { "field": "patient_id", "message": "Patient is required" },
      { "field": "facility_id", "message": "Facility is required" }
    ]
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

10. Get Telemedicine Order

Get telemedicine order details. Requires JWT authentication.

Endpoint

GET /clinical/telemedicine_orders/:id

Request Headers

Authorization: Bearer <jwt_token>

Path Parameters

ParameterTypeDescription
idUUIDTelemedicine order ID

Success Response

Status Code: 200 OK

{
  "data": {
    "id": "aa0e8400-e29b-41d4-a716-446655440005",
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "patient_id": "990e8400-e29b-41d4-a716-446655440004",
    "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
    "razorpay_order_id": "order_abc123",
    "amount": 30000,
    "currency": "INR",
    "status": "paid",
    "appointment_type": "telemedicine",
    "payment_option": "BEFORE",
    "slot_start_time": "2026-03-10T10:00:00.000Z",
    "slot_end_time": "2026-03-10T10:30:00.000Z",
    "reason_for_visit": "General Consultation",
    "international_payment": false,
    "appointment_id": "880e8400-e29b-41d4-a716-446655440003",
    "appointment_verification_id": "770e8400-e29b-41d4-a716-446655440002",
    "created_at": "2026-03-06T10:00:00.000Z",
    "updated_at": "2026-03-06T10:30:00.000Z"
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

Error Responses

1. Order Not Found

Status Code: 404 Not Found

{
  "data": null,
  "error": {
    "code": "not_found",
    "message": "Order not found"
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

11. Create Appointment Order

Create a Razorpay order for in-person appointment. Requires JWT authentication.

Endpoint

POST /clinical/appointment_orders

Request Headers

Content-Type: application/json
Authorization: Bearer <jwt_token>

Request Payload

ParameterTypeRequiredDescription
practitioner_idUUID✅ YesPractitioner UUID
patient_idUUID✅ YesPatient UUID
facility_idUUID✅ YesFacility UUID
appointment_verification_idUUIDNoFrom public appointment flow
existing_appointment_idUUIDNoExisting appointment ID
appointment_idUUIDNoAppointment ID
slot_start_timeISO8601NoSlot start time
slot_end_timeISO8601NoSlot end time
appointment_typeStringNofixed (default), walk_in
payment_optionStringNoBEFORE (default), AFTER, NO
reason_for_visitStringNoReason for visit
international_paymentBooleanNoEnable international payments
amountIntegerNoAmount in paise (auto-calculated if not provided)

Example Request

curl -X POST https://api.kulcare.com/clinical/appointment_orders \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{
    "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
    "patient_id": "990e8400-e29b-41d4-a716-446655440004",
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "appointment_verification_id": "770e8400-e29b-41d4-a716-446655440002",
    "slot_start_time": "2026-03-10T10:00:00.000Z",
    "slot_end_time": "2026-03-10T10:30:00.000Z",
    "appointment_type": "fixed",
    "payment_option": "BEFORE",
    "reason_for_visit": "General Consultation"
  }'

Success Response

Status Code: 201 Created

{
  "data": {
    "id": "bb0e8400-e29b-41d4-a716-446655440006",
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "patient_id": "990e8400-e29b-41d4-a716-446655440004",
    "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
    "razorpay_order_id": "order_def456",
    "amount": 50000,
    "currency": "INR",
    "status": "pending",
    "appointment_type": "fixed",
    "payment_option": "BEFORE",
    "slot_start_time": "2026-03-10T10:00:00.000Z",
    "slot_end_time": "2026-03-10T10:30:00.000Z",
    "reason_for_visit": "General Consultation",
    "international_payment": false,
    "created_at": "2026-03-06T10:00:00.000Z",
    "updated_at": "2026-03-06T10:00:00.000Z"
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "razorpay_order_id": "order_def456"
  }
}

12. Get Appointment Order

Get appointment order details. Requires JWT authentication.

Endpoint

GET /clinical/appointment_orders/:id

Request Headers

Authorization: Bearer <jwt_token>

Path Parameters

ParameterTypeDescription
idUUIDAppointment order ID

Success Response

Status Code: 200 OK

{
  "data": {
    "id": "bb0e8400-e29b-41d4-a716-446655440006",
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "patient_id": "990e8400-e29b-41d4-a716-446655440004",
    "practitioner_id": "660e8400-e29b-41d4-a716-446655440001",
    "razorpay_order_id": "order_def456",
    "amount": 50000,
    "currency": "INR",
    "status": "paid",
    "appointment_type": "fixed",
    "payment_option": "BEFORE",
    "slot_start_time": "2026-03-10T10:00:00.000Z",
    "slot_end_time": "2026-03-10T10:30:00.000Z",
    "reason_for_visit": "General Consultation",
    "international_payment": false,
    "appointment_id": "880e8400-e29b-41d4-a716-446655440003",
    "appointment_verification_id": "770e8400-e29b-41d4-a716-446655440002",
    "created_at": "2026-03-06T10:00:00.000Z",
    "updated_at": "2026-03-06T10:30:00.000Z"
  },
  "meta": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

13. Billing Webhook

Receive Razorpay payment webhook events.

Endpoint

POST /billing/webhooks

Request Headers

Content-Type: application/json
X-Razorpay-Signature: <razorpay_signature>

Request Payload (Razorpay Format)

{
  "event": "payment.captured",
  "payload": {
    "payment": {
      "entity": {
        "id": "pay_abc123",
        "order_id": "order_abc123",
        "amount": 30000,
        "currency": "INR",
        "status": "captured"
      }
    }
  }
}

Supported Events

EventDescription
payment.capturedPayment successful
payment.failedPayment failed

Response

Status Code: 200 OK

{
  "received": true
}

Enums Reference

Appointment Type

ValueDescription
telemedicineVideo consultation
fixedScheduled in-person appointment
walk_inWalk-in appointment

Payment Option

ValueDescription
BEFOREPayment before appointment
AFTERPayment after appointment
NONo payment required

Order Status

ValueDescription
pendingAwaiting payment
paidPayment successful
failedPayment failed

Gender

ValueDescription
maleMale
femaleFemale
otherOther

Field Mappings (Legacy → New Schema)

Legacy FieldNew Schema Field
clinic_doctor_idpractitioner_id
namepatient_name
clinic_patient_idpatient_id
ONCALLtelemedicine
FIXEDfixed
WALK_IN / WALKINwalk_in
91 (country_code)+91

Complete Booking Flow

1. GET /clinical/public_appointments/time_slots
   ↓ (Get available slots with fees)
   Response: { slots: [...], fees: 500, telemedicine_fees: 300 }

2. POST /clinical/public_appointments/send_code
   ↓ (Create verification, send OTP)
   Request: { facility_id, practitioner_id, phone_number, ... }
   Response: { id: "verification_id", verified: false, ... }

3. POST /clinical/public_appointments/:id/verify
   ↓ (Verify OTP - marks as verified)
   Request: { verification_code: "123456" }
   Response: { id: "verification_id", verified: true, ... }

4. PUT /clinical/public_appointments/:id
   ↓ (Create actual appointment)
   Request: { patient_name, email, gender, ... }
   Response: { verification: {...}, appointment: {...} }

5. POST /clinical/telemedicine_orders (JWT required)
   ↓ (Create Razorpay order for payment)
   Request: { practitioner_id, patient_id, facility_id, ... }
   Response: { id: "order_id", razorpay_order_id: "order_xxx", amount: 30000, status: "pending" }

6. [Frontend handles Razorpay payment]
   - Use razorpay_order_id to collect payment
   - Redirect to Razorpay checkout

7. POST /billing/webhooks
   ↓ (Razorpay notifies payment status)
   Event: payment.captured or payment.failed

8. Appointment status updated to confirmed

Amount Values

All amounts are in paise (1 rupee = 100 paise).

Amount (Paise)Amount (Rupees)
30000₹300
50000₹500
100000₹1,000

Error Codes Summary

CodeDescriptionHTTP Status
validation_failedRequest validation failed422
not_foundResource not found404
unauthorizedAuthentication required401
internal_errorServer error500

Notes for Frontend Team

  1. Public Endpoints: Time slots, send_code, verify, update, availability are public (no auth required).

  2. JWT Required: Telemedicine orders and appointment orders require JWT authentication.

  3. OTP Flow: Always implement the OTP verification flow for public bookings.

  4. Verification Expiry: OTP codes expire after 30 minutes. Show appropriate error and allow resend.

  5. Max Attempts: Limit verification attempts to 3. Show error and allow resend after limit.

  6. Amount in Paise: All monetary values are in paise (multiply by 100 for rupees).

  7. Country Code: Input "91" becomes "+91" automatically.

  8. Appointment Types: Map frontend types to backend: ONCALL → telemedicine, FIXED → fixed.


Related Files

  • Controller: backend/domains/clinical/controllers/public_appointments_controller.rb
  • Controller: backend/domains/clinical/controllers/facility_listings_controller.rb
  • Controller: backend/domains/clinical/controllers/telemedicine_orders_controller.rb
  • Controller: backend/domains/clinical/controllers/appointment_orders_controller.rb
  • Controller: backend/domains/billing/controllers/webhooks_controller.rb
  • Model: backend/domains/clinical/models/appointment_verification.rb
  • Model: backend/domains/clinical/models/telemedicine_order.rb
  • Model: backend/domains/clinical/models/appointment_order.rb
  • Blueprint: backend/domains/clinical/blueprints/facility_listing_blueprint.rb

Support

For questions or issues, contact the Backend Team or refer to:

  • API Documentation: /api/docs
  • GitHub Issue: #1025

On this page

OverviewEndpoints SummaryCommon Headers1. Get Time SlotsEndpointRequest HeadersQuery ParametersExample RequestSuccess ResponseResponse FieldsError Responses1. Validation Error - Missing Parameters2. Invalid Date Format3. Facility Not Found4. Practitioner Not Found2. Send OTP CodeEndpointRequest HeadersRequest PayloadRequest ParametersExample RequestSuccess ResponseError Responses1. Validation Error - Missing Phone Number2. Invalid Phone Number3. Facility Not Found3. Create Appointment VerificationEndpointRequest HeadersRequest PayloadRequest ParametersExample RequestSuccess ResponseError Responses1. Validation Error - Missing Required Fields2. Invalid Appointment Type4. Verify OTP CodeEndpointPath ParametersRequest HeadersRequest PayloadExample RequestSuccess ResponseError Responses1. Invalid Verification Code2. Verification Expired3. Maximum Attempts Exceeded4. Verification Not Found5. Already Verified5. Resend OTP CodeEndpointPath ParametersExample RequestSuccess ResponseError Responses1. Verification Not Found6. Update AppointmentEndpointPath ParametersRequest PayloadExample RequestSuccess ResponseError Responses1. Verification Not Verified2. Slot Not Available7. Get Facility ListingEndpointPath ParametersExample RequestSuccess ResponseResponse FieldsError Responses1. Facility Not Found8. Check Practitioner AvailabilityEndpointQuery ParametersSuccess Response9. Create Telemedicine OrderEndpointRequest HeadersRequest PayloadExample RequestSuccess ResponseError Responses1. Authentication Required2. Validation Error - Missing Required Fields10. Get Telemedicine OrderEndpointRequest HeadersPath ParametersSuccess ResponseError Responses1. Order Not Found11. Create Appointment OrderEndpointRequest HeadersRequest PayloadExample RequestSuccess Response12. Get Appointment OrderEndpointRequest HeadersPath ParametersSuccess Response13. Billing WebhookEndpointRequest HeadersRequest Payload (Razorpay Format)Supported EventsResponseEnums ReferenceAppointment TypePayment OptionOrder StatusGenderField Mappings (Legacy → New Schema)Complete Booking FlowAmount ValuesError Codes SummaryNotes for Frontend TeamRelated FilesSupport