Möten
Appointments API låter dig boka möten för dina kontakter baserat på dina evenemangstyper, samt hämta, lista, uppdatera, avboka eller ta bort dem. Det besvarar även frågan som kommer först i de flesta bokningsflöden — vilka tider som faktiskt är lediga — och täcker kalendersidan: listar de Google-kalendrar du har anslutit och importerar händelser som redan finns i dem. När en Google Kalender-anslutning är aktiv skapas motsvarande kalenderhändelse och hålls automatiskt synkroniserad i bakgrunden. Restauranger som använder Zenchef, Formitable, OpenTable eller TheFork för sina egna bokningssystem kan också verifieras och anslutas här, så att AI-agenten bokar riktiga bord istället för interna möten — och företag som hanterar sina scheman i Trafft kan ansluta på samma sätt.
Alla sökvägar på denna sida är relativa till bas-URL:en https://api.dmchamp.com/v1. Varje anrop kräver din API-nyckel — se Autentisering för en fullständig lista över hur den kan skickas. Exemplen nedan använder headern X-API-Key, där ett cURL-exempel även visar frågeformuläret ?apiKey=.
Händelser vs. möten: En händelsetyp är en definition av en bokningsbar tid (typ av möte, längd, rum). Ett möte är en bokad instans av en händelsetyp för en specifik kontakt. Du bokar ett möte genom att referera till kontakten och händelsetypen.
Mötesobjektet
Varje slutpunkt som returnerar ett möte använder samma struktur:
| Fält | Beskrivning |
|---|---|
id |
Unikt ID för mötet. |
contact_id |
ID för kontakten som mötet är bokat med. |
event_id |
ID för händelsetypen som mötet bokades på. |
status |
Confirmed eller Canceled. |
start_time |
Mötets starttid, ISO 8601 i UTC. |
end_time |
Mötets sluttid, ISO 8601 i UTC. |
created_at |
När mötet skapades. |
last_modified_at |
När mötet senast ändrades. |
room_name |
Rum eller resurs som mötet är bokat i, när händelsetypen använder rum. |
description |
Fritextbeskrivning av mötet. |
summary |
Kort sammanfattning eller titel. |
cancelation_reason |
Orsak som angavs när mötet avbokades, om någon. |
google_calendar_event_id |
ID för den länkade Google Kalender-händelsen. Sätts när kalendersynkroniseringen är klar; null när ingen kalender är ansluten eller medan synkroniseringen pågår. |
calendar_synced |
true när mötet är länkat till en kalenderhändelse. |
imported |
true när mötet har importerats från en extern kalender istället för att bokas direkt. |
is_recurring |
true när mötet är en del av en återkommande serie. |
recurrence_frequency |
Hur ofta mötet upprepas, vid återkommande möten. |
recurring_event_id |
ID för den återkommande serie som detta möte tillhör. |
recurring_interval |
Intervall mellan upprepningar, vid återkommande möten. |
recurring_sequence |
Position för detta möte inom dess återkommande serie. |
end_after_x_occurrences |
Antal förekomster efter vilka den återkommande serien avslutas. |
booking_provider |
Källsystem som bokningen kom ifrån, när den bokats via en ansluten bokningsleverantör. |
Om kalendersynkronisering: Direkt efter att du bokat eller ändrat ett möte kan
google_calendar_event_idfortfarande varanullochcalendar_syncedkan varafalseeftersom synkroniseringen körs i bakgrunden en stund senare. Hämta mötet igen en kort stund senare för att se de ifyllda kalenderfälten.
Hitta tillgängliga tider
GET /appointments/available-slots
Returnerar de tider som faktiskt är lediga för en händelsetyp mellan två tidpunkter. Detta är normalt det första anropet i ett bokningsflöde: visa dessa tider, låt personen välja en, och skicka sedan den valda tiden till Boka ett möte.
Svaret tar redan hänsyn till händelsetypens egna öppettider och tidslängd, dess rum, möten du redan har bokat på den, samt allt som är blockerat i de anslutna Google-kalendrarna — så en tid som returneras här är en tid du kan boka.
| Frågeparameter | Krävs | Beskrivning |
|---|---|---|
event_id |
Ja | Händelsetypen att kontrollera. Måste tillhöra ditt konto. |
start_time |
Ja | Starten på tidsfönstret du vill ha tider för, ISO 8601 datum-tid. |
end_time |
Ja | Slutet på tidsfönstret, ISO 8601 datum-tid. Hela slutdagen inkluderas. |
Resultaten returneras grupperade per dag — och när händelsetypen använder rum, en grupp per rum per dag:
| Fält | Beskrivning |
|---|---|
date |
Dagen som gruppen täcker, skrivet DD/MM/YYYY. |
day |
Veckodagsnamn med gemener, till exempel monday. |
room_name |
Rummet eller resursen som denna grupp tillhör, när händelsetypen använder rum. |
available_slots |
De bokningsbara blocken den dagen, tidigast först. |
Varje post i available_slots har:
| Fält | Beskrivning |
|---|---|
start_time |
Blockstart som HH:mm. |
end_time |
Blockslut som HH:mm. |
available |
true — endast ledig tid returneras. |
spots_left |
Hur många bokningar som fortfarande får plats i detta block. Visas endast för händelsetyper som tillåter mer än en bokning per tid. |
Tiderna är lokala för händelsetypen, inte UTC.
date,start_timeochend_timeär klockslag i händelsetypens egen tidszon (dess åsidosättning, eller ditt kontos tidszon om ingen sådan finns). Boka ett möte förväntar sig ett ISO 8601 UTC-ögonblick, så konvertera tiden du valde innan du skickar den.
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"])
Svar (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 }
]
}
]
}
En dag utan lediga tider visas helt enkelt inte. Om event_id, start_time eller end_time saknas returneras 400; en händelsetyp som inte finns på ditt konto returnerar 404.
Boka ett möte
POST /appointments
Bokar ett nytt möte för en kontakt på en av dina händelsetyper. Sluttiden beräknas automatiskt baserat på händelsetypens tidslängd.
Bokningen kontrolleras mot konflikter: om den begärda tiden överlappar ett befintligt bekräftat möte på samma händelsetyp misslyckas anropet med ett 409 och ingenting skapas.
| Fält | Krävs | Beskrivning |
|---|---|---|
contact_id |
Ja | ID för kontakten som ska bokas. Måste tillhöra ditt konto. |
event_id |
Ja | ID för händelsetypen som ska bokas. Måste tillhöra ditt konto. |
start_time |
Ja | Önskad starttid som ett ISO 8601-datum/tid. |
room_name |
Nej | Namn på rum eller resurs, när händelsetypen använder rum. |
cURL (använder frågeformuläret ?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"])
Svar (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
}
}
Hämta ett möte
GET /appointments/{appointmentId}
Returnerar ett enskilt möte via dess ID, inklusive dess synkroniseringsstatus för kalendern.
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"])
Svar (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
}
}
Lista möten
GET /appointments
Listar möten för ditt konto, med det nyaste först, med markörbaserad paginering.
| Frågeparameter | Krävs | Beskrivning |
|---|---|---|
contact_id |
Nej | Returnera endast möten för denna kontakt. Kontaktfiltrerade listor inkluderar endast bekräftade möten. |
date |
Nej | Returnera endast möten för denna kalenderdag (YYYY-MM-DD). Kräver contact_id. |
status |
Nej | Filtrera efter Confirmed eller Canceled. Endast tillgängligt utan contact_id. |
limit |
Nej | Sidstorlek, ett heltal mellan 1 och 100. Standardvärde 50. |
cursor |
Nej | Värdet next_cursor från ett tidigare svar. |
Några regler att komma ihåg:
- Utan filter får du varje möte på kontot, sida för sida.
- Per kontakt — ställ in
contact_idför att se en kontakts bekräftade möten. Du kan begränsa detta till en enskild dag genom att även skicka meddate. - Per status — ställ in
status(utancontact_id) för att endast listaConfirmedeller endastCanceledmöten för hela kontot. - Filtret
dateutancontact_id, ellerstatus=Canceledtillsammans medcontact_id, returnerar ett400.
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"])
Svar (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
}
För att bläddra igenom resultaten, skicka med next_cursor från ett svar som cursor i nästa begäran. Fortsätt tills next_cursor är null. Se Fel & Paginering för det gemensamma pagineringsmönstret.
Uppdatera ett möte
PUT /appointments/{appointmentId}
Boka om ett möte eller ändra dess detaljer. Skicka endast de fält du vill ändra — minst ett krävs. Den kombinerade start- och sluttiden måste vara i kronologisk ordning (end_time måste vara efter start_time). Ändringar synkroniseras automatiskt till den länkade kalenderhändelsen.
| Fält | Beskrivning |
|---|---|
start_time |
Ny starttid, ISO 8601 datum-tid. |
end_time |
Ny sluttid, ISO 8601 datum-tid. Måste vara efter starttiden. |
room_name |
Nytt namn på rum eller resurs. |
description |
Ny beskrivning, eller null för att rensa den. |
summary |
Ny sammanfattning, eller null för att rensa den. |
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"])
Svar (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
}
}
Avboka en tid
POST /appointments/{appointmentId}/cancel
Avbokar en bekräftad tid, med möjlighet att ange en orsak. Tiden finns kvar på ditt konto med status Canceled, och den länkade kalenderhändelsen tas bort automatiskt i bakgrunden. Att avboka en redan avbokad tid returnerar en 400.
| Fält | Krävs | Beskrivning |
|---|---|---|
cancellation_reason |
Nej | Orsak till avbokningen, sparas på bokningen. |
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"])
Svar (200 OK):
{
"success": true,
"appointment_id": "aBcD1234eFgH5678"
}
Ta bort en bokning
DELETE /appointments/{appointmentId}
Tar permanent bort en bokning och dess referenser. Om du bara vill avboka tiden men behålla posten, använd avboka istället.
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"])
Svar (200 OK):
{
"success": true
}
Lista dina anslutna Google-kalendrar
GET /appointments/google-calendars
Returnerar de Google-kalendrar som är tillgängliga på detta konto, direkt från Google — användbart för att visa kontoinnehavaren en väljare för vilken kalender som ska importeras från nedan, eller bara för att bekräfta att anslutningen är aktiv.
Detta fungerar endast när kontot har anslutit Google Kalender (Inställningar → Integrationer) med minst läsbehörighet. Om det inte har gjorts, eller om den beviljade åtkomsten inte längre inkluderar läsbehörighet för kalendern, får du ett 400 som ber dig att (åter)ansluta den.
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"])
Svar (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"
}
]
}
Varje post har Googles egen CalendarListEntry-form, så fältnamnen följer Googles camelCase, inte detta API:s vanliga snake_case — det är Googles data som skickas vidare som den är, inte vår. En saknad eller återkallad anslutning returnerar 400 med ett felmeddelande som förklarar att Google Kalender behöver (åter)anslutas.
Importera händelser från en Google-kalender
POST /appointments/import-calendar-events
Hämtar händelser som redan finns i en kampanjs eller AI-agents anslutna Google-kalender(ar) och gör om dem till möten — användbart första gången du ansluter en kalender som redan har bokningar. Detta kan ta en stund (varje händelse går igenom extrahering för att ta reda på vem den är till för), så det körs aldrig direkt: begäran köar ett bakgrundsjobb och ger dig tillbaka ett job_id att polla.
| Fält | Krävs | Beskrivning |
|---|---|---|
campaign_id |
En av dessa två | Kampanjen vars anslutna kalender(ar) ska importeras från. |
agent_id |
En av dessa två | AI-agenten vars anslutna kalender(ar) ska importeras från. |
identifier |
Ja | "EMAIL" eller "PHONE_NUMBER" — vilken kontaktinformation som ska extraheras från varje kalenderhändelse för att matcha eller skapa kontakten den tillhör. |
Skicka exakt en av campaign_id / agent_id, aldrig båda och aldrig ingen — båda kombinationerna returnerar ett 400. Den du skickar måste tillhöra ditt konto, annars får du ett 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"])
Svar (202 Accepted):
{
"success": true,
"job_id": "jK9mQ2xR7pL4wN1t",
"status": "queued",
"campaign_id": null,
"agent_id": "agent_abc123"
}
campaign_id och agent_id ekar tillbaka den du skickade; den andra är alltid null.
Polla importjobbet
GET /appointments/import-calendar-events/{jobId}
curl "https://api.dmchamp.com/v1/appointments/import-calendar-events/jK9mQ2xR7pL4wN1t" \
-H "X-API-Key: YOUR_API_KEY"
Svar (200 OK):
{
"success": true,
"job_id": "jK9mQ2xR7pL4wN1t",
"status": "completed",
"message": "Imported 12 events as appointments.",
"error": null
}
status |
Betydelse |
|---|---|
queued |
Inte hämtad än. Fortsätt polla. |
processing |
Importen körs. Fortsätt polla. |
completed |
Klar — message innehåller en kort sammanfattning som är lätt att läsa. |
failed |
Något gick fel — error innehåller orsaken. |
GET på ett jobId som inte finns (eller tillhör ett annat konto) returnerar 404.
Externa bokningsintegrationer (Zenchef / Formitable / OpenTable / TheFork / Trafft)
Zenchef och Formitable är restaurangbokningssystem som din AI-agent kan boka riktiga bord genom; Trafft är en schemaläggningsplattform för företag som arbetar med tidsbokning, vilken ansluts en gång per konto snarare än per restaurang. De två restaurangplattformarna har vardera en publik, oautentiserad bokningswidget (https://api.dmchamp.com/v1/zenchef-widget/... och https://api.dmchamp.com/v1/formitable-widget/...) som renderas i chatten för gästen — dessa widget-vägar är vanliga HTML-sidor avsedda att öppnas i en webbläsare, inte JSON API-slutpunkter, så de dokumenteras inte här. Vad som följer är slutpunkterna för kontohantering: att verifiera att ett restaurang-ID tillhör kontoinnehavaren, samt att lägga till, uppdatera eller ta bort det.
Zenchef
Att ansluta en Zenchef-restaurang är en tvåstegsverifiering, så kontoinnehavaren bevisar att de faktiskt driver restaurangen innan den kopplas till boten: kontrollera först att ID:t finns (utan att avslöja namnet), låt dem sedan skriva in restaurangens namn själva och verifiera att det matchar.
Steg 1 — Kontrollera att ett restaurang-ID finns
POST /appointments/zenchef-restaurants/check
| Fält | Krävs | Beskrivning |
|---|---|---|
restaurant_id |
Ja | Zenchef-restaurangens ID som ska kontrolleras. |
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" }'
Svar (200 OK):
{
"success": true,
"data": { "exists": true, "requiresNameVerification": true }
}
exists: false betyder att ingen Zenchef-restaurang har det ID:t — inget mer att göra. Hastighetsbegränsat till 10 kontroller per 5 minuter per konto; att överskrida detta returnerar 429.
Steg 2 — Verifiera restaurangens namn
POST /appointments/zenchef-restaurants/verify-name
| Fält | Krävs | Beskrivning |
|---|---|---|
restaurant_id |
Ja | Zenchef-restaurangens ID från steg 1. |
user_input_name |
Ja | Namnet som kontoinnehavaren skrev in — jämförs med restaurangens riktiga namn på Zenchef (skiftläges- och blankstegsokänsligt). |
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" }'
Svar (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 betyder att namnet inte matchade — restaurantDetails utelämnas, be kontoinnehavaren att försöka igen. Hastighetsbegränsat till 3 försök per 5 minuter (strängare än existenskontrollen, eftersom detta är det faktiska bevissteget). Ett restaurant_id som inte längre kan matchas på Zenchef returnerar 404.
Steg 3 — Spara restaurangen
POST /appointments/zenchef-restaurants
| Fält | Krävs | Beskrivning |
|---|---|---|
restaurant_id |
Ja | 1–64 tecken, bokstäver/siffror/understreck/bindestreck. |
restaurant_name |
Ja | Det verifierade restaurangnamnet från steg 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" }'
Svar (201 Created):
{ "success": true, "data": { "restaurantId": "12345" } }
Uppdatera en sparad Zenchef-restaurang
PUT /appointments/zenchef-restaurants/{restaurantId}
| Fält | Krävs | Beskrivning |
|---|---|---|
restaurant_name |
Nej | Nytt visningsnamn. |
is_active |
Nej | Ange false för att hindra boten från att boka mot denna restaurang utan att ta bort den. |
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 }'
Svar (200 OK): samma format som spar-svaret ovan.
Ta bort en Zenchef-restaurang
DELETE /appointments/zenchef-restaurants/{restaurantId}
curl -X DELETE "https://api.dmchamp.com/v1/appointments/zenchef-restaurants/12345" \
-H "X-API-Key: YOUR_API_KEY"
Svar (200 OK): { "success": true, "data": { "restaurantId": "12345" } }
En restaurantId som för närvarande inte finns på kontot returnerar 404 vid uppdatering eller borttagning.
Formitable
Formitable behöver inte den tvåstegsnamnverifiering som Zenchef kräver — dess restaurang-ID:n är redan begränsade per företag, så ett verifieringsanrop räcker. Den har också en detaljsökning som används för att cachelagra restaurangens webbplats-URL under konfigurationen.
Verifiera ett restaurang-ID
POST /appointments/formitable-restaurants/verify
| Fält | Krävs | Beskrivning |
|---|---|---|
restaurant_id |
Ja | Formitable-restaurangens ID. |
language |
Nej | Språktagg för sondförfrågan. Standardvärde är "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" }'
Svar (200 OK):
{
"success": true,
"data": {
"verified": true,
"restaurantDetails": {
"restaurantId": "the-blue-door",
"productCount": 4,
"sampleProductTitle": "Dinner for two",
"language": "en"
}
}
}
Ett restaurant_id som Formitable inte känner igen returnerar 404. Hastighetsbegränsat till 10 försök per 5 minuter per konto.
Hämta restaurangdetaljer
GET /appointments/formitable-restaurants/{restaurantId}/details?language=en
Hämtar restaurangens offentliga profil från Formitable, inklusive dess webbplats — används för att cachelagra webbplatsens URL när restaurangen konfigureras. language är en valfri frågeparameter som som standard är "en".
curl "https://api.dmchamp.com/v1/appointments/formitable-restaurants/the-blue-door/details?language=en" \
-H "X-API-Key: YOUR_API_KEY"
Svar (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"
}
}
Spara restaurangen
POST /appointments/formitable-restaurants
| Fält | Krävs | Beskrivning |
|---|---|---|
restaurant_id |
Ja | 1–64 tecken, bokstäver/siffror/understreck/bindestreck. |
restaurant_name |
Ja | Visningsnamn. |
language |
Ja | ISO-språktagg, t.ex. "en" eller "en-GB". |
website_url |
Nej | Restaurangens webbplats, från detaljsökningen ovan. Måste vara 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"
}'
Svar (201 Created): { "success": true, "data": { "restaurantId": "the-blue-door" } }
Uppdatera en sparad Formitable-restaurang
PUT /appointments/formitable-restaurants/{restaurantId}
| Fält | Krävs | Beskrivning |
|---|---|---|
restaurant_name |
Nej | Nytt visningsnamn. |
language |
Nej | Ny ISO-språktagg. |
is_active |
Nej | Sätt false för att hindra boten från att boka mot denna restaurang utan att ta bort den. |
website_url |
Nej | Ny webbadress. |
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 }'
Svar (200 OK): samma format som spar-svaret ovan.
Ta bort en Formitable-restaurang
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"
Svar (200 OK): { "success": true, "data": { "restaurantId": "the-blue-door" } }
En restaurantId som för närvarande inte finns på kontot returnerar 404 vid uppdatering eller borttagning.
OpenTable
OpenTable-restauranger nås via plattformens OpenTable-partneruppgifter, och OpenTable låter endast dessa uppgifter se restauranger som har anslutit plattformens listning via OpenTables Integrations Marketplace. Så, precis som med Formitable, räcker ett verifieringsanrop: ett nåbart restaurang-ID (det numeriska “RID”) bevisar både att restaurangen existerar och att den har anslutit integrationen. Tills OpenTable-partnerlistningen är aktiverad på plattformen svarar verifieringsanropet 503.
Verifiera en OpenTable-restaurang
POST /appointments/opentable-restaurants/verify
| Fält | Krävs | Beskrivning |
|---|---|---|
restaurant_id |
Ja | OpenTable Restaurant ID (RID), ett nummer som t.ex. 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" }'
Svar (200 OK):
{
"success": true,
"data": {
"verified": true,
"restaurantDetails": {
"restaurantId": "1038007",
"diningAreaCount": 2,
"diningAreaNames": ["Main Room", "Garden"],
"tableTypes": ["default", "outdoor", "bar"]
}
}
}
verified: false betyder att ingen OpenTable-restaurang har det ID:t. Ett 403 betyder att restaurangen existerar men ännu inte har anslutit plattformens integration inuti OpenTable. Hastighetsbegränsat till 10 försök per 5 minuter per konto.
Lägg till en OpenTable-restaurang
POST /appointments/opentable-restaurants
| Fält | Krävs | Beskrivning |
|---|---|---|
restaurant_id |
Ja | Det verifierade restaurang-ID:t. |
restaurant_name |
Ja | Visningsnamn (en etikett; även vad AI:n kallar restaurangen). |
website_url |
Nej | En http(s)-URL som visas för gäster när AI:n skickar vidare dem till restaurangen. |
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" }'
Svar (201 Created): { "success": true, "data": { "restaurantId": "1038007" } }
Uppdatera en sparad OpenTable-restaurang
PUT /appointments/opentable-restaurants/{restaurantId}
Skicka något av restaurant_name, is_active (pausa med false) eller website_url (tom sträng rensar det); utelämnade fält lämnas oförändrade.
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 }'
Svar (200 OK): { "success": true, "data": { "restaurantId": "1038007" } }
Ta bort en OpenTable-restaurang
DELETE /appointments/opentable-restaurants/{restaurantId}
curl -X DELETE "https://api.dmchamp.com/v1/appointments/opentable-restaurants/1038007" \
-H "X-API-Key: YOUR_API_KEY"
Svar (200 OK): { "success": true, "data": { "restaurantId": "1038007" } }
En restaurantId som för närvarande inte finns på kontot returnerar 404 vid uppdatering.
TheFork
TheFork-restauranger nås via plattformens TheFork-partneruppgifter, och TheFork låter endast dessa uppgifter se restauranger som har plattformens partner aktiverad på sitt TheFork-konto. Så, precis som med Formitable och OpenTable, räcker ett verifieringsanrop: ett nåbart restaurang-ID bevisar både att restaurangen existerar och att partnern är aktiverad för den. ID:t är det UUID som TheFork ger restaurangen i TheFork Manager, skickat som en sträng. Tills TheFork har godkänt plattformen som partner och utfärdat uppgifterna, svarar verifieringsanropet 503 — se TheFork för vad det innebär idag.
Verifiera en TheFork-restaurang
POST /appointments/thefork-restaurants/verify
| Fält | Krävs | Beskrivning |
|---|---|---|
restaurant_id |
Ja | TheFork-restaurangens ID, ett UUID såsom 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" }'
Svar (200 OK):
{
"success": true,
"data": {
"verified": true,
"restaurantDetails": {
"restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60",
"partySizes": [1, 2, 3, 4, 5, 6, 7, 8]
}
}
}
partySizes är de sällskapsstorlekar som restaurangen tar emot online under de kommande 30 dagarna. Ett 404 eller 403 innebär att TheFork inte gav oss en restaurang med det ID:t — antingen är ID:t felaktigt, eller så är plattformens partner ännu inte aktiverad på den restaurangen; ett 400 innebär att ID:t inte är ett UUID. Hastighetsbegränsat till 10 försök per 5 minuter per konto.
Lägg till en TheFork-restaurang
POST /appointments/thefork-restaurants
| Fält | Krävs | Beskrivning |
|---|---|---|
restaurant_id |
Ja | Det verifierade restaurang-ID:t (UUID). |
restaurant_name |
Ja | Visningsnamn (en etikett; även det namn AI:n använder för restaurangen). |
website_url |
Nej | En http(s)-URL som visas för gäster när AI:n hänvisar dem till restaurangen. |
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" }'
Svar (201 Created): { "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }
Uppdatera en sparad TheFork-restaurang
PUT /appointments/thefork-restaurants/{restaurantId}
Skicka något av restaurant_name, is_active (pausa med false) eller website_url (tom sträng rensar det); utelämnade fält lämnas oförändrade.
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 }'
Svar (200 OK): { "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }
Ta bort en TheFork-restaurang
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"
Svar (200 OK): { "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }
En restaurantId som för närvarande inte finns på kontot returnerar 404 vid uppdatering eller borttagning.
Trafft
Trafft ansluts en gång för hela kontot, inte per plats: en företagsadress plus API-uppgifter från Traffts administratörspanel (Features & Integrations → API & Connectors, en del av Traffts Business-plan). Anslutningsanropet kontrollerar dessa uppgifter mot Trafft innan något lagras, så en felaktig adress, felaktiga uppgifter eller en plan utan API-åtkomst misslyckas här istället för under en kundkonversation. Klienthemligheten (client secret) lagras krypterad och returneras aldrig av någon slutpunkt.
Alla tre skrivanrop (POST, PUT, DELETE) kräver behörigheten edit för integrationer; statusen GET kräver view för integrationer.
Anslut Trafft
POST /appointments/trafft/connect
| Fält | Krävs | Beskrivning |
|---|---|---|
subdomain |
Ja | Företagsadressen — delen före .admin.trafft.com i URL:en du loggar in på, t.ex. acme. En fullständig adress accepteras och reduceras till samma värde. |
client_id |
Ja | Klient-ID från Traffts sida för API & Connectors. |
client_secret |
Ja | Klienthemlighet (Client Secret) från samma sida. Lagras krypterad, returneras aldrig. |
company_name |
Nej | En etikett för din egen lista. |
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"
}'
Svar (200 OK):
{
"success": true,
"data": {
"subdomain": "acme",
"service_count": 12,
"employee_count": 4,
"location_count": 2
}
}
Antalen kommer tillbaka från Trafft under kontrollen — de är det snabbaste sättet att bekräfta att uppgifterna pekar på det konto du avsåg.
Hämta anslutningsstatus
GET /appointments/trafft
curl "https://api.dmchamp.com/v1/appointments/trafft" \
-H "X-API-Key: YOUR_API_KEY"
Svar (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 betyder att ingenting har ställts in ännu. Klienthemligheten inkluderas aldrig i detta svar.
Uppdatera anslutningen
PUT /appointments/trafft
| Fält | Krävs | Beskrivning |
|---|---|---|
is_active |
Nej | Ställ in false för att pausa — AI:n slutar boka i Trafft, men anslutningen kvarstår. true återupptar den. |
company_name |
Nej | Ny etikett. |
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 }'
Svar (200 OK): samma anslutningsobjekt som GET ovan.
Koppla från Trafft
DELETE /appointments/trafft
curl -X DELETE "https://api.dmchamp.com/v1/appointments/trafft" \
-H "X-API-Key: YOUR_API_KEY"
Svar (200 OK): { "success": true }
Frånkoppling tar endast bort de lagrade inloggningsuppgifterna. Bokningar som redan finns i Trafft förblir orörda.
Felstruktur för alla Zenchef/Formitable/OpenTable/TheFork-slutpunkter: till skillnad från resten av den här sidan visas fel här med sin status två gånger — en gång som HTTP-status och en gång som
error_codei brödtexten — till exempel{ "success": false, "error": "Restaurant not found", "error_code": 404 }. Hantera det på samma sätt som alla andra fel: kontrollerasuccess, läserrorför meddelandet.
Fel i Appointments API
Slutpunkter för möten returnerar standardfelmeddelandet:
{
"success": false,
"error": "Appointment not found"
}
| Status | När det inträffar på en slutpunkt för möten |
|---|---|
400 |
Ett obligatoriskt fält saknas eller är ogiltigt — till exempel ett felaktigt start_time, ett end_time som inte är efter start_time, en ogiltig filterkombination, inga fält att uppdatera eller ett redan avbokat möte. |
404 |
Mötet, kontakten eller händelsetypen hittades inte. |
409 |
Den begärda tidsluckan är redan upptagen (bokningskonflikt). |
De delade koderna som alla slutpunkter kan returnera — 401, 403 (din plan inkluderar inte API-åtkomst), 429 (hastighetsbegränsning) och 500 — listas med vägledning för återförsök i Fel & Paginering.
Använd din egen Google OAuth-klient (skärm för kalendergodkännande)
När ett konto ansluter Google Kalender namnger Googles inloggningsfönster OAuth-klientens projekt — som standard plattformens. En byrå kan registrera sin egen Google OAuth 2.0-klient på byråkontot; från och med då körs kalenderanslutningen för det kontot och varje underkonto under det genom den klienten, så att godkännandeskärmen visar byråns namn och logotyp. Inget annat ändras: anslutningsflödet, tvåvägssynkroniseringen och mötesslutpunkterna ovan fungerar precis som tidigare.
Endast Google Kalender. Gmail-brevlådans OAuth för e-postkanalen påverkas inte.
Vad din klient behöver först
- En OAuth 2.0-klient av typen Webbapplikation i ditt Google Cloud-projekt, med Google Calendar API aktiverat för det projektet.
- Varje
redirect_uris-post (som returneras av slutpunkterna nedan) tillagd under klientens Auktoriserade omdirigerings-URI:er. Den första posten är din verifieradeapi.-domän när du har en — Google verifierar endast ett varumärke vars omdirigering finns på en domän du äger — följt av plattformens neutrala värd som reservalternativ fram till dess. - Godkännandeskärmen med ditt varumärke, din domän under Auktoriserade domäner och de två Kalender-omfången deklarerade (
scopesi svaret). Tills appen är publicerad och verifierad av Google ser användare en varning om overifierad app och klienten är begränsad till 100 användare.
Spara din klient
PUT /account-config/google-oauth-client
| Fält | Krävs | Beskrivning |
|---|---|---|
client_id |
Ja | OAuth 2.0-klient-ID:t, som slutar på .apps.googleusercontent.com. |
client_secret |
Ja | Klienthemligheten. Verifieras mot Google innan den lagras, och krypteras sedan. Returneras aldrig av någon slutpunkt. |
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"
}'
Svar
{
"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": ["…"]
}
En felaktig hemlighet eller ett okänt klient-ID nekas med 400 och Googles egen orsak i error, och ingenting lagras.
Läs eller ta bort den
GET /account-config/google-oauth-client returnerar samma sammanfattning när som helst — configured: false plus redirect_uris och scopes innan något sparas, så att du kan ställa in Google-sidan först. DELETE /account-config/google-oauth-client tar bort klienten: nya anslutningar återgår till plattformsklienten, och kalendrar som var anslutna via den borttagna klienten måste återanslutas, eftersom endast den klient som skapade en anslutning kan uppdatera den.
Teammedlemmar behöver Integrations: view för GET och Integrations: edit för PUT / DELETE.
Nästa steg
- Kontakter — skapa och sök efter de kontakter du bokar för.
- Meddelanden och konversationer — skicka en bekräftelse eller påminnelse till en kontakt.
- Webhooks — få aviseringar när bokningar ändras.