DM Champ Docs

Spotkania

Interfejs API Appointments umożliwia rezerwowanie wizyt dla Twoich kontaktów w ramach typów wydarzeń, a następnie ich pobieranie, wyświetlanie, aktualizowanie, anulowanie lub usuwanie. Odpowiada również na pytanie, które pojawia się jako pierwsze w większości procesów rezerwacji — które terminy są faktycznie wolne — oraz obsługuje stronę kalendarza: wyświetlanie połączonych kalendarzy Google i importowanie wydarzeń, które już się w nich znajdują. Gdy połączenie z Kalendarzem Google jest aktywne, pasujące wydarzenie w kalendarzu jest tworzone i automatycznie synchronizowane w tle. Restauracje korzystające z systemów Zenchef, Formitable, OpenTable lub TheFork do własnych rezerwacji mogą być również zweryfikowane i połączone w tym miejscu, dzięki czemu Agent AI rezerwuje rzeczywiste stoliki zamiast wewnętrznych wizyt — firmy usługowe prowadzące harmonogram w Trafft mogą połączyć się w ten sam sposób.

Wszystkie ścieżki na tej stronie są względne względem podstawowego adresu URL https://api.dmchamp.com/v1. Każde żądanie wymaga Twojego klucza API — zobacz Uwierzytelnianie, aby uzyskać pełną listę sposobów jego przesyłania. Poniższe przykłady wykorzystują nagłówek X-API-Key, a jeden z przykładów cURL pokazuje również formularz zapytania ?apiKey=.

Wydarzenia a spotkania: Typ wydarzenia to definicja dostępnego terminu (rodzaj spotkania, jego długość, sale). Spotkanie to jedna zarezerwowana instancja typu wydarzenia dla konkretnego kontaktu. Spotkanie rezerwuje się poprzez odwołanie do kontaktu oraz typu wydarzenia.


Obiekt spotkania

Każdy punkt końcowy, który zwraca spotkanie, używa tego samego formatu:

Pole Opis
id Unikalny identyfikator spotkania.
contact_id Identyfikator kontaktu, dla którego zarezerwowano spotkanie.
event_id Identyfikator typu wydarzenia, w ramach którego zarezerwowano spotkanie.
status Confirmed lub Canceled.
start_time Początek spotkania, format ISO 8601 w UTC.
end_time Koniec spotkania, format ISO 8601 w UTC.
created_at Czas utworzenia spotkania.
last_modified_at Czas ostatniej zmiany spotkania.
room_name Sala lub zasób, w którym zarezerwowano spotkanie, jeśli typ wydarzenia korzysta z sal.
description Dowolny opis spotkania.
summary Krótkie podsumowanie lub tytuł.
cancelation_reason Powód podany podczas anulowania spotkania, jeśli istnieje.
google_calendar_event_id Identyfikator powiązanego wydarzenia w Kalendarzu Google. Ustawiany po zakończeniu synchronizacji z kalendarzem; null, gdy żaden kalendarz nie jest połączony lub gdy synchronizacja jest w toku.
calendar_synced true po powiązaniu spotkania z wydarzeniem w kalendarzu.
imported true, gdy spotkanie zostało zaimportowane z zewnętrznego kalendarza zamiast bezpośredniej rezerwacji.
is_recurring true, gdy spotkanie jest częścią serii cyklicznej.
recurrence_frequency Częstotliwość powtarzania spotkania w przypadku serii cyklicznej.
recurring_event_id Identyfikator serii cyklicznej, do której należy to spotkanie.
recurring_interval Interwał między powtórzeniami w przypadku serii cyklicznej.
recurring_sequence Pozycja tego spotkania w serii cyklicznej.
end_after_x_occurrences Liczba wystąpień, po których kończy się seria cykliczna.
booking_provider System źródłowy, z którego pochodzi rezerwacja, w przypadku rezerwacji przez połączonego dostawcę usług rezerwacyjnych.

O synchronizacji kalendarza: Bezpośrednio po zarezerwowaniu lub zmianie spotkania pole google_calendar_event_id może nadal mieć wartość null, a calendar_synced może być false, ponieważ synchronizacja odbywa się w tle chwilę później. Pobierz spotkanie ponownie po krótkim czasie, aby zobaczyć wypełnione pola kalendarza.


Znajdź dostępne terminy

GET /appointments/available-slots

Zwraca terminy, które są faktycznie wolne dla danego typu wydarzenia pomiędzy dwoma punktami w czasie. Jest to zazwyczaj pierwsze wywołanie w procesie rezerwacji: wyświetl te terminy, pozwól użytkownikowi wybrać jeden z nich, a następnie wyślij wybrany czas do Zarezerwuj spotkanie.

Odpowiedź uwzględnia już godziny otwarcia i długość slotu danego typu wydarzenia, jego sale, spotkania, które już zostały zarezerwowane, oraz wszystko, co jest zablokowane w połączonych Kalendarzach Google — więc każdy zwrócony termin jest terminem, który możesz zarezerwować.

Parametr zapytania Wymagany Opis
event_id Tak Typ wydarzenia do sprawdzenia. Musi należeć do Twojego konta.
start_time Tak Początek okna czasowego, dla którego chcesz sprawdzić dostępność, w formacie daty i godziny ISO 8601.
end_time Tak Koniec okna czasowego w formacie daty i godziny ISO 8601. Cały dzień końcowy jest uwzględniony.

Wyniki są pogrupowane według dni — a w przypadku, gdy typ wydarzenia korzysta z sal, jedna grupa na salę na dzień:

Pole Opis
date Dzień, którego dotyczy grupa, zapisany jako DD/MM/YYYY.
day Nazwa dnia tygodnia małymi literami, na przykład monday.
room_name Sala lub zasób, do którego należy ta grupa, jeśli typ wydarzenia korzysta z sal.
available_slots Dostępne bloki rezerwacyjne w tym dniu, od najwcześniejszego.

Każdy wpis w available_slots zawiera:

Pole Opis
start_time Początek bloku jako HH:mm.
end_time Koniec bloku jako HH:mm.
available true — zwracany jest tylko wolny czas.
spots_left Ile rezerwacji jeszcze mieści się w tym bloku. Obecne tylko w typach wydarzeń, które przyjmują więcej niż jedną rezerwację na slot.

Czasy są lokalne dla typu wydarzenia, a nie w UTC. date, start_time oraz end_time to wartości zegarowe w strefie czasowej typu wydarzenia (jego nadpisaniu lub strefie czasowej Twojego konta, jeśli nie określono inaczej). Zarezerwuj spotkanie oczekuje momentu w formacie ISO 8601 UTC, więc przekonwertuj wybrany termin przed jego wysłaniem.

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"])

Odpowiedź (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 }
      ]
    }
  ]
}

Dzień, w którym nie ma wolnych terminów, po prostu się nie pojawia. Brak event_id, start_time lub end_time zwraca 400; typ wydarzenia, którego nie ma na Twoim koncie, zwraca 404.


Zarezerwuj spotkanie

POST /appointments

Rezerwuje nowe spotkanie dla kontaktu w ramach jednego z Twoich typów wydarzeń. Czas zakończenia jest obliczany automatycznie na podstawie czasu trwania terminu typu wydarzenia.

Rezerwacja jest sprawdzana pod kątem konfliktów: jeśli żądany termin pokrywa się z istniejącym potwierdzonym spotkaniem w ramach tego samego typu wydarzenia, żądanie kończy się niepowodzeniem z błędem 409 i nic nie zostaje utworzone.

Pole Wymagane Opis
contact_id Tak Identyfikator kontaktu, dla którego dokonujemy rezerwacji. Musi należeć do Twojego konta.
event_id Tak Identyfikator typu wydarzenia, w ramach którego dokonujemy rezerwacji. Musi należeć do Twojego konta.
start_time Tak Żądany czas rozpoczęcia jako data i godzina w formacie ISO 8601.
room_name Nie Nazwa sali lub zasobu, jeśli typ wydarzenia korzysta z sal.

cURL (używając formularza zapytania ?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"])

Odpowiedź (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
  }
}

Uzyskaj spotkanie

GET /appointments/{appointmentId}

Zwraca pojedyncze spotkanie na podstawie jego identyfikatora, w tym jego stan synchronizacji z kalendarzem.

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"])

Odpowiedź (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
  }
}

Wyświetl listę spotkań

GET /appointments

Wyświetla listę spotkań dla Twojego konta, od najnowszego, z wykorzystaniem stronicowania opartego na kursorze.

Parametr zapytania Wymagany Opis
contact_id Nie Zwraca tylko spotkania dla tego kontaktu. Listy filtrowane według kontaktu zawierają tylko potwierdzone spotkania
date Nie Zwraca tylko spotkania z tego dnia kalendarzowego (YYYY-MM-DD). Wymaga contact_id.
status Nie Filtruj według Confirmed lub Canceled. Dostępne tylko bez contact_id.
limit Nie Rozmiar strony, liczba całkowita od 1 do 100. Domyślnie 50.
cursor Nie Wartość next_cursor z poprzedniej odpowiedzi.

Kilka zasad, o których warto pamiętać:

  • Bez filtrów otrzymasz każde spotkanie na koncie, strona po stronie.
  • Według kontaktu — ustaw contact_id, aby zobaczyć potwierdzone spotkania danego kontaktu. Możesz zawęzić to do jednego dnia, przekazując również date.
  • Według statusu — ustaw status (bez contact_id), aby wyświetlić tylko spotkania Confirmed lub tylko Canceled na całym koncie.
  • Filtr date bez contact_id lub status=Canceled wraz z contact_id zwraca 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"])

Odpowiedź (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
}

Aby przeglądać wyniki, przekaż next_cursor z jednej odpowiedzi jako cursor w następnym żądaniu. Kontynuuj, aż next_cursor będzie null. Zobacz Błędy i stronicowanie, aby poznać wspólny wzorzec stronicowania.


Zaktualizuj spotkanie

PUT /appointments/{appointmentId}

Zmień termin spotkania lub edytuj jego szczegóły. Wyślij tylko te pola, które chcesz zmienić — wymagane jest co najmniej jedno. Połączony czas rozpoczęcia i zakończenia musi zachowywać porządek chronologiczny (end_time musi być po start_time). Zmiany są automatycznie synchronizowane z powiązanym wydarzeniem w kalendarzu.

Pole Opis
start_time Nowy początek, data i godzina w formacie ISO 8601.
end_time Nowy koniec, data i godzina w formacie ISO 8601. Musi przypadać po czasie rozpoczęcia.
room_name Nowa nazwa pokoju lub zasobu.
description Nowy opis lub null, aby go wyczyścić.
summary Nowe podsumowanie lub null, aby je wyczyścić.

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"])

Odpowiedź (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
  }
}

Anulowanie spotkania

POST /appointments/{appointmentId}/cancel

Anuluje potwierdzone spotkanie, opcjonalnie rejestrując powód. Spotkanie pozostaje na Twoim koncie ze statusem Canceled, a powiązane wydarzenie w kalendarzu jest automatycznie usuwane w tle. Anulowanie już anulowanego spotkania zwraca 400.

Pole Wymagane Opis
cancellation_reason Nie Powód anulowania, zapisywany w spotkaniu.

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"])

Odpowiedź (200 OK):

{
  "success": true,
  "appointment_id": "aBcD1234eFgH5678"
}

Usuwanie spotkania

DELETE /appointments/{appointmentId}

Trwale usuwa spotkanie i jego odniesienia. Jeśli chcesz tylko odwołać rezerwację, zachowując rekord, użyj zamiast tego anuluj.

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"])

Odpowiedź (200 OK):

{
  "success": true
}

Wyświetl swoje połączone Kalendarze Google

GET /appointments/google-calendars

Zwraca kalendarze Google dostępne na tym koncie, bezpośrednio z Google — przydatne do pokazania właścicielowi konta selektora kalendarza, z którego ma importować dane, lub po prostu do potwierdzenia, że połączenie jest aktywne.

Działa to tylko wtedy, gdy konto ma połączony Kalendarz Google (Ustawienia → Integracje) z co najmniej dostępem do odczytu. Jeśli tak nie jest lub przyznany dostęp nie obejmuje już zakresu odczytu kalendarza, otrzymasz 400 z informacją o konieczności (ponownego) połączenia go.

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"])

Odpowiedź (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"
    }
  ]
}

Każdy wpis ma własny format CalendarListEntry Google, więc nazwy pól są zgodne z camelCase Google, a nie ze standardowym snake_case tego API — są to dane Google przekazane w niezmienionej formie, a nie nasze. Brakujące lub cofnięte połączenie zwraca 400 z błędem wyjaśniającym, że Kalendarz Google wymaga (ponownego) połączenia.


Importuj wydarzenia z Kalendarza Google

POST /appointments/import-calendar-events

Pobiera wydarzenia znajdujące się już w połączonym(-ych) Kalendarzu(-ach) Google kampanii lub Agenta AI i zamienia je w spotkania — przydatne przy pierwszym łączeniu kalendarza, który ma już istniejące rezerwacje. Może to chwilę potrwać (każde wydarzenie przechodzi przez proces ekstrakcji, aby ustalić, dla kogo jest przeznaczone), więc nigdy nie działa w trybie inline: żądanie dodaje zadanie do kolejki w tle i zwraca job_id do odpytywania.

Pole Wymagane Opis
campaign_id Jedno z tych dwóch Kampania, z której połączonych kalendarzy importować dane.
agent_id Jedno z tych dwóch Agent AI, z którego połączonych kalendarzy importować dane.
identifier Tak "EMAIL" lub "PHONE_NUMBER" — który element danych kontaktowych wyodrębnić z każdego wydarzenia w kalendarzu, aby dopasować lub utworzyć kontakt, do którego ono należy.

Wyślij dokładnie jedno z campaign_id / agent_id, nigdy oba i nigdy żadnego — każda inna kombinacja zwraca 400. To, które wyślesz, musi należeć do Twojego konta, w przeciwnym razie otrzymasz 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"])

Odpowiedź (202 Accepted):

{
  "success": true,
  "job_id": "jK9mQ2xR7pL4wN1t",
  "status": "queued",
  "campaign_id": null,
  "agent_id": "agent_abc123"
}

campaign_id i agent_id zwracają to, które wysłałeś; drugie jest zawsze null.

Odpytywanie zadania importu

GET /appointments/import-calendar-events/{jobId}

curl "https://api.dmchamp.com/v1/appointments/import-calendar-events/jK9mQ2xR7pL4wN1t" \
  -H "X-API-Key: YOUR_API_KEY"

Odpowiedź (200 OK):

{
  "success": true,
  "job_id": "jK9mQ2xR7pL4wN1t",
  "status": "completed",
  "message": "Imported 12 events as appointments.",
  "error": null
}
status Znaczenie
queued Jeszcze nieodebrane. Kontynuuj odpytywanie.
processing Import jest w toku. Kontynuuj odpytywanie.
completed Gotowe — message zawiera krótkie, czytelne podsumowanie.
failed Coś poszło nie tak — error zawiera przyczynę.

GET dla jobId, który nie istnieje (lub należy do innego konta), zwraca 404.


Zewnętrzne integracje rezerwacyjne (Zenchef / Formitable / OpenTable / TheFork / Trafft)

Zenchef i Formitable to systemy rezerwacji restauracji, za pośrednictwem których Twój Agent AI może rezerwować prawdziwe stoliki; Trafft to platforma do planowania dla firm usługowych, łączona raz na konto, a nie dla każdej restauracji z osobna. Obie platformy restauracyjne posiadają publiczny, nieuwierzytelniony widżet rezerwacyjny (https://api.dmchamp.com/v1/zenchef-widget/... i https://api.dmchamp.com/v1/formitable-widget/...), który wyświetla się w czacie dla klienta — te ścieżki widżetów to zwykłe strony HTML przeznaczone do otwierania w przeglądarce, a nie punkty końcowe JSON API, dlatego nie zostały tutaj opisane. Poniżej znajdują się punkty końcowe zarządzania kontem: weryfikacja, czy identyfikator restauracji należy do właściciela konta, a następnie dodawanie, aktualizowanie lub usuwanie go.

Zenchef

Podłączenie restauracji Zenchef to dwuetapowa weryfikacja, dzięki której właściciel konta potwierdza, że faktycznie prowadzi restaurację, zanim zostanie ona połączona z botem: najpierw sprawdź, czy identyfikator istnieje (bez ujawniania nazwy), a następnie poproś o samodzielne wpisanie nazwy restauracji i sprawdź, czy jest ona zgodna.

Krok 1 — Sprawdź, czy identyfikator restauracji istnieje

POST /appointments/zenchef-restaurants/check

Pole Wymagane Opis
restaurant_id Tak Identyfikator restauracji Zenchef do sprawdzenia.
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" }'

Odpowiedź (200 OK):

{
  "success": true,
  "data": { "exists": true, "requiresNameVerification": true }
}

exists: false oznacza, że żadna restauracja Zenchef nie posiada tego identyfikatora — nie ma nic więcej do zrobienia. Limit wynosi 10 sprawdzeń na 5 minut na konto; przekroczenie tego limitu zwraca 429.

Krok 2 — Zweryfikuj nazwę restauracji

POST /appointments/zenchef-restaurants/verify-name

Pole Wymagane Opis
restaurant_id Tak Identyfikator restauracji Zenchef z kroku 1.
user_input_name Tak Nazwa wpisana przez właściciela konta — porównywana z rzeczywistą nazwą restauracji w Zenchef (wielkość liter i białe znaki są ignorowane).
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" }'

Odpowiedź (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 oznacza, że nazwa nie pasuje — restaurantDetails jest pomijane, poproś właściciela konta o ponowną próbę. Limit wynosi 3 próby na 5 minut (bardziej rygorystyczny niż sprawdzenie istnienia, ponieważ jest to właściwy krok weryfikacyjny). restaurant_id, który nie jest już rozpoznawany w Zenchef, zwraca 404.

Krok 3 — Zapisz restaurację

POST /appointments/zenchef-restaurants

Pole Wymagane Opis
restaurant_id Tak 1–64 znaki, litery/cyfry/podkreślnik/myślnik.
restaurant_name Tak Zweryfikowana nazwa restauracji z kroku 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" }'

Odpowiedź (201 Created):

{ "success": true, "data": { "restaurantId": "12345" } }

Aktualizacja zapisanej restauracji Zenchef

PUT /appointments/zenchef-restaurants/{restaurantId}

Pole Wymagane Opis
restaurant_name Nie Nowa nazwa wyświetlana.
is_active Nie Ustaw false, aby powstrzymać bota przed dokonywaniem rezerwacji w tej restauracji bez jej usuwania.
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 }'

Odpowiedź (200 OK): ten sam format co odpowiedź zapisu powyżej.

Usuń restaurację 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"

Odpowiedź (200 OK): { "success": true, "data": { "restaurantId": "12345" } }

restaurantId, którego obecnie nie ma na koncie, zwraca 404 przy aktualizacji lub usunięciu.

Formitable

Formitable nie wymaga dwuetapowego potwierdzenia nazwy, jak Zenchef — jego identyfikatory restauracji są już przypisane do konkretnej firmy, więc wystarczy jedno wywołanie weryfikacyjne. Posiada również funkcję wyszukiwania szczegółów, używaną do buforowania adresu URL strony internetowej restauracji podczas konfiguracji.

Zweryfikuj identyfikator restauracji

POST /appointments/formitable-restaurants/verify

Pole Wymagane Opis
restaurant_id Tak Identyfikator restauracji Formitable.
language Nie Znacznik języka dla żądania sondowania. Domyślnie "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" }'

Odpowiedź (200 OK):

{
  "success": true,
  "data": {
    "verified": true,
    "restaurantDetails": {
      "restaurantId": "the-blue-door",
      "productCount": 4,
      "sampleProductTitle": "Dinner for two",
      "language": "en"
    }
  }
}

restaurant_id, którego Formitable nie rozpoznaje, zwraca 404. Limit prędkości wynosi 10 prób na 5 minut na konto.

Pobierz szczegóły restauracji

GET /appointments/formitable-restaurants/{restaurantId}/details?language=en

Pobiera publiczny profil restauracji z Formitable, w tym jej stronę internetową — używane do buforowania adresu URL strony podczas konfigurowania restauracji. language jest opcjonalnym parametrem zapytania, domyślnie ustawionym na "en".

curl "https://api.dmchamp.com/v1/appointments/formitable-restaurants/the-blue-door/details?language=en" \
  -H "X-API-Key: YOUR_API_KEY"

Odpowiedź (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"
  }
}

Zapisz restaurację

POST /appointments/formitable-restaurants

Pole Wymagane Opis
restaurant_id Tak 1–64 znaki, litery/cyfry/podkreślnik/myślnik.
restaurant_name Tak Nazwa wyświetlana.
language Tak Znacznik języka ISO, np. "en" lub "en-GB".
website_url Nie Strona internetowa restauracji, z powyższego wyszukiwania szczegółów. Musi być 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"
  }'

Odpowiedź (201 Created): { "success": true, "data": { "restaurantId": "the-blue-door" } }

Zaktualizuj zapisaną restaurację Formitable

PUT /appointments/formitable-restaurants/{restaurantId}

Pole Wymagane Opis
restaurant_name Nie Nowa nazwa wyświetlana.
language Nie Nowy znacznik języka ISO.
is_active Nie Ustaw false, aby powstrzymać bota przed dokonywaniem rezerwacji w tej restauracji bez jej usuwania.
website_url Nie Nowy adres URL strony internetowej.
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 }'

Odpowiedź (200 OK): ten sam format co odpowiedź zapisu powyżej.

Usuń restaurację 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"

Odpowiedź (200 OK): { "success": true, "data": { "restaurantId": "the-blue-door" } }

restaurantId, którego obecnie nie ma na koncie, zwraca 404 przy aktualizacji lub usunięciu.

OpenTable

Restauracje OpenTable są dostępne za pośrednictwem danych uwierzytelniających partnera OpenTable platformy, a OpenTable pozwala tym danym widzieć tylko te restauracje, które połączyły ofertę platformy wewnątrz Marketplace Integracji OpenTable. Podobnie jak w przypadku Formitable, wystarczy jedno wywołanie weryfikacyjne: osiągalny identyfikator restauracji (numeryczny “RID”) potwierdza zarówno istnienie restauracji, jak i fakt, że połączyła ona integrację. Dopóki oferta partnera OpenTable nie zostanie włączona na platformie, wywołanie weryfikacyjne zwróci 503.

Weryfikacja restauracji OpenTable

POST /appointments/opentable-restaurants/verify

Pole Wymagane Opis
restaurant_id Tak Identyfikator restauracji OpenTable (RID), liczba taka jak 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" }'

Odpowiedź (200 OK):

{
  "success": true,
  "data": {
    "verified": true,
    "restaurantDetails": {
      "restaurantId": "1038007",
      "diningAreaCount": 2,
      "diningAreaNames": ["Main Room", "Garden"],
      "tableTypes": ["default", "outdoor", "bar"]
    }
  }
}

verified: false oznacza, że żadna restauracja OpenTable nie posiada tego identyfikatora. 403 oznacza, że restauracja istnieje, ale nie połączyła jeszcze integracji platformy wewnątrz OpenTable. Limit wynosi 10 prób na 5 minut na konto.

Dodawanie restauracji OpenTable

POST /appointments/opentable-restaurants

Pole Wymagane Opis
restaurant_id Tak Zweryfikowany identyfikator restauracji.
restaurant_name Tak Nazwa wyświetlana (etykieta; używana również przez AI do nazywania restauracji).
website_url Nie Adres URL http(s) pokazywany gościom, gdy AI przekierowuje ich do restauracji.
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" }'

Odpowiedź (201 Created): { "success": true, "data": { "restaurantId": "1038007" } }

Aktualizacja zapisanej restauracji OpenTable

PUT /appointments/opentable-restaurants/{restaurantId}

Wyślij dowolne z restaurant_name, is_active (wstrzymaj za pomocą false) lub website_url (pusty ciąg znaków czyści pole); pominięte pola pozostają bez zmian.

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 }'

Odpowiedź (200 OK): { "success": true, "data": { "restaurantId": "1038007" } }

Usuwanie restauracji z 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"

Odpowiedź (200 OK): { "success": true, "data": { "restaurantId": "1038007" } }

Aktualizacja restaurantId, którego nie ma obecnie na koncie, zwraca 404.

TheFork

Restauracje TheFork są obsługiwane za pośrednictwem danych uwierzytelniających partnera TheFork, a platforma TheFork pozwala tym danym widzieć tylko te restauracje, które mają włączonego partnera platformy na swoim koncie TheFork. Podobnie jak w przypadku Formitable i OpenTable, wystarczy jedno wywołanie weryfikacyjne: osiągalny identyfikator restauracji (Restaurant ID) potwierdza zarówno istnienie restauracji, jak i to, że partner jest na niej włączony. Identyfikator to UUID nadawany restauracji przez TheFork w menedżerze TheFork Manager, przesyłany jako ciąg znaków. Dopóki TheFork nie zatwierdzi platformy jako partnera i nie wyda danych uwierzytelniających, wywołanie weryfikacyjne zwróci 503 — zobacz TheFork, aby dowiedzieć się, co to oznacza obecnie.

Weryfikacja restauracji TheFork

POST /appointments/thefork-restaurants/verify

Pole Wymagane Opis
restaurant_id Tak Identyfikator restauracji TheFork, UUID, np. 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" }'

Odpowiedź (200 OK):

{
  "success": true,
  "data": {
    "verified": true,
    "restaurantDetails": {
      "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60",
      "partySizes": [1, 2, 3, 4, 5, 6, 7, 8]
    }
  }
}

partySizes to wielkości grup, które restauracja przyjmuje online w ciągu najbliższych 30 dni. 404 lub 403 oznacza, że TheFork nie udostępnił nam restauracji o tym identyfikatorze — albo identyfikator jest błędny, albo partner platformy nie jest jeszcze włączony dla tej restauracji; 400 oznacza, że identyfikator nie jest w formacie UUID. Limit wynosi 10 prób na 5 minut na konto.

Dodawanie restauracji TheFork

POST /appointments/thefork-restaurants

Pole Wymagane Opis
restaurant_id Tak Zweryfikowany identyfikator restauracji (UUID).
restaurant_name Tak Nazwa wyświetlana (etykieta; używana również przez AI do nazywania restauracji).
website_url Nie Adres URL http(s) pokazywany gościom, gdy AI przekierowuje ich do restauracji.
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" }'

Odpowiedź (201 Created): { "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }

Aktualizacja zapisanej restauracji TheFork

PUT /appointments/thefork-restaurants/{restaurantId}

Wyślij dowolne z restaurant_name, is_active (wstrzymaj za pomocą false) lub website_url (pusty ciąg znaków czyści pole); pominięte pola pozostają bez zmian.

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 }'

Odpowiedź (200 OK): { "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }

Usuwanie restauracji 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"

Odpowiedź (200 OK): { "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }

restaurantId, którego obecnie nie ma na koncie, zwraca 404 przy aktualizacji lub usunięciu.

Trafft

System Trafft łączy się raz dla całego konta, a nie dla każdej lokalizacji: jeden adres firmy oraz dane uwierzytelniające API z panelu administratora Trafft (Features & Integrations → API & Connectors, część planu Business w Trafft). Wywołanie połączenia sprawdza te dane uwierzytelniające w systemie Trafft przed zapisaniem czegokolwiek, więc błędny adres, błędne dane lub plan bez dostępu do API spowodują błąd na tym etapie, a nie podczas rozmowy z klientem. Klient secret jest przechowywany w formie zaszyfrowanej i nigdy nie jest zwracany przez żaden punkt końcowy.

Wszystkie trzy wywołania zapisu (POST, PUT, DELETE) wymagają uprawnienia edit dla integracji; status GET wymaga uprawnienia view dla integracji.

Połącz Trafft

POST /appointments/trafft/connect

Pole Wymagane Opis
subdomain Tak Adres firmy — część przed .admin.trafft.com w adresie URL, pod którym się logujesz, np. acme. Pełny adres jest akceptowany i skracany do tej samej wartości.
client_id Tak Client ID ze strony API & Connectors w Trafft.
client_secret Tak Client Secret z tej samej strony. Przechowywany w formie zaszyfrowanej, nigdy nie jest zwracany.
company_name Nie Etykieta dla Twojej własnej listy.
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"
  }'

Odpowiedź (200 OK):

{
  "success": true,
  "data": {
    "subdomain": "acme",
    "service_count": 12,
    "employee_count": 4,
    "location_count": 2
  }
}

Liczby są zwracane z systemu Trafft podczas sprawdzania — to najszybszy sposób, aby potwierdzić, że dane uwierzytelniające wskazują na konto, o które Ci chodziło.

Pobierz status połączenia

GET /appointments/trafft

curl "https://api.dmchamp.com/v1/appointments/trafft" \
  -H "X-API-Key: YOUR_API_KEY"

Odpowiedź (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 oznacza, że nic nie zostało jeszcze skonfigurowane. Klient secret nigdy nie jest uwzględniany w tej odpowiedzi.

Aktualizuj połączenie

PUT /appointments/trafft

Pole Wymagane Opis
is_active Nie Ustaw false, aby wstrzymać — AI przestaje dodawać rezerwacje do Trafft, połączenie pozostaje aktywne. true wznawia działanie.
company_name Nie Nowa etykieta.
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 }'

Odpowiedź (200 OK): ten sam obiekt połączenia co GET powyżej.

Rozłącz Trafft

DELETE /appointments/trafft

curl -X DELETE "https://api.dmchamp.com/v1/appointments/trafft" \
  -H "X-API-Key: YOUR_API_KEY"

Odpowiedź (200 OK): { "success": true }

Rozłączenie usuwa tylko zapisane dane uwierzytelniające. Rezerwacje znajdujące się już w Trafft pozostają nienaruszone.

Format błędu we wszystkich punktach końcowych Zenchef/Formitable/OpenTable/TheFork: w przeciwieństwie do reszty tej strony, błędy w tym miejscu zawierają status dwukrotnie — raz jako status HTTP, a raz jako error_code w treści — na przykład { "success": false, "error": "Restaurant not found", "error_code": 404 }. Obsługuj je w taki sam sposób jak każdy inny błąd: sprawdź success, przeczytaj error, aby uzyskać komunikat.


Błędy API wizyt

Punkty końcowe wizyt zwracają standardową kopertę błędu:

{
  "success": false,
  "error": "Appointment not found"
}
Status Kiedy występuje w punkcie końcowym wizyt
400 Brakuje wymaganego pola lub jest ono nieprawidłowe — na przykład błędny start_time, end_time niebędący po start_time, nieprawidłowa kombinacja filtrów, brak pól do aktualizacji lub wizyta, która została już anulowana.
404 Nie znaleziono wizyty, kontaktu lub typu wydarzenia.
409 Żądany przedział czasowy jest już zajęty (konflikt rezerwacji).

Wspólne kody, które może zwrócić każdy punkt końcowy — 401, 403 (Twój plan nie obejmuje dostępu do API), 429 (limit szybkości) oraz 500 — zostały wymienione wraz ze wskazówkami dotyczącymi ponawiania prób w sekcji Błędy i stronicowanie.


Użyj własnego klienta Google OAuth (ekran zgody Kalendarza)

Gdy konto łączy się z Kalendarzem Google, okno logowania Google wyświetla nazwę projektu klienta OAuth — domyślnie jest to projekt platformy. Agencja może zarejestrować własnego klienta Google OAuth 2.0 na koncie agencji; od tego momentu łączenie kalendarza dla tego konta i wszystkich podrzędnych kont odbywa się za pośrednictwem tego klienta, dzięki czemu na ekranie zgody wyświetlana jest nazwa i logo agencji. Nic innego się nie zmienia: proces łączenia, synchronizacja dwukierunkowa i powyższe punkty końcowe dotyczące spotkań działają dokładnie tak samo jak wcześniej.

Tylko Kalendarz Google. OAuth skrzynki pocztowej Gmail dla kanału Email pozostaje bez zmian.

Czego najpierw potrzebuje Twój klient

  1. Klient OAuth 2.0 typu Aplikacja internetowa w Twoim projekcie Google Cloud, z włączonym interfejsem Google Calendar API w tym projekcie.
  2. Każdy wpis redirect_uris (zwracany przez poniższe punkty końcowe) dodany w sekcji Autoryzowane identyfikatory URI przekierowania klienta. Pierwszym wpisem jest Twoja zweryfikowana domena api., jeśli ją posiadasz — Google weryfikuje tylko markę, której przekierowanie znajduje się w domenie, której jesteś właścicielem — a następnie neutralny host platformy jako rozwiązanie zastępcze używane do tego czasu.
  3. Ekran zgody z Twoją marką, Twoją domeną w sekcji Autoryzowane domeny oraz zadeklarowanymi dwoma zakresami Kalendarza (scopes w odpowiedzi). Dopóki aplikacja nie zostanie opublikowana i zweryfikowana przez Google, użytkownicy będą widzieć ostrzeżenie o niezweryfikowanej aplikacji, a liczba użytkowników klienta będzie ograniczona do 100.

Zapisz swojego klienta

PUT /account-config/google-oauth-client

Pole Wymagane Opis
client_id Tak Identyfikator klienta OAuth 2.0, kończący się na .apps.googleusercontent.com.
client_secret Tak Klucz tajny klienta. Weryfikowany w Google przed zapisaniem, a następnie szyfrowany. Nigdy nie jest zwracany przez żaden punkt końcowy.
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"
  }'

Odpowiedź

{
  "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": ["…"]
}

Błędny klucz tajny lub nieznany identyfikator klienta są odrzucane z 400 oraz własnym powodem Google w error, a żadne dane nie są zapisywane.

Odczytaj lub usuń

GET /account-config/google-oauth-client zwraca to samo podsumowanie w dowolnym momencie — configured: false oraz redirect_uris i scopes przed zapisaniem czegokolwiek, dzięki czemu możesz najpierw skonfigurować stronę Google. DELETE /account-config/google-oauth-client usuwa klienta: nowe połączenia powracają do klienta platformy, a kalendarze, które zostały połączone za pośrednictwem usuniętego klienta, muszą zostać połączone ponownie, ponieważ tylko klient, który ustanowił połączenie, może je odświeżyć.

Członkowie zespołu potrzebują uprawnień Integracje: wyświetlanie dla GET oraz Integracje: edycja dla PUT / DELETE.


Następne kroki

  • Kontakty — twórz i wyszukuj kontakty, dla których dokonujesz rezerwacji.
  • Wiadomości i konwersacje — wysyłaj do kontaktu potwierdzenia lub przypomnienia.
  • Webhooki — otrzymuj powiadomienia o zmianach w spotkaniach.