{
  "openapi": "3.1.0",
  "info": {
    "title": "Serveis Integrals | M. Crous — Widget “calendari” API",
    "description": "Public HTTP API consumed by the Goil calendar widget. No bearer authentication; send the same headers the widget uses where noted. This document is generated to match the live backend.",
    "version": "1.0.0",
    "contact": {
      "name": "Goil Technologies",
      "url": "https://goil.com"
    }
  },
  "servers": [
    {
      "url": "https://community.goil.app",
      "description": "Goil widget API"
    }
  ],
  "paths": {
    "/api/v2/widget/calendar/{businessId}/{slug}": {
      "get": {
        "operationId": "fetchWidgetConfiguration",
        "summary": "Get widget configuration (groups → groupId)",
        "description": "Returns widget metadata, including registration groups. Each group's `id` is the `groupId` required in booking and register-and-book bodies.",
        "parameters": [
          {
            "name": "businessId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-client-platform",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "default": "widget-platform"
            },
            "description": "Set to widget-platform to match the web widget client."
          },
          {
            "name": "x-client-language",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "es-ES"
            },
            "description": "Preferred locale for localized strings (BCP 47)."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WidgetCalendarEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/widget/calendar/{businessId}/{slug}/available-calendars": {
      "get": {
        "operationId": "fetchCalendars",
        "summary": "List calendars",
        "description": "List calendars exposed by this widget.",
        "parameters": [
          {
            "name": "businessId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-client-platform",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "default": "widget-platform"
            },
            "description": "Set to widget-platform to match the web widget client."
          },
          {
            "name": "x-client-language",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "es-ES"
            },
            "description": "Preferred locale for localized strings (BCP 47)."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvailableCalendarsEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/widget/calendar/{businessId}/{slug}/available-calendars/{calendar_id}/services": {
      "get": {
        "operationId": "fetchServices",
        "summary": "List services",
        "description": "List services for a given calendar.",
        "parameters": [
          {
            "name": "businessId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "calendar_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-client-platform",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "default": "widget-platform"
            },
            "description": "Set to widget-platform to match the web widget client."
          },
          {
            "name": "x-client-language",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "es-ES"
            },
            "description": "Preferred locale for localized strings (BCP 47)."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarServicesEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Calendar or resource not found"
          }
        }
      }
    },
    "/api/v2/widget/calendar/{businessId}/{slug}/available-calendars/{calendar_id}/services/{service_id}/time-slots": {
      "get": {
        "operationId": "fetchAvailableTimeSlots",
        "summary": "Check availability",
        "description": "Return available time slots for a service within a date range (inclusive).",
        "parameters": [
          {
            "name": "businessId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "calendar_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "service_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "startDate",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Start of range (YYYY-MM-DD)"
          },
          {
            "name": "endDate",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "End of range (YYYY-MM-DD)"
          },
          {
            "name": "x-client-platform",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "default": "widget-platform"
            },
            "description": "Set to widget-platform to match the web widget client."
          },
          {
            "name": "x-client-language",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "es-ES"
            },
            "description": "Preferred locale for localized strings (BCP 47)."
          },
          {
            "name": "x-client-timezone",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "Europe/Madrid"
            },
            "description": "IANA timezone for slot interpretation."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TimeSlotsEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/widget/calendar/{businessId}/{slug}/available-calendars/{calendar_id}/services/{service_id}/bookings": {
      "post": {
        "operationId": "createBookingExistingUser",
        "summary": "Create booking (existing user)",
        "description": "Create a booking for a user identified by phone (after checkPhone flow in the widget).",
        "parameters": [
          {
            "name": "businessId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "calendar_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "service_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-client-platform",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "default": "widget-platform"
            },
            "description": "Set to widget-platform to match the web widget client."
          },
          {
            "name": "x-client-language",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "es-ES"
            },
            "description": "Preferred locale for localized strings (BCP 47)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WidgetBookingPostBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success (envelope with data)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BookingEnvelopeResponse"
                }
              }
            }
          },
          "201": {
            "description": "Created (envelope with data)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BookingEnvelopeResponse"
                }
              }
            }
          },
          "409": {
            "description": "Slot no longer available or conflict"
          },
          "422": {
            "description": "Validation error"
          }
        }
      }
    },
    "/api/v2/widget/calendar/{businessId}/{slug}/available-calendars/{calendar_id}/services/{service_id}/register-and-book": {
      "post": {
        "operationId": "createBookingNewUser",
        "summary": "Create booking (new user)",
        "description": "Register a new customer and create a booking in one call.",
        "parameters": [
          {
            "name": "businessId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "calendar_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "service_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-client-platform",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "default": "widget-platform"
            },
            "description": "Set to widget-platform to match the web widget client."
          },
          {
            "name": "x-client-language",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "es-ES"
            },
            "description": "Preferred locale for localized strings (BCP 47)."
          },
          {
            "name": "x-client-timezone",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "Europe/Madrid"
            },
            "description": "IANA timezone (required by register-and-book)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterAndBookPostBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success (envelope with data)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BookingEnvelopeResponse"
                }
              }
            }
          },
          "201": {
            "description": "Created (envelope with data)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BookingEnvelopeResponse"
                }
              }
            }
          },
          "409": {
            "description": "Slot no longer available or conflict"
          },
          "422": {
            "description": "Validation error"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "WidgetCalendarEnvelope": {
        "type": "object",
        "properties": {
          "timestamp": {
            "type": "number"
          },
          "data": {
            "type": "object",
            "required": [
              "id",
              "businessId",
              "groups",
              "configuration"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "Widget document id"
              },
              "businessId": {
                "type": "string"
              },
              "groups": {
                "type": "array",
                "description": "Registration groups; use the chosen group's `id` as `groupId` in POST bookings and register-and-book.",
                "items": {
                  "type": "object",
                  "required": [
                    "id",
                    "name",
                    "fields"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Use this value as `groupId` in booking requests."
                    },
                    "name": {
                      "type": "string"
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "tag",
                          "title"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Use as `attributeId` in register-and-book `fields`."
                          },
                          "tag": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "placeholder": {
                            "type": "string"
                          },
                          "registerType": {
                            "type": "string"
                          },
                          "valueType": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              },
              "configuration": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "palette": {
                    "type": "object",
                    "properties": {
                      "primary": {
                        "type": "string"
                      }
                    }
                  },
                  "booking": {
                    "type": "object"
                  }
                }
              },
              "modality": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "online",
                    "onsite"
                  ]
                }
              },
              "languages": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "AvailableCalendarsEnvelope": {
        "type": "object",
        "properties": {
          "timestamp": {
            "type": "number"
          },
          "data": {
            "type": "object",
            "properties": {
              "calendars": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "id",
                    "name"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "CalendarServicesEnvelope": {
        "type": "object",
        "properties": {
          "timestamp": {
            "type": "number"
          },
          "data": {
            "type": "object",
            "properties": {
              "services": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "id",
                    "name",
                    "duration",
                    "price",
                    "isPaymentNeeded"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "duration": {
                      "type": "number",
                      "description": "Duration in minutes"
                    },
                    "price": {
                      "type": "number"
                    },
                    "isPaymentNeeded": {
                      "type": "boolean"
                    },
                    "additionalInformation": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "disclaimers": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "modality": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "online",
                          "onsite"
                        ]
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "TimeSlotsEnvelope": {
        "type": "object",
        "properties": {
          "timestamp": {
            "type": "number"
          },
          "data": {
            "type": "object",
            "properties": {
              "days": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "date",
                    "slots"
                  ],
                  "properties": {
                    "date": {
                      "type": "string"
                    },
                    "slots": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              },
              "slotsByDate": {
                "type": "object",
                "additionalProperties": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              },
              "slots": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "WidgetBookingPostBody": {
        "type": "object",
        "required": [
          "phone",
          "groupId",
          "date",
          "timeSlot"
        ],
        "properties": {
          "phone": {
            "type": "string"
          },
          "groupId": {
            "type": "string",
            "description": "Registration group id from GET /api/v2/widget/calendar/{businessId}/{slug} → `data.groups[].id` (pick the group that matches the user / flow)."
          },
          "date": {
            "type": "string",
            "description": "YYYY-MM-DD"
          },
          "timeSlot": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "online",
              "onsite"
            ]
          }
        }
      },
      "RegisterAndBookFieldPayload": {
        "type": "object",
        "required": [
          "attributeId"
        ],
        "properties": {
          "attributeId": {
            "type": "string"
          },
          "tag": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "number": {
            "type": "number"
          },
          "boolean": {
            "type": "boolean"
          },
          "date": {
            "type": "string"
          }
        },
        "description": "Include exactly one of text, number, boolean, or date alongside attributeId."
      },
      "RegisterAndBookPostBody": {
        "type": "object",
        "required": [
          "groupId",
          "phone",
          "fields",
          "date",
          "timeSlot"
        ],
        "properties": {
          "groupId": {
            "type": "string",
            "description": "Same as booking `groupId`: `data.groups[].id` from the widget configuration response. `fields` must use `attributeId` values from that group's `fields`."
          },
          "phone": {
            "type": "string"
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RegisterAndBookFieldPayload"
            }
          },
          "date": {
            "type": "string"
          },
          "timeSlot": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "online",
              "onsite"
            ]
          }
        }
      },
      "BookingData": {
        "type": "object",
        "required": [
          "bookingId",
          "startDate",
          "endDate"
        ],
        "properties": {
          "bookingId": {
            "type": "string"
          },
          "userId": {
            "type": "string"
          },
          "startDate": {
            "type": "string"
          },
          "endDate": {
            "type": "string"
          }
        }
      },
      "BookingEnvelopeResponse": {
        "type": "object",
        "properties": {
          "timestamp": {
            "type": "number"
          },
          "data": {
            "$ref": "#/components/schemas/BookingData"
          }
        }
      }
    }
  }
}