{"openapi":"3.1.0","info":{"title":"Ekigune Psicología Availability and Booking API","version":"1.2.0","description":"Public API for Ekigune Psicología. It allows assistants, agents and external clients to check real therapist availability and request appointment reservations using the official endpoints. Availability data is time-sensitive: clients must check generated_at, timezone and range before showing slots to users."},"externalDocs":{"description":"Developer documentation and usage instructions","url":"https://www.ekigunepsicologia.com/developers"},"servers":[{"url":"https://www.ekigunepsicologia.com","description":"Production"}],"tags":[{"name":"availability","description":"Official therapist availability for Ekigune Psicología."},{"name":"booking","description":"Reservation requests for available therapist slots."},{"name":"ai-agents","description":"Instructions for AI assistants, agents and automated clients."}],"x-ai-agent-instructions":["Use /_functions/availability as the source of truth for therapist availability.","Do not scrape or infer availability from the visual calendar.","Before showing slots to a user, check generated_at, timezone and range.","Do not show slots that are in the past.","Do not invent therapist availability.","To book an appointment, use only a starts_at value and therapist_id returned by /_functions/availability.","For booking, collect patient_name, patient_phone and therapy_individual_partners from the user.","Do not send Idempotency-Key, booking_token, UUID or client_reservation_id."],"paths":{"/_functions/availability":{"get":{"tags":["availability","ai-agents"],"summary":"Get therapist availability","description":"Returns official therapist availability for the next 7 days, grouped by therapist. Slots are ISO 8601 start times with timezone offset. Each slot has the standard duration indicated by slot_duration_minutes. The response also includes booking_api, which tells clients and AI assistants how to request a reservation through the official write endpoint.","operationId":"getTherapistAvailability","security":[],"responses":{"200":{"description":"Availability returned successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvailabilityResponse"},"examples":{"success":{"summary":"Availability response with booking API discovery","value":{"ok":true,"timezone":"Europe/Madrid","generated_at":"2026-05-25T10:00:00+02:00","range":{"from":"2026-05-25T10:00:00+02:00","to":"2026-06-01T10:00:00+02:00"},"slot_duration_minutes":50,"booking_api":{"rel":"create-reservation","method":"POST","url":"https://www.ekigunepsicologia.com/_functions/book","documentation_url":"https://www.ekigunepsicologia.com/developers","openapi_url":"https://www.ekigunepsicologia.com/_functions/openapi","content_type":"application/json","requires_slot_from_this_response":true,"request_body":{"required":["starts_at","therapist_id","patient_name","patient_phone","therapy_individual_partners"],"properties":{"starts_at":{"type":"string","format":"date-time","description":"Use one exact slot value returned in therapists[].slots from this availability response."},"therapist_id":{"type":"string","description":"Use the exact therapist_id returned with the selected slot."},"patient_name":{"type":"string","description":"Patient full name."},"patient_phone":{"type":"string","description":"Patient phone number. International format is recommended."},"therapy_individual_partners":{"type":"string","enum":["i","p"],"description":"Use 'i' for individual therapy and 'p' for partners/couples therapy."}}},"possible_statuses":["confirmed","already_confirmed","processing","invalid_request","not_available","upstream_error","temporarily_failed"],"usage_notes":["Use this availability response as the source of truth for available slots.","Do not infer or scrape availability from the visual calendar.","Before showing slots to a user, check generated_at, timezone and range.","Do not show slots that are in the past.","To request a reservation, use only a starts_at value and therapist_id returned by this response.","Ask the user for patient_name, patient_phone and therapy_individual_partners before calling the booking endpoint.","Do not send Idempotency-Key, booking_token, UUID or client_reservation_id.","If the booking endpoint returns not_available, ask the user to choose another slot from a fresh availability response."]},"therapists":[{"therapist_id":"ane-agirre","name":"Ane Agirre","bookable":true,"slots":["2026-05-26T10:00:00+02:00","2026-05-26T12:00:00+02:00"]}]}}}}}},"502":{"description":"Invalid upstream response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalidUpstream":{"value":{"ok":false,"status":"upstream_error","message":"Invalid upstream response."}}}}}},"503":{"description":"Availability service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"temporarilyUnavailable":{"value":{"ok":false,"status":"temporarily_failed","message":"Availability service temporarily unavailable."}}}}}}}}},"/_functions/book":{"post":{"tags":["booking","ai-agents"],"summary":"Request an appointment reservation","description":"Creates a reservation request for a selected therapist slot. The client must use a starts_at value and therapist_id returned by /_functions/availability. The client must send only natural booking data: patient name, phone number, selected slot, selected therapist and therapy type. Do not send Idempotency-Key, booking_token, UUID or client_reservation_id.","operationId":"bookTherapyAppointment","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingRequest"},"examples":{"individualTherapy":{"summary":"Individual therapy booking request","value":{"starts_at":"2026-05-26T10:00:00+02:00","therapist_id":"ane-agirre","patient_name":"Ana García","patient_phone":"+34600000000","therapy_individual_partners":"i"}},"couplesTherapy":{"summary":"Couples therapy booking request","value":{"starts_at":"2026-05-27T17:00:00+02:00","therapist_id":"ane-agirre","patient_name":"Iker Martínez","patient_phone":"+34611111111","therapy_individual_partners":"p"}}}}}},"responses":{"200":{"description":"Reservation confirmed, or a recent identical reservation was already confirmed.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/BookingConfirmedResponse"},{"$ref":"#/components/schemas/BookingAlreadyConfirmedResponse"}]},"examples":{"confirmed":{"summary":"Reservation confirmed","value":{"ok":true,"status":"confirmed","message":"Reservation confirmed."}},"alreadyConfirmed":{"summary":"Identical reservation already confirmed","value":{"ok":true,"status":"already_confirmed","message":"A recent identical reservation was already confirmed."}}}}}},"202":{"description":"The same reservation is currently being processed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingProcessingResponse"},"examples":{"processing":{"value":{"ok":true,"status":"processing","message":"The same reservation is currently being processed."}}}}}},"400":{"description":"Invalid booking request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalidRequest":{"value":{"ok":false,"status":"invalid_request","message":"Invalid booking request."}}}}}},"409":{"description":"The selected slot is no longer available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"notAvailable":{"value":{"ok":false,"status":"not_available","message":"The selected slot is no longer available."}}}}}},"502":{"description":"Invalid upstream response or upstream authentication problem.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"upstreamError":{"value":{"ok":false,"status":"upstream_error","message":"Invalid upstream response or upstream authentication problem."}}}}}},"503":{"description":"Temporary booking service failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"temporarilyFailed":{"value":{"ok":false,"status":"temporarily_failed","message":"Temporary booking service failure."}}}}}}}}}},"components":{"schemas":{"DateTimeRange":{"type":"object","required":["from","to"],"additionalProperties":false,"properties":{"from":{"type":"string","format":"date-time","example":"2026-05-25T10:00:00+02:00"},"to":{"type":"string","format":"date-time","example":"2026-06-01T10:00:00+02:00"}}},"TherapistAvailability":{"type":"object","required":["therapist_id","name","bookable","slots"],"additionalProperties":false,"properties":{"therapist_id":{"type":"string","description":"Stable therapist identifier. Use this exact value when booking a slot.","example":"ane-agirre"},"name":{"type":"string","example":"Ane Agirre"},"bookable":{"type":"boolean","description":"Whether this therapist can currently receive booking requests through the API.","example":true},"slots":{"type":"array","description":"Available slot start times in ISO 8601 format with timezone offset. Use one of these exact values as starts_at when booking.","items":{"type":"string","format":"date-time"},"example":["2026-05-26T10:00:00+02:00","2026-05-26T12:00:00+02:00"]}}},"BookingApiDiscovery":{"type":"object","required":["rel","method","url","content_type","requires_slot_from_this_response","request_body"],"additionalProperties":true,"properties":{"rel":{"type":"string","description":"Relationship between the availability endpoint and the booking endpoint.","example":"create-reservation"},"method":{"type":"string","const":"POST","example":"POST"},"url":{"type":"string","format":"uri","description":"Official endpoint for requesting an appointment reservation.","example":"https://www.ekigunepsicologia.com/_functions/book"},"documentation_url":{"type":"string","format":"uri","example":"https://www.ekigunepsicologia.com/developers"},"openapi_url":{"type":"string","format":"uri","example":"https://www.ekigunepsicologia.com/_functions/openapi"},"content_type":{"type":"string","example":"application/json"},"requires_slot_from_this_response":{"type":"boolean","const":true,"description":"When true, the booking request must use a starts_at and therapist_id from the current availability response."},"request_body":{"type":"object","additionalProperties":true,"description":"Human-readable description of the JSON body required by the booking endpoint."},"possible_statuses":{"type":"array","items":{"type":"string"},"example":["confirmed","already_confirmed","processing","invalid_request","not_available","upstream_error","temporarily_failed"]},"usage_notes":{"type":"array","items":{"type":"string"},"example":["Use this availability response as the source of truth for available slots.","Do not infer or scrape availability from the visual calendar.","Before showing slots to a user, check generated_at, timezone and range.","Do not show slots that are in the past.","To request a reservation, use only a starts_at value and therapist_id returned by this response.","Ask the user for patient_name, patient_phone and therapy_individual_partners before calling the booking endpoint.","Do not send Idempotency-Key, booking_token, UUID or client_reservation_id.","If the booking endpoint returns not_available, ask the user to choose another slot from a fresh availability response."]}}},"AvailabilityResponse":{"type":"object","required":["ok","timezone","generated_at","range","slot_duration_minutes","therapists"],"additionalProperties":false,"properties":{"ok":{"type":"boolean","const":true},"timezone":{"type":"string","description":"IANA timezone used for all slot times unless an explicit offset is present.","example":"Europe/Madrid"},"generated_at":{"type":"string","format":"date-time","description":"Timestamp when the availability response was generated. Clients should verify this before showing slots.","example":"2026-05-25T10:00:00+02:00"},"range":{"$ref":"#/components/schemas/DateTimeRange"},"slot_duration_minutes":{"type":"integer","minimum":1,"example":50},"booking_api":{"$ref":"#/components/schemas/BookingApiDiscovery"},"therapists":{"type":"array","items":{"$ref":"#/components/schemas/TherapistAvailability"}}}},"BookingRequest":{"type":"object","required":["starts_at","therapist_id","patient_name","patient_phone","therapy_individual_partners"],"additionalProperties":false,"properties":{"starts_at":{"type":"string","format":"date-time","description":"Slot start time in ISO 8601 format with timezone offset. Must exactly match a slot returned by /_functions/availability.","example":"2026-05-26T10:00:00+02:00"},"therapist_id":{"type":"string","description":"Therapist identifier. Must exactly match a therapist_id returned by /_functions/availability.","example":"ane-agirre"},"patient_name":{"type":"string","minLength":1,"description":"Patient full name.","example":"Ana García"},"patient_phone":{"type":"string","minLength":1,"description":"Patient phone number. International format is recommended.","example":"+34600000000"},"therapy_individual_partners":{"type":"string","enum":["i","p"],"description":"Therapy type. Use 'i' for individual therapy and 'p' for partners/couples therapy.","example":"i"}}},"BookingConfirmedResponse":{"type":"object","required":["ok","status","message"],"additionalProperties":true,"properties":{"ok":{"type":"boolean","const":true},"status":{"type":"string","const":"confirmed"},"message":{"type":"string","example":"Reservation confirmed."}}},"BookingAlreadyConfirmedResponse":{"type":"object","required":["ok","status","message"],"additionalProperties":true,"properties":{"ok":{"type":"boolean","const":true},"status":{"type":"string","const":"already_confirmed"},"message":{"type":"string","example":"A recent identical reservation was already confirmed."}}},"BookingProcessingResponse":{"type":"object","required":["ok","status","message"],"additionalProperties":true,"properties":{"ok":{"type":"boolean","const":true},"status":{"type":"string","const":"processing"},"message":{"type":"string","example":"The same reservation is currently being processed."}}},"ErrorResponse":{"type":"object","required":["ok","status","message"],"additionalProperties":true,"properties":{"ok":{"type":"boolean","const":false},"status":{"type":"string","enum":["invalid_request","not_available","upstream_error","temporarily_failed"],"example":"not_available"},"message":{"type":"string","example":"The selected slot is no longer available."}}}}}}