DM Champ Docs

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_id potrebbe essere ancora null e calendar_synced potrebbe essere false perché 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 Il tipo di evento da controllare. Deve appartenere al tuo account.
start_time Inizio della finestra per cui desideri gli slot, data-ora ISO 8601.
end_time 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_time e end_time sono 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 ID del contatto per cui prenotare. Deve appartenere al tuo account.
event_id ID della tipologia di evento su cui prenotare. Deve appartenere al tuo account.
start_time 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_id per vedere gli appuntamenti confermati di un contatto. Puoi restringere il campo a un singolo giorno passando anche date.
  • Per stato — imposta status (senza contact_id) per elencare solo gli appuntamenti Confirmed o solo Canceled nell’account.
  • Il filtro date senza contact_id, o status=Canceled insieme a contact_id, restituisce un 400.

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 "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 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 L’ID del ristorante Zenchef dal passaggio 1.
user_input_name 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 1–64 caratteri, lettere/numeri/underscore/trattino.
restaurant_name 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 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 1–64 caratteri, lettere/numeri/underscore/trattino.
restaurant_name Nome visualizzato.
language 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 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 L’ID Ristorante verificato.
restaurant_name 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 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 L’ID Ristorante verificato (UUID).
restaurant_name 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 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 Client ID dalla pagina API & Connectors di Trafft.
client_secret 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_code nel corpo — ad esempio { "success": false, "error": "Restaurant not found", "error_code": 404 }. Gestiscilo allo stesso modo di qualsiasi altro errore: controlla success, leggi error per 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

  1. Un client OAuth 2.0 di tipo Applicazione web nel tuo progetto Google Cloud, con l’API Google Calendar abilitata su quel progetto.
  2. Ogni voce redirect_uris (restituita dagli endpoint sottostanti) aggiunta sotto gli URI di reindirizzamento autorizzati del client. La prima voce è il tuo dominio api. 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.
  3. La schermata di consenso con il tuo brand, il tuo dominio sotto Domini autorizzati e i due ambiti (scope) del Calendario dichiarati (scopes nella 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 L’ID client OAuth 2.0, che termina con .apps.googleusercontent.com.
client_secret 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.