# Integrazione dei calendari con un servizio di terze parti

Le API – in formato ReST – messe a disposizione dalla piattaforma consentono le integrazioni necessarie con i sistemi esterni.\
Sono previste chiamate senza autenticazione per l’accesso a informazioni pubbliche e un meccanismo di autenticazione per la consultazione di dati non pubblici e per le operazioni di scrittura dove previste.

**Verranno presi in esame 2 use-case specifici:**

* L'integrazione con un sistema Taglia code
* L'integrazione di un IVR (Interactive Voice Response)

Le API dei calendari di **Opencity Italia** verranno interrogate al fine di:

* Recuperare configurazioni dei servizi e delle agende
* Ottenere disponibilità e slot prenotabili
* Effettuare prenotazioni (opzionale)
* Recuperare appuntamenti per una sede

La documentazione e i test delle API sono disponibili tramite interfaccia di tipo swagger.

* **Catalogo servizi e configurazione agende**

{% embed url="<https://www.comune.bugliano.pi.it/openapi/doc>" %}

* **Calendari, disponibilità, appuntamenti**

{% embed url="<https://servizi.comune.bugliano.pi.it/lang/api/doc>" %}

***

## **1. Integrazione IVR**

### **1.1 Flusso generale**

Il sistema IVR consente la prenotazione di appuntamenti tramite scelta vocale tra diverse tipologie di servizio, ad esempio:

* Rilascio documenti
* Certificati
* Identità digitale
* Autentiche

Per ogni servizio selezionato il flusso prevede due passaggi principali:

1. **Recupero configurazione del servizio**\
   Uffici, sedi e calendari associati.
2. **Recupero disponibilità**\
   Individuazione delle prime disponibilità nei calendari della sede scelta.

***

## **1.2 Recupero configurazione del servizio**

#### **Endpoint**

```
GET /api/openapi/booking-config?id={service_id}
```

#### **Descrizione**

Questa chiamata restituisce:

* Informazioni sul servizio
* Uffici che lo erogano
* Sedi
* Calendari associati alla sede

#### **Esempio di risposta (estratto)**

```json
{
  "items": [
    {
      "id": 2240,
      "link": "https://www.comune.bugliano.pi.it/api//servizi/47b0fb50deb217bfcceb5b6b4c32ba5b",
      "name": "Attivazione della TARI",
      "offices": [
        {
          "id": 856,
          "link": "https://www.comune.bugliano.pi.it/api//amministrazione/uffici/2c1aad31d1f20d6189ee5d1881a125e4",
          "name": "Ufficio Ambiente",
          "places": [
            {
              "id": 213,
              "link": "https://www.comune.bugliano.pi.it/api//vivere-il-comune/luoghi/4c246236f96f06a1a73a8ca05ebf71e7",
              "name": "Palazzo del municipio",
              "location": {
                "lat": 44.611185,
                "lng": 11.661106,
                "address": "Via Niccolò Macchiavelli 40062 Molinella"
              },
              "calendars": [...]
              ],
              ...              
            }
          ]
        }
      ],
      "categories": [
        "Tributi, finanze e contravvenzioni"
      ]
    }
  ],
  "self": "https://www.comune.bugliano.pi.it/api/openapi/booking-config?offset=0&limit=200&id=2240",
  "next": null,
  "prev": null,
  "count": 1
}
```

Il servizio è erogato dall’Ufficio Anagrafe in due sedi, è necessario individuare la sede desiderata per la quale si vogliono trovare le disponibilità.\
Ipotizziamo che ci interessino le disponibilità della sede di Via Niccolò Macchiavelli: dobbiamo entrare quindi nella struttura calendars, che è fatta come segue:

```json
{
  ...
  "calendars": [
    {
      "id": "b95b5409-2b3d-44d1-b534-12bb99206b1b",
      "link": "https://servizi.comune.bugliano.pi.it/lang/api/calendars/b95b5409-2b3d-44d1-b534-12bb99206b1b",
      "availabilities_link": "https://servizi.comune.bugliano.pi.it/lang/api/availabilities?available=true&calendar_ids=b95b5409-2b3d-44d1-b534-12bb99206b1b"
    },
    {
      "id": "d35879fc-2047-47ed-8dd1-e317dc6c5cd0",
      "link": "https://servizi.comune.bugliano.pi.it/lang/api/calendars/d35879fc-2047-47ed-8dd1-e317dc6c5cd0",
      "availabilities_link": "https://servizi.comune.bugliano.pi.it/lang/api/availabilities?available=true&calendar_ids=d35879fc-2047-47ed-8dd1-e317dc6c5cd0"
    },
    {
      "id": "2e1e0f6c-3b51-4877-86bc-c9331f46b423",
      "link": "https://servizi.comune.bugliano.pi.it/lang/api/calendars/2e1e0f6c-3b51-4877-86bc-c9331f46b423",
      "availabilities_link": "https://servizi.comune.bugliano.pi.it/lang/api/availabilities?available=true&calendar_ids=2e1e0f6c-3b51-4877-86bc-c9331f46b423"
    }
  ],
  "merge_availabilities": true,
  "merged_availabilities_link": "https://servizi.comune.bugliano.pi.it/lang/api/availabilities?available=true&calendar_ids=b95b5409-2b3d-44d1-b534-12bb99206b1b%2Cd35879fc-2047-47ed-8dd1-e317dc6c5cd0%2C2e1e0f6c-3b51-4877-86bc-c9331f46b423",
  ...
}

```

***

## **1.3 Recupero disponibilità**

Una volta selezionato il servizio è possibile fare la seconda chiamata che restituisce le disponibilità per i calendari collegati al servizio e alla sede selezionata<br>

Questa API è pensata per restituire **X slot ottimali** nell’ambito di un intervallo dinamico di giorni, utile per sistemi IVR che devono proporre appuntamenti.

#### **Endpoint**

```
GET /lang/api/availabilities/windowed?window_size=Y&limit=X&reserve=true|false&calendar_ids=...
```

#### **Parametri**

| Parametro      | Validazione e default                      | Descrizione                                                                                                            |
| -------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| `window_size`  | <p>intero, tra 1 e 30</p><p>default: 8</p> | Numero di giorni per i quali si vogliono degli appuntamenti liberi                                                     |
| `limit`        | <p>intero, tra 1 e 10<br>default: 3</p>    | Numero di appuntamenti che si vogliono suggerire nell’IVR                                                              |
| `reserve`      | <p>booleano<br>default: false</p>          | Riserva gli appuntamenti contestualmente alla chiamata, senza necessità di ulteriori chiamate per riservare i tre slot |
| `calendar_ids` | obbligatorio                               | Lista di UUID separati da virgola                                                                                      |

#### **Logica di selezione**

Per scegliere gli appuntamenti liberi viene individuato un intervallo di giorni in cui è presente almeno uno slot libero. È possibile quindi che vengano elencati dei giorni non consecutivi e questo rende indeterminabile a priori l’intervallo coperto da questa chiamata. Nell’esempio che segue vengono ritornati per esempio 8 giorni tra il 1 settembre e il 16 settembre. Su servizi con calendari molto saturi anche se vengono richiesti 8 giorni potrebbero esserci un numero minore di giorni tra cui scegliere.

Nel caso di servizi con calendari molto liberi di fatto stiamo individuando il numero massimo di giorni tra il primo e l’ultimo appuntamento suggerito. Nel caso di servizi con calendari saturati in modo molto disomogeneo potrebbero esserci intervalli di tempo anche molto ampi tra il primo e l’ultimo appuntamento suggerito.

<br>

Indichiamo i tre slot proposti con A, B, C

| <p><br></p> | 1 disp      | 2           | 3           | 4           | 5           | 6           | 7           | 8           |
| ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- |
| <p><br></p> | 1/9/25      | 2/9/25      | 5/9/25      | 7/9/25      | 8/9/25      | 10/9/25     | 11/9/25     | 16/9/25     |
| Matt        | A           | <p><br></p> | <p><br></p> | <p><br></p> | <p><br></p> | <p><br></p> | <p><br></p> | C           |
| Pom         | <p><br></p> | <p><br></p> | <p><br></p> | B           | <p><br></p> | <p><br></p> | <p><br></p> | <p><br></p> |

<br>

Nell’intervallo di giorni individuati restituisce la prima (A) e l’ultima disponibilità (C) di quei giorni: questo favorisce al massimo la differenza della fascia oraria negli slot suggeriti.

La seconda disponibilità è nel giorno di mezzo dell’intervallo di 8 giorni, la piattaforma cerca, se è possibile, di restituire un periodo del giorno diverso da quello del PRIMO meeting (A).

Se A è di mattina B è nel pomeriggio e viceversa.

<br>

#### **Esempio**

Calendario con disponibilità Lu, Ma, Me, Gio, Ve | 09:00 - 18:00

```json
{
  "meta": {
    "count": 3,
    "parameter": {
      "calendar_ids": "83bb67e1-2137-4852-b6b1-d68809df43b1",
      "reserve": false,
      "window_size": "8",
      "limit": "3"
    }
  },
  "links": {
    "self": null,
    "prev": null,
    "next": null
  },
  "data": [
    {
      "date": "2025-07-31",
      "start_time": "10:30",
      "end_time": "11:00",
      "slots_available": 1,
      "availability": true,
      "opening_hour_id": "a90d71fe-0d56-4a1b-a1cf-11a567541041",
      "calendar_id": "83bb67e1-2137-4852-b6b1-d68809df43b1",
      "meeting_id": null, // null|Uuid meeting in bozza, valorizzato solo se reserve = true
      "meeting_code": "K001"// null|string 
    },
    {
      "date": "2025-08-05",
      "start_time": "12:00",
      "end_time": "12:30",
      "slots_available": 1,
      "availability": true,
      "opening_hour_id": "a90d71fe-0d56-4a1b-a1cf-11a567541041",
      "calendar_id": "83bb67e1-2137-4852-b6b1-d68809df43b1",
      "meeting_id": null, // null|Uuid meeting in bozza, valorizzato solo se reserve = true
      "meeting_code": "K002"// null|string
    },
    {
      "date": "2025-08-08",
      "start_time": "09:00",
      "end_time": "09:30",
      "slots_available": 1,
      "availability": true,
      "opening_hour_id": "a90d71fe-0d56-4a1b-a1cf-11a567541041",
      "calendar_id": "83bb67e1-2137-4852-b6b1-d68809df43b1",
      "meeting_id": null, // null|Uuid meeting in bozza, valorizzato solo se reserve = true
      "meeting_code": "K003" // null|string 
    }
  ]
}
```

***

## **1.4 Prima data disponibile**

Questo endpoint restituisce il primo giorno con almeno una disponibilità tra i calendari indicati. È utile per mostrare al cittadino la prima data prenotabile prima che scelga uno slot specifico.

La chiamata richiede autenticazione come **bearer token** nell'header `Authorization` (vedi [Autenticazione](/sviluppatori-e-partner-tecnologici/integrazioni/integrazioni-con-il-flusso-delle-pratiche/api-rest.md#autenticazione)).

#### **Endpoint**

```
GET /lang/api/availabilities/first-available-date?calendar_ids=UUID1,UUID2,...
```

#### **Parametri**

| Parametro      | Obbligatorio | Descrizione                                     |
| -------------- | ------------ | ----------------------------------------------- |
| `calendar_ids` | Sì           | Lista di UUID dei calendari separati da virgola |

#### **Visibilità per ruolo**

I risultati variano in base al ruolo dell'utente chiamante:

* per il **cittadino** (CPSUser) sono applicati il preavviso minimo e la profondità di prenotazione configurati sul calendario;
* per **operatore** e **amministratore** non si applicano restrizioni di tempo.

#### **Esempio di risposta**

HTTP 200:

```json
{
  "date": "2024-02-20"
}
```

#### **Errori**

| Codice HTTP | Causa                                                                 |
| ----------- | --------------------------------------------------------------------- |
| 400         | Parametro `calendar_ids` assente o UUID non valido                    |
| 404         | Calendario non trovato o nessuna disponibilità nei calendari indicati |

***

## **1.5 Conferma degli appuntamenti**

In caso di `reserve = true` il campo `meetind_id` sarà valorizzato con uuid del meeting in bozza, per poter confermare un meeting andrà fatta una PUT/PATCH sul meeting selezionato cambiando lo stato ed inserendo anche i dati generali del meeting (Nome del richiedente, email, numero di telefono ecc ecc)

<br>

#### **Endpoint**

```
PATCH /lang/api/meetings/{meeting_id}
```

#### **Esempio**

```json
{
  "status": "1", // Stato confermato
  "name": "Mario Rossi",
  "email": "",
  "phone_number": "",
  "reason": "",
  "user_message": "",
  "motivation_outcome": "",
  "videoconference_link": "",
  "opening_hour": "",
  "locale": "it",
  "calendar_group_config_id": "5916", // Id del servizio 
  "calendar_group_office_id": "964",  // Id dell’ufficio
  "calendar_group_place_id": "780",   // Id della sede
  "location": ""
}

```

***

## **2. Integrazione Sistemi Tagliacode**

I sistemi di gestione code possono sincronizzare ogni giorno gli appuntamenti previsti per una sede specifica.

Poiché i calendari accettano tipicamente prenotazioni solo fino al giorno successivo, **è sufficiente un’unica sincronizzazione giornaliera**.

***

## **2.1 Recupero agende relative a una sede**

#### **Endpoint**

```
GET /api/openapi/booking-config?place_id={place_id}
```

Questa chiamata restituisce:

* Tutti i servizi erogati nella sede
* Tutti i calendari da cui provengono gli appuntamenti

I calendar ID ottenuti saranno utilizzati nella chiamata successiva.

#### **Esempio di risposta**

```json
{
  "items": [
    {
      "id": 2240,
      "link": "https://www.comune.bugliano.pi.it/api//servizi/47b0fb50deb217bfcceb5b6b4c32ba5b",
      "name": "Attivazione della TARI",
      "offices": [
        {
          "id": 856,
          "link": "https://www.comune.bugliano.pi.it/api//amministrazione/uffici/2c1aad31d1f20d6189ee5d1881a125e4",
          "name": "Ufficio Ambiente",
          "places": [
            {
              "id": 213,
              "link": "https://www.comune.bugliano.pi.it/api//vivere-il-comune/luoghi/4c246236f96f06a1a73a8ca05ebf71e7",
              "name": "Palazzo del municipio",
              "location": {
                "lat": 44.611185,
                "lng": 11.661106,
                "address": "Via Niccol&ograve; Macchiavelli 40062 Molinella"
              },
              "calendars": [
                {
                  "id": "b95b5409-2b3d-44d1-b534-12bb99206b1b",
                  "link": "https://servizi.comune.bugliano.pi.it/lang/api/calendars/b95b5409-2b3d-44d1-b534-12bb99206b1b",
                  "availabilities_link": "https://servizi.comune.bugliano.pi.it/lang/api/availabilities?available=true&calendar_ids=b95b5409-2b3d-44d1-b534-12bb99206b1b"
                },
                {
                  "id": "d35879fc-2047-47ed-8dd1-e317dc6c5cd0",
                  "link": "https://servizi.comune.bugliano.pi.it/lang/api/calendars/d35879fc-2047-47ed-8dd1-e317dc6c5cd0",
                  "availabilities_link": "https://servizi.comune.bugliano.pi.it/lang/api/availabilities?available=true&calendar_ids=d35879fc-2047-47ed-8dd1-e317dc6c5cd0"
                },
                {
                  "id": "2e1e0f6c-3b51-4877-86bc-c9331f46b423",
                  "link": "https://servizi.comune.bugliano.pi.it/lang/api/calendars/2e1e0f6c-3b51-4877-86bc-c9331f46b423",
                  "availabilities_link": "https://servizi.comune.bugliano.pi.it/lang/api/availabilities?available=true&calendar_ids=2e1e0f6c-3b51-4877-86bc-c9331f46b423"
                }
              ],
              "merge_availabilities": true,
              "merged_availabilities_link": "https://servizi.comune.bugliano.pi.it/lang/api/availabilities?available=true&calendar_ids=b95b5409-2b3d-44d1-b534-12bb99206b1b%2Cd35879fc-2047-47ed-8dd1-e317dc6c5cd0%2C2e1e0f6c-3b51-4877-86bc-c9331f46b423"
            }
          ]
        }
      ],
      "categories": [
        "Tributi, finanze e contravvenzioni"
      ],
      "show_howto_in_motivation": true,
      "view_type": "select"
    }
  ]
}
```

***

## **2.2 Recupero appuntamenti del giorno**

La chiamata è autenticata, si dovranno utilizzare le credenziali fornite per reperire un token JWT da allegare alla chiamata come indicato nella documentazione:

{% embed url="<https://docs.opencityitalia.it/developers/integrazioni/integrazioni-con-il-flusso-delle-pratiche/api-rest#autenticazione>" %}

#### **Endpoint**

```
GET /lang/api/meetings?calendars_ids=C1,C2,C3&from_time=...&to_time=...
```

Il risultato è una struttura dati di questo tipo (si omettono volutamente i campi non strettamente necessari): ogni elemento dell’array contiene un appuntamento per una persona con codice breve code.

#### **Esempio di risposta (estratto)**

```json
[
  {
    "id": "5b00796e-ef10-4c98-b9f5-b0f7ffd7a17d",
    "user": "5300188a-fc05-4f49-8933-6d2d7d5c9ebc",
    "email": "string",
    "phone_number": "string",
    "fiscal_code": "string",
    "name": "string",
    "from_time": "2025-06-03T10:00:00+02:00",
    "to_time": "2025-06-03T10:20:00+02:00",
    "status": 1,
    "code": "K123",
    "calendar_group_config_id": "2282",
    "calendar_group_office_id": "964",
    "calendar_group_place_id": "4864"
  }
]

```

Nel json dell’appuntamento verranno riportate anche le indicazioni relative al servizio, alla sede ed all’ufficio.

* id del servizio → calendar\_group\_config\_id
* id dell’ufficio → calendar\_group\_office\_id
* id della sede → calendar\_group\_place\_id


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.opencityitalia.it/sviluppatori-e-partner-tecnologici/integrazioni/integrazione-dei-calendari-con-un-servizio-di-terze-parti.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
