Appuntamenti
L’API Appointments ti consente di prenotare appuntamenti per i tuoi contatti sui tuoi tipi di evento, quindi di recuperarli, elencarli, aggiornarli, annullarli o eliminarli. Risponde anche alla domanda che sorge per prima nella maggior parte dei flussi di prenotazione — quali orari sono effettivamente liberi — e copre il lato calendario: elencando i Google Calendar che hai collegato e importando gli eventi che vi sono già presenti. Quando una connessione a Google Calendar è attiva, l’evento del calendario corrispondente viene creato e mantenuto sincronizzato automaticamente in background. I ristoranti che utilizzano Zenchef, Formitable, OpenTable o TheFork per il proprio sistema di prenotazione possono anche essere verificati e collegati qui, in modo che l’Agente AI prenoti tavoli reali invece di appuntamenti interni — e le attività basate su appuntamenti che gestiscono la propria programmazione in Trafft possono connettersi allo stesso modo.
Tutti i percorsi in questa pagina sono relativi all’URL di base https://api.dmchamp.com/v1. Ogni richiesta richiede la tua chiave API: consulta Autenticazione per l’elenco completo delle modalità di invio. Gli esempi seguenti utilizzano l’intestazione X-API-Key, con un esempio cURL che mostra anche il formato di query ?apiKey=.
Eventi vs. appuntamenti: Una tipologia di evento è la definizione di uno slot prenotabile (il tipo di riunione, la sua durata, le sue sale). Un appuntamento è una singola istanza prenotata di una tipologia di evento per uno specifico contatto. Prenoti un appuntamento facendo riferimento al contatto e alla tipologia di evento.
L’oggetto appuntamento
Ogni endpoint che restituisce un appuntamento utilizza la stessa struttura:
| Campo | Descrizione |
|---|---|
id |
ID univoco dell’appuntamento. |
contact_id |
ID del contatto con cui è prenotato l’appuntamento. |
event_id |
ID della tipologia di evento su cui è stato prenotato l’appuntamento. |
status |
Confirmed o Canceled. |
start_time |
Inizio dell’appuntamento, ISO 8601 in UTC. |
end_time |
Fine dell’appuntamento, ISO 8601 in UTC. |
created_at |
Quando è stato creato l’appuntamento. |
last_modified_at |
Quando l’appuntamento è stato modificato l’ultima volta. |
room_name |
Sala o risorsa in cui è prenotato l’appuntamento, quando la tipologia di evento utilizza le sale. |
description |
Descrizione a formato libero dell’appuntamento. |
summary |
Breve riepilogo o titolo. |
cancelation_reason |
Motivo fornito al momento dell’annullamento dell’appuntamento, se presente. |
google_calendar_event_id |
ID dell’evento di Google Calendar collegato. Impostato una volta completata la sincronizzazione del calendario; null quando nessun calendario è collegato o mentre la sincronizzazione è ancora in corso. |
calendar_synced |
true una volta che l’appuntamento è collegato a un evento di calendario. |
imported |
true quando l’appuntamento è stato importato da un calendario esterno anziché prenotato direttamente. |
is_recurring |
true quando l’appuntamento fa parte di una serie ricorrente. |
recurrence_frequency |
Frequenza di ripetizione dell’appuntamento, quando ricorrente. |
recurring_event_id |
ID della serie ricorrente a cui appartiene questo appuntamento. |
recurring_interval |
Intervallo tra le ripetizioni, quando ricorrente. |
recurring_sequence |
Posizione di questo appuntamento all’interno della sua serie ricorrente. |
end_after_x_occurrences |
Numero di occorrenze dopo le quali termina la serie ricorrente. |
booking_provider |
Sistema di origine da cui proviene la prenotazione, quando prenotato tramite un fornitore di prenotazioni collegato. |
Informazioni sulla sincronizzazione del calendario: Subito dopo aver prenotato o modificato un appuntamento,
google_calendar_event_idpotrebbe essere ancoranullecalendar_syncedpotrebbe esserefalseperché la sincronizzazione viene eseguita in background poco dopo. Recupera nuovamente l’appuntamento poco dopo per visualizzare i campi del calendario popolati.
Trova gli slot disponibili
GET /appointments/available-slots
Restituisce gli orari che sono effettivamente liberi per un tipo di evento tra due momenti. Questa è solitamente la prima chiamata in un flusso di prenotazione: mostra questi slot, lascia che la persona ne scelga uno, quindi invia l’orario scelto a Prenota un appuntamento.
La risposta tiene già conto degli orari di apertura e della durata dello slot del tipo di evento, delle sue sale, degli appuntamenti che hai già prenotato su di esso e di tutto ciò che è bloccato sui Google Calendar collegati — quindi uno slot restituito qui è uno slot che puoi prenotare.
| Parametro di query | Obbligatorio | Descrizione |
|---|---|---|
event_id |
Sì | Il tipo di evento da controllare. Deve appartenere al tuo account. |
start_time |
Sì | Inizio della finestra per cui desideri gli slot, data-ora ISO 8601. |
end_time |
Sì | Fine della finestra, data-ora ISO 8601. L’intero giorno finale è incluso. |
I risultati vengono restituiti raggruppati per giorno — e, quando il tipo di evento utilizza le sale, un gruppo per sala per giorno:
| Campo | Descrizione |
|---|---|
date |
Il giorno coperto dal gruppo, scritto DD/MM/YYYY. |
day |
Nome del giorno della settimana in minuscolo, ad esempio monday. |
room_name |
La sala o la risorsa a cui appartiene questo gruppo, quando il tipo di evento utilizza le sale. |
available_slots |
I blocchi prenotabili in quel giorno, dal più presto al più tardi. |
Ogni voce in available_slots ha:
| Campo | Descrizione |
|---|---|
start_time |
Inizio del blocco come HH:mm. |
end_time |
Fine del blocco come HH:mm. |
available |
true — viene restituito solo il tempo libero. |
spots_left |
Quante prenotazioni rientrano ancora in questo blocco. Presente solo sui tipi di evento che accettano più di una prenotazione per slot. |
Gli orari sono locali rispetto al tipo di evento, non UTC.
date,start_timeeend_timesono valori di orologio locale nel fuso orario del tipo di evento (il suo override, o il fuso orario del tuo account quando non ne ha uno). Prenota un appuntamento si aspetta un istante UTC ISO 8601, quindi converti lo slot che hai scelto prima di inviarlo.
cURL
curl "https://api.dmchamp.com/v1/appointments/available-slots?event_id=event_xyz789&start_time=2026-06-15T00:00:00.000Z&end_time=2026-06-19T00:00:00.000Z" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({
event_id: "event_xyz789",
start_time: "2026-06-15T00:00:00.000Z",
end_time: "2026-06-19T00:00:00.000Z",
});
const res = await fetch(
`https://api.dmchamp.com/v1/appointments/available-slots?${params}`,
{ headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.data);
Python
import requests
res = requests.get(
"https://api.dmchamp.com/v1/appointments/available-slots",
headers={"X-API-Key": "YOUR_API_KEY"},
params={
"event_id": "event_xyz789",
"start_time": "2026-06-15T00:00:00.000Z",
"end_time": "2026-06-19T00:00:00.000Z",
},
)
print(res.json()["data"])
Risposta (200 OK):
{
"success": true,
"data": [
{
"date": "15/06/2026",
"day": "monday",
"room_name": "Room A",
"available_slots": [
{ "start_time": "10:00", "end_time": "10:30", "available": true },
{ "start_time": "10:30", "end_time": "11:00", "available": true }
]
},
{
"date": "16/06/2026",
"day": "tuesday",
"room_name": "Room A",
"available_slots": [
{ "start_time": "09:00", "end_time": "09:30", "available": true, "spots_left": 2 }
]
}
]
}
Un giorno senza disponibilità semplicemente non appare. event_id, start_time o end_time mancanti restituiscono 400; un tipo di evento che non è sul tuo account restituisce 404.
Prenota un appuntamento
POST /appointments
Prenota un nuovo appuntamento per un contatto su una delle tue tipologie di evento. L’orario di fine viene calcolato automaticamente in base alla durata dello slot della tipologia di evento.
La prenotazione viene controllata per verificare la presenza di conflitti: se lo slot richiesto si sovrappone a un appuntamento confermato esistente sulla stessa tipologia di evento, la richiesta fallisce con un 409 e non viene creato nulla.
| Campo | Obbligatorio | Descrizione |
|---|---|---|
contact_id |
Sì | ID del contatto per cui prenotare. Deve appartenere al tuo account. |
event_id |
Sì | ID della tipologia di evento su cui prenotare. Deve appartenere al tuo account. |
start_time |
Sì | Inizio desiderato come data-ora ISO 8601. |
room_name |
No | Nome della sala o della risorsa, quando la tipologia di evento utilizza le sale. |
cURL (utilizzando il formato di query ?apiKey=)
curl -X POST "https://api.dmchamp.com/v1/appointments?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contact_id": "contact_abc123",
"event_id": "event_xyz789",
"start_time": "2026-06-15T10:00:00.000Z",
"room_name": "Room A"
}'
JavaScript
const res = await fetch("https://api.dmchamp.com/v1/appointments", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
contact_id: "contact_abc123",
event_id: "event_xyz789",
start_time: "2026-06-15T10:00:00.000Z",
room_name: "Room A",
}),
});
const data = await res.json();
console.log(data.appointment_id);
Python
import requests
res = requests.post(
"https://api.dmchamp.com/v1/appointments",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"contact_id": "contact_abc123",
"event_id": "event_xyz789",
"start_time": "2026-06-15T10:00:00.000Z",
"room_name": "Room A",
},
)
print(res.json()["appointment_id"])
Risposta (201 Created):
{
"success": true,
"appointment_id": "aBcD1234eFgH5678",
"appointment": {
"id": "aBcD1234eFgH5678",
"contact_id": "contact_abc123",
"event_id": "event_xyz789",
"status": "Confirmed",
"start_time": "2026-06-15T10:00:00.000Z",
"end_time": "2026-06-15T10:30:00.000Z",
"created_at": "2026-06-10T09:00:00.000Z",
"last_modified_at": "2026-06-10T09:00:00.000Z",
"room_name": "Room A",
"google_calendar_event_id": null,
"calendar_synced": false
}
}
Ottieni un appuntamento
GET /appointments/{appointmentId}
Restituisce un singolo appuntamento tramite il suo ID, incluso il suo stato di sincronizzazione del calendario.
cURL
curl "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch(
"https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678",
{ headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.appointment);
Python
import requests
res = requests.get(
"https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678",
headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["appointment"])
Risposta (200 OK):
{
"success": true,
"appointment": {
"id": "aBcD1234eFgH5678",
"contact_id": "contact_abc123",
"event_id": "event_xyz789",
"status": "Confirmed",
"start_time": "2026-06-15T10:00:00.000Z",
"end_time": "2026-06-15T10:30:00.000Z",
"room_name": "Room A",
"google_calendar_event_id": "abc123googleevent",
"calendar_synced": true
}
}
Elenca appuntamenti
GET /appointments
Elenca gli appuntamenti per il tuo account, dal più recente, con paginazione basata su cursore.
| Parametro di query | Obbligatorio | Descrizione |
|---|---|---|
contact_id |
No | Restituisce solo gli appuntamenti per questo contatto. Gli elenchi filtrati per contatto includono solo gli appuntamenti confermati. |
date |
No | Restituisce solo gli appuntamenti in questo giorno del calendario (YYYY-MM-DD). Richiede contact_id. |
status |
No | Filtra per Confirmed o Canceled. Disponibile solo senza contact_id. |
limit |
No | Dimensione della pagina, un numero intero tra 1 e 100. Predefinito 50. |
cursor |
No | Il valore next_cursor da una risposta precedente. |
Alcune regole da tenere a mente:
- Senza filtri, ottieni ogni appuntamento sull’account, pagina per pagina.
- Per contatto — imposta
contact_idper vedere gli appuntamenti confermati di un contatto. Puoi restringere il campo a un singolo giorno passando anchedate. - Per stato — imposta
status(senzacontact_id) per elencare solo gli appuntamentiConfirmedo soloCancelednell’account. - Il filtro
datesenzacontact_id, ostatus=Canceledinsieme acontact_id, restituisce un400.
cURL
curl "https://api.dmchamp.com/v1/appointments?contact_id=contact_abc123&date=2026-06-15" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({
contact_id: "contact_abc123",
date: "2026-06-15",
});
const res = await fetch(
`https://api.dmchamp.com/v1/appointments?${params}`,
{ headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.appointments, data.next_cursor);
Python
import requests
res = requests.get(
"https://api.dmchamp.com/v1/appointments",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"contact_id": "contact_abc123", "date": "2026-06-15"},
)
data = res.json()
print(data["appointments"], data["next_cursor"])
Risposta (200 OK):
{
"success": true,
"appointments": [
{
"id": "aBcD1234eFgH5678",
"contact_id": "contact_abc123",
"event_id": "event_xyz789",
"status": "Confirmed",
"start_time": "2026-06-15T10:00:00.000Z",
"end_time": "2026-06-15T10:30:00.000Z",
"calendar_synced": true
}
],
"next_cursor": null
}
Per scorrere i risultati, passa il next_cursor da una risposta come cursor della richiesta successiva. Continua finché next_cursor non è null. Vedi Errori e Paginazione per il pattern di paginazione condiviso.
Aggiorna un appuntamento
PUT /appointments/{appointmentId}
Ripianifica un appuntamento o modifica i suoi dettagli. Invia solo i campi che desideri modificare: almeno uno è obbligatorio. L’inizio e la fine combinati devono rimanere in ordine cronologico (end_time deve essere successivo a start_time). Le modifiche vengono sincronizzate automaticamente con l’evento del calendario collegato.
| Campo | Descrizione |
|---|---|
start_time |
Nuovo inizio, data-ora in formato ISO 8601. |
end_time |
Nuova fine, data-ora in formato ISO 8601. Deve essere successiva all’orario di inizio. |
room_name |
Nuovo nome della stanza o della risorsa. |
description |
Nuova descrizione, o null per cancellarla. |
summary |
Nuovo riepilogo, o null per cancellarlo. |
cURL
curl -X PUT "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"start_time": "2026-06-16T10:00:00.000Z",
"end_time": "2026-06-16T10:30:00.000Z"
}'
JavaScript
const res = await fetch(
"https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678",
{
method: "PUT",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
start_time: "2026-06-16T10:00:00.000Z",
end_time: "2026-06-16T10:30:00.000Z",
}),
}
);
const data = await res.json();
console.log(data.appointment);
Python
import requests
res = requests.put(
"https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"start_time": "2026-06-16T10:00:00.000Z",
"end_time": "2026-06-16T10:30:00.000Z",
},
)
print(res.json()["appointment"])
Risposta (200 OK):
{
"success": true,
"appointment_id": "aBcD1234eFgH5678",
"appointment": {
"id": "aBcD1234eFgH5678",
"contact_id": "contact_abc123",
"event_id": "event_xyz789",
"status": "Confirmed",
"start_time": "2026-06-16T10:00:00.000Z",
"end_time": "2026-06-16T10:30:00.000Z",
"calendar_synced": true
}
}
Annulla un appuntamento
POST /appointments/{appointmentId}/cancel
Annulla un appuntamento confermato, registrando facoltativamente un motivo. L’appuntamento rimane nel tuo account con lo stato Canceled e l’evento del calendario collegato viene rimosso automaticamente in background. L’annullamento di un appuntamento già annullato restituisce un 400.
| Campo | Obbligatorio | Descrizione |
|---|---|---|
cancellation_reason |
No | Motivo dell’annullamento, memorizzato nell’appuntamento. |
cURL
curl -X POST "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678/cancel" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"cancellation_reason": "Client asked to reschedule next month"
}'
JavaScript
const res = await fetch(
"https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678/cancel",
{
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
cancellation_reason: "Client asked to reschedule next month",
}),
}
);
const data = await res.json();
console.log(data.success);
Python
import requests
res = requests.post(
"https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678/cancel",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={"cancellation_reason": "Client asked to reschedule next month"},
)
print(res.json()["success"])
Risposta (200 OK):
{
"success": true,
"appointment_id": "aBcD1234eFgH5678"
}
Elimina un appuntamento
DELETE /appointments/{appointmentId}
Elimina definitivamente un appuntamento e i suoi riferimenti. Se desideri solo annullare la prenotazione mantenendo il record, utilizza invece annulla.
cURL
curl -X DELETE "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch(
"https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678",
{ method: "DELETE", headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.success);
Python
import requests
res = requests.delete(
"https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678",
headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["success"])
Risposta (200 OK):
{
"success": true
}
Elenca i tuoi Google Calendar collegati
GET /appointments/google-calendars
Restituisce i Google Calendar disponibili su questo account, direttamente da Google — utile per mostrare al titolare dell’account un selettore da cui importare il calendario qui sotto, o semplicemente per confermare che la connessione è attiva.
Questo funziona solo una volta che l’account ha collegato Google Calendar (Impostazioni → Integrazioni) con almeno l’accesso in lettura. Se non lo ha fatto, o se l’accesso concesso non include più l’ambito di lettura del calendario, riceverai un 400 che ti invita a (ri)collegarlo.
cURL
curl "https://api.dmchamp.com/v1/appointments/google-calendars" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch("https://api.dmchamp.com/v1/appointments/google-calendars", {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.data);
Python
import requests
res = requests.get(
"https://api.dmchamp.com/v1/appointments/google-calendars",
headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["data"])
Risposta (200 OK):
{
"success": true,
"data": [
{
"id": "primary",
"summary": "jane@example.com",
"timeZone": "America/New_York",
"accessRole": "owner",
"primary": true
},
{
"id": "abcdefg1234567890@group.calendar.google.com",
"summary": "Bookings",
"timeZone": "America/New_York",
"accessRole": "writer"
}
]
}
Ogni voce ha la forma CalendarListEntry di Google, quindi i nomi dei campi seguono lo camelCase di Google, non il solito snake_case di questa API: si tratta dei dati di Google trasmessi così come sono, non dei nostri. Una connessione mancante o revocata restituisce 400 con un errore che spiega che Google Calendar deve essere (ri)collegato.
Importa eventi da un Google Calendar
POST /appointments/import-calendar-events
Estrae gli eventi già presenti nel/i Google Calendar collegato/i di una campagna o di un Agente AI e li trasforma in appuntamenti; è utile la prima volta che si collega un calendario che ha già delle prenotazioni. Questa operazione può richiedere del tempo (ogni evento viene analizzato per capire a chi è destinato), quindi non viene mai eseguita in linea: la richiesta accoda un processo in background e ti restituisce un job_id da interrogare.
| Campo | Obbligatorio | Descrizione |
|---|---|---|
campaign_id |
Uno di questi due | La campagna da cui importare i calendari collegati. |
agent_id |
Uno di questi due | L’Agente AI da cui importare i calendari collegati. |
identifier |
Sì | "EMAIL" o "PHONE_NUMBER": quale informazione di contatto estrarre da ogni evento del calendario per trovare o creare il contatto a cui appartiene. |
Invia esattamente uno tra campaign_id / agent_id, mai entrambi e mai nessuno dei due: qualsiasi altra combinazione restituisce un 400. Qualunque tu scelga di inviare deve appartenere al tuo account, altrimenti riceverai un 404.
cURL
curl -X POST "https://api.dmchamp.com/v1/appointments/import-calendar-events?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "agent_abc123",
"identifier": "EMAIL"
}'
JavaScript
const res = await fetch("https://api.dmchamp.com/v1/appointments/import-calendar-events", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
agent_id: "agent_abc123",
identifier: "EMAIL",
}),
});
const data = await res.json();
console.log(data.job_id);
Python
import requests
res = requests.post(
"https://api.dmchamp.com/v1/appointments/import-calendar-events",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={"agent_id": "agent_abc123", "identifier": "EMAIL"},
)
print(res.json()["job_id"])
Risposta (202 Accepted):
{
"success": true,
"job_id": "jK9mQ2xR7pL4wN1t",
"status": "queued",
"campaign_id": null,
"agent_id": "agent_abc123"
}
campaign_id e agent_id rimandano quello che hai inviato; l’altro è sempre null.
Interroga il processo di importazione
GET /appointments/import-calendar-events/{jobId}
curl "https://api.dmchamp.com/v1/appointments/import-calendar-events/jK9mQ2xR7pL4wN1t" \
-H "X-API-Key: YOUR_API_KEY"
Risposta (200 OK):
{
"success": true,
"job_id": "jK9mQ2xR7pL4wN1t",
"status": "completed",
"message": "Imported 12 events as appointments.",
"error": null
}
status |
Significato |
|---|---|
queued |
Non ancora preso in carico. Continua a interrogare. |
processing |
L’importazione è in corso. Continua a interrogare. |
completed |
Completato: message contiene un breve riepilogo leggibile. |
failed |
Qualcosa è andato storto: error contiene il motivo. |
GET su un jobId che non esiste (o appartiene a un account diverso) restituisce 404.
Integrazioni di prenotazione esterne (Zenchef / Formitable / OpenTable / TheFork / Trafft)
Zenchef e Formitable sono sistemi di prenotazione per ristoranti tramite i quali il tuo Agente IA può prenotare tavoli reali; Trafft è una piattaforma di pianificazione per attività basate su appuntamenti, collegata una volta per account anziché per ristorante. Le due piattaforme per ristoranti dispongono ciascuna di un widget di prenotazione pubblico e non autenticato (https://api.dmchamp.com/v1/zenchef-widget/... e https://api.dmchamp.com/v1/formitable-widget/...) che viene visualizzato all’interno della chat per il cliente — tali percorsi del widget sono semplici pagine HTML destinate ad essere aperte in un browser, non endpoint API JSON, quindi non sono documentati qui. Di seguito sono riportati gli endpoint di gestione dell’account: verifica che un ID ristorante appartenga al titolare dell’account, quindi aggiunta, aggiornamento o rimozione dello stesso.
Zenchef
La connessione di un ristorante Zenchef è una verifica in due passaggi, in modo che il titolare dell’account dimostri di gestire effettivamente il ristorante prima che venga collegato al bot: prima si verifica che l’ID esista (senza rivelare il nome), poi si chiede di digitare il nome del ristorante e si verifica che corrisponda.
Passaggio 1 — Verificare che un ID ristorante esista
POST /appointments/zenchef-restaurants/check
| Campo | Obbligatorio | Descrizione |
|---|---|---|
restaurant_id |
Sì | L’ID del ristorante Zenchef da verificare. |
curl -X POST "https://api.dmchamp.com/v1/appointments/zenchef-restaurants/check?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "restaurant_id": "12345" }'
Risposta (200 OK):
{
"success": true,
"data": { "exists": true, "requiresNameVerification": true }
}
exists: false significa che nessun ristorante Zenchef possiede quell’ID: non c’è altro da fare. Limitato a 10 controlli ogni 5 minuti per account; il superamento di questo limite restituisce 429.
Passaggio 2 — Verificare il nome del ristorante
POST /appointments/zenchef-restaurants/verify-name
| Campo | Obbligatorio | Descrizione |
|---|---|---|
restaurant_id |
Sì | L’ID del ristorante Zenchef dal passaggio 1. |
user_input_name |
Sì | Il nome digitato dal titolare dell’account: confrontato con il nome reale del ristorante su Zenchef (non sensibile a maiuscole/minuscole o spazi). |
curl -X POST "https://api.dmchamp.com/v1/appointments/zenchef-restaurants/verify-name?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "restaurant_id": "12345", "user_input_name": "The Blue Door Bistro" }'
Risposta (200 OK):
{
"success": true,
"data": {
"verified": true,
"restaurantDetails": {
"id": "12345",
"name": "The Blue Door Bistro",
"address": "1 Rue de Rivoli, Paris",
"status": "active"
}
}
}
verified: false significa che il nome non corrisponde: restaurantDetails viene omesso, chiedi al titolare dell’account di riprovare. Limitato a 3 tentativi ogni 5 minuti (più restrittivo del controllo di esistenza, poiché questo è il passaggio di prova effettivo). Un restaurant_id che non è più risolvibile su Zenchef restituisce 404.
Passaggio 3 — Salvare il ristorante
POST /appointments/zenchef-restaurants
| Campo | Obbligatorio | Descrizione |
|---|---|---|
restaurant_id |
Sì | 1–64 caratteri, lettere/numeri/underscore/trattino. |
restaurant_name |
Sì | Il nome del ristorante verificato dal passaggio 2. |
curl -X POST "https://api.dmchamp.com/v1/appointments/zenchef-restaurants?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "restaurant_id": "12345", "restaurant_name": "The Blue Door Bistro" }'
Risposta (201 Created):
{ "success": true, "data": { "restaurantId": "12345" } }
Aggiornare un ristorante Zenchef salvato
PUT /appointments/zenchef-restaurants/{restaurantId}
| Campo | Obbligatorio | Descrizione |
|---|---|---|
restaurant_name |
No | Nuovo nome visualizzato. |
is_active |
No | Imposta false per impedire al bot di effettuare prenotazioni presso questo ristorante senza rimuoverlo. |
curl -X PUT "https://api.dmchamp.com/v1/appointments/zenchef-restaurants/12345" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "is_active": false }'
Risposta (200 OK): stessa struttura della risposta di salvataggio sopra.
Rimuovere un ristorante Zenchef
DELETE /appointments/zenchef-restaurants/{restaurantId}
curl -X DELETE "https://api.dmchamp.com/v1/appointments/zenchef-restaurants/12345" \
-H "X-API-Key: YOUR_API_KEY"
Risposta (200 OK): { "success": true, "data": { "restaurantId": "12345" } }
Un restaurantId non attualmente presente nell’account restituisce 404 in caso di aggiornamento o eliminazione.
Formitable
Formitable non richiede la verifica del nome in due passaggi necessaria per Zenchef: i suoi ID ristorante sono già limitati per attività, quindi una sola chiamata di verifica è sufficiente. Dispone inoltre di una ricerca dei dettagli utilizzata per memorizzare nella cache l’URL del sito web del ristorante durante la configurazione.
Verificare un ID ristorante
POST /appointments/formitable-restaurants/verify
| Campo | Obbligatorio | Descrizione |
|---|---|---|
restaurant_id |
Sì | L’ID ristorante Formitable. |
language |
No | Tag della lingua per la richiesta di sondaggio. L’impostazione predefinita è "nl". |
curl -X POST "https://api.dmchamp.com/v1/appointments/formitable-restaurants/verify?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "restaurant_id": "the-blue-door", "language": "en" }'
Risposta (200 OK):
{
"success": true,
"data": {
"verified": true,
"restaurantDetails": {
"restaurantId": "the-blue-door",
"productCount": 4,
"sampleProductTitle": "Dinner for two",
"language": "en"
}
}
}
Un restaurant_id non riconosciuto da Formitable restituisce 404. Limitato a 10 tentativi ogni 5 minuti per account.
Ottenere i dettagli del ristorante
GET /appointments/formitable-restaurants/{restaurantId}/details?language=en
Recupera il profilo pubblico del ristorante da Formitable, incluso il suo sito web: utilizzato per memorizzare nella cache l’URL del sito web durante la configurazione del ristorante. language è un parametro di query opzionale, con valore predefinito "en".
curl "https://api.dmchamp.com/v1/appointments/formitable-restaurants/the-blue-door/details?language=en" \
-H "X-API-Key: YOUR_API_KEY"
Risposta (200 OK):
{
"success": true,
"data": {
"uid": "the-blue-door",
"name": "The Blue Door Bistro",
"website": "https://thebluedoorbistro.com",
"email": "info@thebluedoorbistro.com",
"telephone": "+31201234567",
"streetAddress": "Prinsengracht 1",
"zipcode": "1015 AB",
"city": "Amsterdam",
"country": "Netherlands",
"countryCode": "NL",
"currency": "EUR"
}
}
Salva il ristorante
POST /appointments/formitable-restaurants
| Campo | Obbligatorio | Descrizione |
|---|---|---|
restaurant_id |
Sì | 1–64 caratteri, lettere/numeri/underscore/trattino. |
restaurant_name |
Sì | Nome visualizzato. |
language |
Sì | Tag lingua ISO, ad es. "en" o "en-GB". |
website_url |
No | Il sito web del ristorante, dalla ricerca dei dettagli sopra. Deve essere http(s)://. |
curl -X POST "https://api.dmchamp.com/v1/appointments/formitable-restaurants?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"restaurant_id": "the-blue-door",
"restaurant_name": "The Blue Door Bistro",
"language": "en",
"website_url": "https://thebluedoorbistro.com"
}'
Risposta (201 Created): { "success": true, "data": { "restaurantId": "the-blue-door" } }
Aggiorna un ristorante Formitable salvato
PUT /appointments/formitable-restaurants/{restaurantId}
| Campo | Obbligatorio | Descrizione |
|---|---|---|
restaurant_name |
No | Nuovo nome visualizzato. |
language |
No | Nuovo tag lingua ISO. |
is_active |
No | Imposta false per impedire al bot di effettuare prenotazioni presso questo ristorante senza rimuoverlo. |
website_url |
No | Nuovo URL del sito web. |
curl -X PUT "https://api.dmchamp.com/v1/appointments/formitable-restaurants/the-blue-door" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "is_active": false }'
Risposta (200 OK): stessa struttura della risposta di salvataggio sopra.
Rimuovi un ristorante Formitable
DELETE /appointments/formitable-restaurants/{restaurantId}
curl -X DELETE "https://api.dmchamp.com/v1/appointments/formitable-restaurants/the-blue-door" \
-H "X-API-Key: YOUR_API_KEY"
Risposta (200 OK): { "success": true, "data": { "restaurantId": "the-blue-door" } }
Un restaurantId non attualmente presente nell’account restituisce 404 in caso di aggiornamento o eliminazione.
OpenTable
I ristoranti OpenTable vengono raggiunti tramite le credenziali partner OpenTable della piattaforma, e OpenTable consente a tali credenziali di vedere solo i ristoranti che hanno collegato l’elenco della piattaforma all’interno del Marketplace delle integrazioni di OpenTable. Quindi, come per Formitable, è sufficiente una chiamata di verifica: un ID Ristorante raggiungibile (il “RID” numerico) dimostra sia che il ristorante esiste, sia che ha collegato l’integrazione. Fino a quando l’elenco partner OpenTable non viene abilitato sulla piattaforma, la chiamata di verifica risponde 503.
Verifica un ristorante OpenTable
POST /appointments/opentable-restaurants/verify
| Campo | Obbligatorio | Descrizione |
|---|---|---|
restaurant_id |
Sì | L’ID Ristorante OpenTable (RID), un numero come 1038007. |
curl -X POST "https://api.dmchamp.com/v1/appointments/opentable-restaurants/verify?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "restaurant_id": "1038007" }'
Risposta (200 OK):
{
"success": true,
"data": {
"verified": true,
"restaurantDetails": {
"restaurantId": "1038007",
"diningAreaCount": 2,
"diningAreaNames": ["Main Room", "Garden"],
"tableTypes": ["default", "outdoor", "bar"]
}
}
}
verified: false significa che nessun ristorante OpenTable ha quell’ID. Un 403 significa che il ristorante esiste ma non ha ancora collegato l’integrazione della piattaforma all’interno di OpenTable. Limitato a 10 tentativi ogni 5 minuti per account.
Aggiungi un ristorante OpenTable
POST /appointments/opentable-restaurants
| Campo | Obbligatorio | Descrizione |
|---|---|---|
restaurant_id |
Sì | L’ID Ristorante verificato. |
restaurant_name |
Sì | Nome visualizzato (un’etichetta; anche come l’IA chiama il ristorante). |
website_url |
No | Un URL http(s) mostrato agli ospiti quando l’IA li trasferisce al ristorante. |
curl -X POST "https://api.dmchamp.com/v1/appointments/opentable-restaurants?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "restaurant_id": "1038007", "restaurant_name": "The Blue Door", "website_url": "https://thebluedoor.example" }'
Risposta (201 Created): { "success": true, "data": { "restaurantId": "1038007" } }
Aggiorna un ristorante OpenTable salvato
PUT /appointments/opentable-restaurants/{restaurantId}
Invia uno qualsiasi tra restaurant_name, is_active (metti in pausa con false) o website_url (una stringa vuota lo cancella); i campi omessi rimangono invariati.
curl -X PUT "https://api.dmchamp.com/v1/appointments/opentable-restaurants/1038007" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "is_active": false }'
Risposta (200 OK): { "success": true, "data": { "restaurantId": "1038007" } }
Rimuovere un ristorante OpenTable
DELETE /appointments/opentable-restaurants/{restaurantId}
curl -X DELETE "https://api.dmchamp.com/v1/appointments/opentable-restaurants/1038007" \
-H "X-API-Key: YOUR_API_KEY"
Risposta (200 OK): { "success": true, "data": { "restaurantId": "1038007" } }
Un restaurantId non attualmente presente nell’account restituisce 404 durante l’aggiornamento.
TheFork
I ristoranti TheFork vengono raggiunti tramite le credenziali partner TheFork della piattaforma, e TheFork consente a tali credenziali di vedere solo i ristoranti che hanno il partner della piattaforma abilitato sul proprio account TheFork. Quindi, come per Formitable e OpenTable, una chiamata di verifica è sufficiente: un ID Ristorante raggiungibile dimostra sia che il ristorante esiste sia che il partner è abilitato su di esso. L’ID è l’UUID che TheFork assegna al ristorante in TheFork Manager, inviato come stringa. Finché TheFork non avrà approvato la piattaforma come partner e rilasciato le credenziali, la chiamata di verifica risponderà 503 — vedi TheFork per cosa significa oggi.
Verifica un ristorante TheFork
POST /appointments/thefork-restaurants/verify
| Campo | Obbligatorio | Descrizione |
|---|---|---|
restaurant_id |
Sì | L’ID Ristorante TheFork, un UUID come 9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60. |
curl -X POST "https://api.dmchamp.com/v1/appointments/thefork-restaurants/verify?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "restaurant_id": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" }'
Risposta (200 OK):
{
"success": true,
"data": {
"verified": true,
"restaurantDetails": {
"restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60",
"partySizes": [1, 2, 3, 4, 5, 6, 7, 8]
}
}
}
partySizes sono le dimensioni del gruppo che il ristorante accetta online nei prossimi 30 giorni. Un 404 o 403 significa che TheFork non ci ha fornito un ristorante con quell’ID — o l’ID è errato, o il partner della piattaforma non è ancora abilitato su quel ristorante; un 400 significa che l’ID non è un UUID. Limitato a 10 tentativi ogni 5 minuti per account.
Aggiungi un ristorante TheFork
POST /appointments/thefork-restaurants
| Campo | Obbligatorio | Descrizione |
|---|---|---|
restaurant_id |
Sì | L’ID Ristorante verificato (UUID). |
restaurant_name |
Sì | Nome visualizzato (un’etichetta; è anche come l’AI chiama il ristorante). |
website_url |
No | Un URL http(s) mostrato agli ospiti quando l’AI li indirizza al ristorante. |
curl -X POST "https://api.dmchamp.com/v1/appointments/thefork-restaurants?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "restaurant_id": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60", "restaurant_name": "The Blue Door", "website_url": "https://thebluedoor.example" }'
Risposta (201 Created): { "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }
Aggiorna un ristorante TheFork salvato
PUT /appointments/thefork-restaurants/{restaurantId}
Invia uno qualsiasi tra restaurant_name, is_active (metti in pausa con false) o website_url (una stringa vuota lo cancella); i campi omessi rimangono invariati.
curl -X PUT "https://api.dmchamp.com/v1/appointments/thefork-restaurants/9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "is_active": false }'
Risposta (200 OK): { "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }
Rimuovi un ristorante TheFork
DELETE /appointments/thefork-restaurants/{restaurantId}
curl -X DELETE "https://api.dmchamp.com/v1/appointments/thefork-restaurants/9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" \
-H "X-API-Key: YOUR_API_KEY"
Risposta (200 OK): { "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }
Un restaurantId non attualmente presente nell’account restituisce 404 in caso di aggiornamento o eliminazione.
Trafft
Trafft viene collegato una volta per l’intero account, non per singola sede: un indirizzo aziendale più le credenziali API dal pannello di amministrazione di Trafft (Features & Integrations → API & Connectors, parte del piano Business di Trafft). La chiamata di connessione verifica tali credenziali su Trafft prima di memorizzare qualsiasi cosa, quindi un indirizzo errato, credenziali errate o un piano senza accesso API falliranno in questa fase anziché durante una conversazione con il cliente. Il client secret viene memorizzato crittografato e non viene mai restituito da alcun endpoint.
Tutte e tre le chiamate di scrittura (POST, PUT, DELETE) richiedono l’autorizzazione edit per le Integrazioni; lo stato GET richiede l’autorizzazione view per le Integrazioni.
Collega Trafft
POST /appointments/trafft/connect
| Campo | Obbligatorio | Descrizione |
|---|---|---|
subdomain |
Sì | L’indirizzo aziendale — la parte prima di .admin.trafft.com nell’URL a cui accedi, ad es. acme. Un indirizzo completo viene accettato e ridotto allo stesso valore. |
client_id |
Sì | Client ID dalla pagina API & Connectors di Trafft. |
client_secret |
Sì | Client Secret dalla stessa pagina. Memorizzato crittografato, mai restituito. |
company_name |
No | Un’etichetta per il tuo elenco personale. |
curl -X POST "https://api.dmchamp.com/v1/appointments/trafft/connect?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"subdomain": "acme",
"client_id": "YOUR_TRAFFT_CLIENT_ID",
"client_secret": "YOUR_TRAFFT_CLIENT_SECRET",
"company_name": "Acme Salon"
}'
Risposta (200 OK):
{
"success": true,
"data": {
"subdomain": "acme",
"service_count": 12,
"employee_count": 4,
"location_count": 2
}
}
I conteggi vengono restituiti da Trafft durante la verifica — sono il modo più rapido per confermare che le credenziali puntino all’account desiderato.
Ottieni lo stato della connessione
GET /appointments/trafft
curl "https://api.dmchamp.com/v1/appointments/trafft" \
-H "X-API-Key: YOUR_API_KEY"
Risposta (200 OK):
{
"success": true,
"data": {
"connected": true,
"subdomain": "acme",
"hostname": "acme.admin.trafft.com",
"client_id": "YOUR_TRAFFT_CLIENT_ID",
"company_name": "Acme Salon",
"is_active": true,
"service_count": 12,
"employee_count": 4,
"location_count": 2
}
}
connected: false significa che non è ancora stato configurato nulla. Il client secret non è mai incluso in questa risposta.
Aggiorna la connessione
PUT /appointments/trafft
| Campo | Obbligatorio | Descrizione |
|---|---|---|
is_active |
No | Imposta false su pausa: l’IA smette di prenotare su Trafft, la connessione rimane attiva. true la riprende. |
company_name |
No | Nuova etichetta. |
curl -X PUT "https://api.dmchamp.com/v1/appointments/trafft" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "is_active": false }'
Risposta (200 OK): lo stesso oggetto di connessione del GET qui sopra.
Disconnetti Trafft
DELETE /appointments/trafft
curl -X DELETE "https://api.dmchamp.com/v1/appointments/trafft" \
-H "X-API-Key: YOUR_API_KEY"
Risposta (200 OK): { "success": true }
La disconnessione rimuove solo le credenziali memorizzate. Gli appuntamenti già presenti in Trafft rimangono invariati.
Formato dell’errore su tutti gli endpoint Zenchef/Formitable/OpenTable/TheFork: a differenza del resto di questa pagina, gli errori qui riportano il loro stato due volte — una come stato HTTP e una come
error_codenel corpo — ad esempio{ "success": false, "error": "Restaurant not found", "error_code": 404 }. Gestiscilo allo stesso modo di qualsiasi altro errore: controllasuccess, leggierrorper il messaggio.
Errori dell’API Appuntamenti
Gli endpoint degli appuntamenti restituiscono il formato di errore standard:
{
"success": false,
"error": "Appointment not found"
}
| Stato | Quando si verifica su un endpoint di appuntamento |
|---|---|
400 |
Un campo obbligatorio manca o non è valido — ad esempio un start_time errato, un end_time non successivo a start_time, una combinazione di filtri non valida, nessun campo da aggiornare o un appuntamento già annullato. |
404 |
L’appuntamento, il contatto o il tipo di evento non è stato trovato. |
409 |
La fascia oraria richiesta è già occupata (conflitto di prenotazione). |
I codici condivisi che ogni endpoint può restituire — 401, 403 (il tuo piano non include l’accesso all’API), 429 (limite di frequenza) e 500 — sono elencati con indicazioni sui tentativi in Errori e Paginazione.
Utilizza il tuo client Google OAuth (schermata di consenso del Calendario)
Quando un account si connette a Google Calendar, la finestra di accesso di Google nomina il progetto del client OAuth — per impostazione predefinita quello della piattaforma. Un’agenzia può registrare il proprio client Google OAuth 2.0 sull’account dell’agenzia; da quel momento in poi, la connessione al calendario per quell’account e per ogni sotto-account ad esso collegato passerà attraverso quel client, in modo che la schermata di consenso mostri il nome e il logo dell’agenzia. Nient’altro cambia: il flusso di connessione, la sincronizzazione bidirezionale e gli endpoint degli appuntamenti sopra indicati funzionano esattamente come prima.
Solo Google Calendar. L’OAuth della casella di posta Gmail per il canale Email non è interessato.
Cosa serve al tuo client per iniziare
- Un client OAuth 2.0 di tipo Applicazione web nel tuo progetto Google Cloud, con l’API Google Calendar abilitata su quel progetto.
- Ogni voce
redirect_uris(restituita dagli endpoint sottostanti) aggiunta sotto gli URI di reindirizzamento autorizzati del client. La prima voce è il tuo dominioapi.verificato quando ne hai uno — Google verifica solo un brand il cui reindirizzamento risiede su un dominio di tua proprietà — seguito dall’host neutrale della piattaforma come fallback utilizzato fino a quel momento. - La schermata di consenso con il tuo brand, il tuo dominio sotto Domini autorizzati e i due ambiti (scope) del Calendario dichiarati (
scopesnella risposta). Fino a quando l’app non viene pubblicata e verificata da Google, gli utenti vedono un avviso di app non verificata e il client è limitato a 100 utenti.
Salva il tuo client
PUT /account-config/google-oauth-client
| Campo | Obbligatorio | Descrizione |
|---|---|---|
client_id |
Sì | L’ID client OAuth 2.0, che termina con .apps.googleusercontent.com. |
client_secret |
Sì | Il segreto del client. Verificato tramite Google prima di essere archiviato, quindi crittografato. Non viene mai restituito da alcun endpoint. |
curl -X PUT "https://api.dmchamp.com/v1/account-config/google-oauth-client?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"client_id": "123456789012-abcdefghijklmnop.apps.googleusercontent.com",
"client_secret": "GOCSPX-your-client-secret"
}'
Risposta
{
"success": true,
"configured": true,
"client_id": "123456789012-abcdefghijklmnop.apps.googleusercontent.com",
"redirect_uris": [
"https://api.youragency.com/v1/auth-google-callback",
"https://api.dmchamp.com/v1/auth-google-callback"
],
"scopes": [
"https://www.googleapis.com/auth/calendar.events",
"https://www.googleapis.com/auth/calendar.readonly"
],
"setup": ["…"]
}
Un segreto errato o un ID client sconosciuto vengono rifiutati con 400 e il motivo specifico di Google in error, e nulla viene archiviato.
Leggi o rimuovi
GET /account-config/google-oauth-client restituisce lo stesso riepilogo in qualsiasi momento — configured: false più redirect_uris e scopes prima che venga salvato qualsiasi elemento, così puoi configurare prima il lato Google. DELETE /account-config/google-oauth-client rimuove il client: le nuove connessioni tornano al client della piattaforma e i calendari che erano stati collegati tramite il client rimosso devono essere ricollegati, poiché solo il client che ha emesso una connessione può aggiornarla.
I membri del team necessitano di Integrazioni: visualizza per GET e Integrazioni: modifica per PUT / DELETE.
Passaggi successivi
- Contatti — crea e cerca i contatti per cui effettui le prenotazioni.
- Messaggi e conversazioni — invia a un contatto una conferma o un promemoria.
- Webhook — ricevi notifiche quando gli appuntamenti cambiano.