{
  "openapi": "3.1.0",
  "info": {
    "title": "Khmer Medical Interpreter AI Booking API",
    "version": "8.4.1",
    "description": "Live Khmer-English medical interpreter service discovery, availability, private-client appointment holds, Stripe payment handoff, and booking status. Never infer availability or price. Check live availability first, ask the user to explicitly confirm the exact time and price, then create a booking hold. Do not collect diagnosis, symptoms, medications, medical record numbers, or unnecessary protected health information.",
    "contact": {
      "email": "hello@khmermedicalinterpreter.com"
    }
  },
  "servers": [
    {
      "url": "https://khmermedicalinterpreter.com"
    }
  ],
  "paths": {
    "/api/ai/services": {
      "get": {
        "operationId": "getInterpreterServices",
        "summary": "Get services and current prices",
        "description": "Read the current Khmer-English interpreter services, rates, durations, service area, and booking rules. Use this or check availability before requesting personal information.",
        "x-openai-isConsequential": false,
        "responses": {
          "200": {
            "description": "Current service catalog",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/ai/availability": {
      "get": {
        "operationId": "checkInterpreterAvailability",
        "summary": "Check a specific live appointment slot",
        "description": "Check whether a requested time is currently available and return the exact server-calculated price plus nearby alternatives when unavailable. All times are America/Phoenix.",
        "x-openai-isConsequential": false,
        "parameters": [
          {
            "name": "service_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "in_person",
                "opi",
                "vri"
              ]
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": true,
            "description": "YYYY-MM-DD",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_time",
            "in": "query",
            "required": true,
            "description": "HH:MM in Arizona time, 24-hour format",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "duration_minutes",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 30,
              "maximum": 360
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Live availability, quote, and alternatives",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request"
          }
        }
      }
    },
    "/api/ai/bookings/hold": {
      "post": {
        "operationId": "createInterpreterBookingHold",
        "summary": "Reserve the user-confirmed private appointment",
        "description": "Creates a real private-client booking hold only after the user explicitly confirms the exact live time and price. Returns a Stripe checkout_url that must be shown to the user. Organization invoice-after-service is intentionally unavailable through the AI interface. The server recalculates price and rechecks availability. Do not send unnecessary medical information.",
        "x-openai-isConsequential": true,
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Unique stable key for this exact booking attempt; reuse only for an identical retry.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 120
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "service_id": {
                    "type": "string",
                    "enum": [
                      "in_person",
                      "opi",
                      "vri"
                    ]
                  },
                  "date": {
                    "type": "string",
                    "description": "YYYY-MM-DD"
                  },
                  "start_time": {
                    "type": "string",
                    "description": "HH:MM in America/Phoenix"
                  },
                  "duration_minutes": {
                    "type": "integer"
                  },
                  "contact_name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "organization_name": {
                    "type": "string",
                    "maxLength": 160,
                    "description": "Optional organization/facility name for scheduling context only; AI billing remains private prepaid."
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "phone": {
                    "type": "string",
                    "maxLength": 40
                  },
                  "location": {
                    "type": "string",
                    "maxLength": 240,
                    "description": "In-person facility/address or remote platform/call details."
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 240,
                    "description": "Operational scheduling notes only. Do not include diagnosis, symptoms, medications, record numbers, or unnecessary PHI."
                  }
                },
                "required": [
                  "service_id",
                  "date",
                  "start_time",
                  "duration_minutes",
                  "contact_name",
                  "email",
                  "phone",
                  "location"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent replay of an existing hold"
          },
          "201": {
            "description": "Private booking hold created; checkout_url is the Stripe payment link."
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "409": {
            "description": "Slot was just taken or idempotency conflict"
          }
        }
      }
    },
    "/api/ai/bookings/status": {
      "get": {
        "operationId": "getInterpreterBookingStatus",
        "summary": "Check payment and confirmation status",
        "description": "Returns non-sensitive operational status for a booking. Use after the user completes Stripe payment to confirm the appointment status. The Stripe checkout URL is intentionally not returned by this status lookup.",
        "x-openai-isConsequential": false,
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "booking_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Booking status"
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "404": {
            "description": "Booking not found"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Server-to-server AI booking API key configured by the service owner."
      }
    }
  }
}
