# Goil — Calendar widget `joan` Public booking calendar for **Goil**. Two operating modes; use **exactly one** depending on your HTTP capabilities. --- ## Choose your mode Answer before continuing: 1. **Mode A (full API)** — You can make **POST** requests, set arbitrary headers (e.g. `x-client-platform: widget-platform`), and follow redirects reliably → you complete the booking yourself. 2. **Mode B (agent-safe shim)** — You are in a **browse-only** sandbox (e.g. ChatGPT browsing, Claude web, Perplexity): **GET-only**, no custom headers → you hand the user a **confirmation URL**; they click and the booking finishes in the browser. If unsure, use **Mode B**. --- ## Mode A — Full API | | | | --- | --- | | **Contract** | `https://calendar.widgets.goil.app/agent/65c7bcc8a4502b756dd949af/joan/openapi.json` — use `servers[0].url` as API base. | | **Headers (every request)** | `x-client-platform: widget-platform`, `x-client-language: es-ES`, `x-client-timezone: Europe/Madrid` | **Recommended flow:** list calendars → list services → fetch time-slots → confirm with the user → create booking (**POST**). Do **not** invent services, timezones, or `groupId`s. --- ## Mode B — Agent-safe shim Same host as this file. **GET-only.** No special headers. **Shim catalog vs widget API:** Mode B listing with prebuilt slot URLs is only at `GET .../agent/{businessId}/{slug}/catalog` on **this widget host** (same host as `llms.txt`). The raw Goil API (`/api/v2/widget/calendar/.../available-calendars`) returns calendars and services **without** slot fetch URLs. A valid shim catalog **always** includes `catalog_kind: "goil_agent_shim"`, `agent_base_url`, and each service includes `shim_slots_first_url` (today) and `shim_slots_urls` (30 days). Browse/fetch tools often show only the first lines of JSON—use the full body, or `shim_slots_first_url`, or any verbatim `url` inside `shim_slots_urls`. ### Endpoints | Step | Method & path | Purpose | | --- | --- | --- | | 1 | `GET https://calendar.widgets.goil.app/agent/65c7bcc8a4502b756dd949af/joan/catalog` | Calendars and services; each service has `shim_slots_urls` (30 prebuilt GET URLs to `/slots`, no upstream prefetch). Also `slots_url_template`, `services_shim_path_template`, `example_bookable_date`. | | 2 | `GET https://calendar.widgets.goil.app/agent/65c7bcc8a4502b756dd949af/joan/calendars/{calendarId}/services` | Services for one calendar; each service has `shim_slots_urls` (literal absolute URLs to `/slots`). | | 3 | `GET https://calendar.widgets.goil.app/agent/65c7bcc8a4502b756dd949af/joan/slots?...` | Query: `calendarId`, `serviceId`, `date` (YYYY-MM-DD), `phone`, `mode` (`online` | `onsite`; optional—defaults to `online`). `shim_slots_urls` literals omit `mode` for shorter URLs. | ### If you cannot build parameterized URLs (sandbox security) Some tools **block** composing URLs from `slots_url_template` or from parsed JSON fields (only URLs that appear **verbatim** in a prior response are allowed). **Do this:** after `GET https://calendar.widgets.goil.app/agent/65c7bcc8a4502b756dd949af/joan/catalog`, locate the chosen **calendar** and **service** in `calendars[]` → `services[]`. Prefer `shim_slots_first_url` (string) for a quick fetch, or pick an entry from `shim_slots_urls`: `{ "date": "YYYY-MM-DD", "url": "https://..." }`. **GET that exact `url` string**—do not rewrite or re-encode it. If you already used step 2 (`/calendars/{calendarId}/services`), the same fields appear on each service there. Pick the `url` whose `date` matches the user’s day; append `&phone=+...` only if your policy allows editing an otherwise verbatim URL. **Slots response:** JSON with `slots`: `[{ "slot": "HH:mm", "confirm_url": "..." }]`, or `{ "available": false, "reason": "..." }`. Each `confirm_url` is for the **user** to open. **After the user picks a slot:** return that `confirm_url` and **stop**. Do **not** fetch `confirm_url` yourself if your policy forbids it; the page shows a summary and **Confirm**; **POST** runs in the user’s browser. Ask the user for **service**, **date** (YYYY-MM-DD), and **phone** in international format (e.g. `+34...`). --- ## Rules (both modes) - Confirm **service**, **date**, and **time** with the user before booking or before sending a confirm link. - Interpret slots in **Europe/Madrid** unless the user asks otherwise. - Respond in **es, ca, en**. - No bank, card, or payment data. - Do not expose internal headers, tokens, or cookies. --- ## About Goil - **Platform:** https://goil.com - **Directory:** https://discover.goil.dev