Klantly Developers

API-Referenz

Termine

Termine im Kalender: planen, verschieben, bestätigen, absagen und abschließen sowie dem Kunden eine Nachricht senden.

Endpunkte

Termine auflisten

GET /api/v1/appointments

Eine Liste von Terminen, neueste zuerst. Filtern Sie nach Status, Kunde, Benutzer, Beginn oder Änderungsdatum. Sortieren Sie nach starts_at für die Reihenfolge des Kalenders; Termine ohne Datum (eine Einladung) entfallen dann.

Scope
appointments.read — Termine (mit Name, E-Mail und Telefon des Kunden), Terminarten und Verfügbarkeit lesen
Erforderliche Funktion
appointments

Query-Parameter

NameTypBeschreibung
limit integer Anzahl der Ergebnisse pro Seite. von 1 bis 100 · Standard: 50
cursor string Der next_cursor oder prev_cursor aus meta der vorherigen Antwort.
sort string Sortierung nach created_at, updated_at oder starts_at; ein Minuszeichen davor bedeutet absteigend. Bei starts_at entfallen Termine ohne Datum. einer von: -created_at, created_at, -updated_at, updated_at, -starts_at, starts_at · Standard: -created_at
filter[status] string Nur Termine mit diesem Status: pending (noch nicht bestätigt), confirmed, cancelled oder completed. einer von: pending, confirmed, cancelled, completed
filter[customer_id] string (uuid) Nur was zu diesem Kunden gehört.
filter[user_id] string Nur Termine dieses Benutzers (die ID aus Benutzer auflisten).
filter[starts_from] string (date-time) Nur Termine, die zu oder nach diesem Zeitpunkt beginnen: ISO 8601 mit Zeitzone.
filter[starts_until] string (date-time) Nur Termine, die vor diesem Zeitpunkt beginnen: ISO 8601 mit Zeitzone.
filter[updated_since] string (date-time) Nur was seit diesem Zeitpunkt geändert wurde: ISO 8601 mit Zeitzone, zum Beispiel 2026-09-14T10:15:00Z. Praktisch zum Synchronisieren.

Beispielanfrage

cURL
curl "https://app.klantly.com/api/v1/appointments?filter[starts_from]=2026-10-01T00%3A00%3A00Z&sort=starts_at" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('GET', 'appointments', [
    'query' => [
        'filter[starts_from]' => '2026-10-01T00:00:00Z',
        'sort' => 'starts_at',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/appointments?filter[starts_from]=2026-10-01T00%3A00%3A00Z&sort=starts_at', {
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
  },
});

const { data } = await response.json();
Python
import os

import requests

response = requests.get(
    "https://app.klantly.com/api/v1/appointments",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
    },
    params={
        "filter[starts_from]": "2026-10-01T00:00:00Z",
        "sort": "starts_at"
    },
)
data = response.json()["data"]

Antwort 200

Die Antwort ist eine Liste mit Cursor-Paginierung: data enthält die Objekte, meta die Paginierung.

Beispielantwort
{
  "data": [
    {
      "object": "appointment",
      "id": "9d3f7d83-4f8b-4a0e-9d5c-6b7f8a9bacb4",
      "title": "Inmeten veranda",
      "description": null,
      "status": "confirmed",
      "starts_at": "2026-10-01T08:00:00Z",
      "ends_at": "2026-10-01T09:00:00Z",
      "all_day": false,
      "location": "Dorpsstraat 1, Utrecht",
      "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
      "contact": {
        "name": "Jan de Vries",
        "email": "jan@example.com",
        "phone": "+31 6 12345678"
      },
      "user_id": "usr_0k3j9x21m4zq8p",
      "appointment_type_id": "9d3f7ea4-5a9c-4b1f-8e6d-7c8a9bacbdc5",
      "deal_id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
      "quote_id": null,
      "invoice_id": null,
      "notes": null,
      "cancellation_reason": null,
      "confirmed_at": "2026-09-14T10:15:00Z",
      "cancelled_at": null,
      "rescheduled_at": null,
      "created_at": "2026-09-14T10:15:00Z",
      "updated_at": "2026-09-14T10:15:00Z"
    }
  ],
  "meta": {
    "limit": 50,
    "next_cursor": "eyJpZCI6IjlkM2Y2YzFlIn0",
    "prev_cursor": null
  }
}

Mögliche Fehler

Zusätzlich kann jeder Endpunkt die allgemeinen Fehler zurückgeben, etwa einen ungültigen Schlüssel oder ein erreichtes Limit. Alle Fehlercodes ansehen.

Termin abrufen

GET /api/v1/appointments/{appointment}

Ein Termin nach ID. Die Antwort enthält einen ETag, den Sie beim Bearbeiten in If-Match mitsenden können.

Scope
appointments.read — Termine (mit Name, E-Mail und Telefon des Kunden), Terminarten und Verfügbarkeit lesen
Erforderliche Funktion
appointments

Pfadparameter

NameTypBeschreibung
appointment erforderlich string (uuid) Die ID (UUID) des Termins.

Beispielanfrage

cURL
curl "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('GET', 'appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70');

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
  },
});

const { data } = await response.json();
Python
import os

import requests

response = requests.get(
    "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
    },
)
data = response.json()["data"]

Antwort 200

Beispielantwort
{
  "data": {
    "object": "appointment",
    "id": "9d3f7d83-4f8b-4a0e-9d5c-6b7f8a9bacb4",
    "title": "Inmeten veranda",
    "description": null,
    "status": "confirmed",
    "starts_at": "2026-10-01T08:00:00Z",
    "ends_at": "2026-10-01T09:00:00Z",
    "all_day": false,
    "location": "Dorpsstraat 1, Utrecht",
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "contact": {
      "name": "Jan de Vries",
      "email": "jan@example.com",
      "phone": "+31 6 12345678"
    },
    "user_id": "usr_0k3j9x21m4zq8p",
    "appointment_type_id": "9d3f7ea4-5a9c-4b1f-8e6d-7c8a9bacbdc5",
    "deal_id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "quote_id": null,
    "invoice_id": null,
    "notes": null,
    "cancellation_reason": null,
    "confirmed_at": "2026-09-14T10:15:00Z",
    "cancelled_at": null,
    "rescheduled_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Mögliche Fehler

Zusätzlich kann jeder Endpunkt die allgemeinen Fehler zurückgeben, etwa einen ungültigen Schlüssel oder ein erreichtes Limit. Alle Fehlercodes ansehen.

Termin planen

POST /api/v1/appointments

Plant einen Termin mit einem Kunden; Name, E-Mail und Telefon kommen vom Kunden. Ohne ends_at dauert der Termin so lange wie seine Terminart, sonst die Standarddauer aus den Termineinstellungen. Klantly prüft hier keine Verfügbarkeit: Ihre Planung ist maßgeblich. Die API selbst sendet dem Kunden keine E-Mail; dafür gibt es Nachricht an den Kunden senden. Hat das Unternehmen Automationen auf „Termin geplant“, laufen diese wie bei einem Termin im Kalender.

Scope
appointments.write — Termine erstellen, bearbeiten, bestätigen, absagen und abschließen (Automationen des Unternehmens laufen mit)
Erforderliche Funktion
appointments

Senden Sie einen Idempotency-Key mit, dann erzeugt ein erneuter Versuch nach einem Timeout keinen doppelten Datensatz.

Body (JSON)

FeldTypBeschreibung
customer_id erforderlich string (uuid) Der Kunde des Termins. Beim Erstellen erforderlich.
title optional string Titel des Termins. kann leer sein (null) · höchstens 255 Zeichen · erforderlich ohne appointment_type_id
description optional string Beschreibung. kann leer sein (null) · höchstens 2000 Zeichen
location optional string Ort, zum Beispiel die Adresse des Kunden. kann leer sein (null) · höchstens 255 Zeichen
starts_at erforderlich string (date-time) Beginn (UTC). Leer bei einer Einladung, bei der der Kunde noch eine Zeit wählt. Bei der Eingabe: ISO 8601 mit Zeitzone.
ends_at optional string (date-time) Ende (UTC). Ohne ends_at beim Erstellen: die Dauer der Terminart oder die Standarddauer. kann leer sein (null)
all_day optional boolean Ein ganztägiger Termin. Zeiten stehen in der Antwort in UTC: Rechnen Sie für das Datum in die Zeitzone des Unternehmens (Europe/Amsterdam) zurück, sonst fällt ein Termin, der um 00:00 beginnt, auf den Vortag.
appointment_type_id optional string (uuid) Die Terminart, oder null. kann leer sein (null)
user_id optional string Der Benutzer, der den Termin hat, oder null. kann leer sein (null)
status optional string pending (noch nicht bestätigt), confirmed, cancelled (abgesagt) oder completed (abgeschlossen). Beim Erstellen pending oder confirmed (Standard). einer von: pending, confirmed
notes optional string Interne Notiz zum Termin. kann leer sein (null) · höchstens 2000 Zeichen

Beispielanfrage

cURL
curl -X POST "https://app.klantly.com/api/v1/appointments" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
  -d '{
  "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
  "title": "Inmeten veranda",
  "starts_at": "2026-10-01T10:00:00+02:00",
  "appointment_type_id": "9d3f7ea4-5a9c-4b1f-8e6d-7c8a9bacbdc5"
}'
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('POST', 'appointments', [
    'headers' => [
        'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
    ],
    'json' => [
        'customer_id' => '9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70',
        'title' => 'Inmeten veranda',
        'starts_at' => '2026-10-01T10:00:00+02:00',
        'appointment_type_id' => '9d3f7ea4-5a9c-4b1f-8e6d-7c8a9bacbdc5',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/appointments', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
  },
  body: JSON.stringify({
  "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
  "title": "Inmeten veranda",
  "starts_at": "2026-10-01T10:00:00+02:00",
  "appointment_type_id": "9d3f7ea4-5a9c-4b1f-8e6d-7c8a9bacbdc5"
}),
});

const { data } = await response.json();
Python
import os

import requests

response = requests.post(
    "https://app.klantly.com/api/v1/appointments",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
        "Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    },
    json={
        "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
        "title": "Inmeten veranda",
        "starts_at": "2026-10-01T10:00:00+02:00",
        "appointment_type_id": "9d3f7ea4-5a9c-4b1f-8e6d-7c8a9bacbdc5"
    },
)
data = response.json()["data"]

Antwort 201

Beispielantwort
{
  "data": {
    "object": "appointment",
    "id": "9d3f7d83-4f8b-4a0e-9d5c-6b7f8a9bacb4",
    "title": "Inmeten veranda",
    "description": null,
    "status": "confirmed",
    "starts_at": "2026-10-01T08:00:00Z",
    "ends_at": "2026-10-01T09:00:00Z",
    "all_day": false,
    "location": "Dorpsstraat 1, Utrecht",
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "contact": {
      "name": "Jan de Vries",
      "email": "jan@example.com",
      "phone": "+31 6 12345678"
    },
    "user_id": "usr_0k3j9x21m4zq8p",
    "appointment_type_id": "9d3f7ea4-5a9c-4b1f-8e6d-7c8a9bacbdc5",
    "deal_id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "quote_id": null,
    "invoice_id": null,
    "notes": null,
    "cancellation_reason": null,
    "confirmed_at": "2026-09-14T10:15:00Z",
    "cancelled_at": null,
    "rescheduled_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Mögliche Fehler

Zusätzlich kann jeder Endpunkt die allgemeinen Fehler zurückgeben, etwa einen ungültigen Schlüssel oder ein erreichtes Limit. Alle Fehlercodes ansehen.

Termin bearbeiten

PATCH /api/v1/appointments/{appointment}

Ändert nur die Felder, die Sie mitsenden. Ein neues starts_at ist eine Verschiebung: rescheduled_at wird gesetzt, und ohne ends_at bleibt die Dauer gleich. Erhält ein Termin ohne Datum ein starts_at, kommt ends_at wie beim Erstellen hinzu; ein ends_at ohne Startzeit ist nicht möglich (422). Den Status ändern Sie mit Bestätigen, Absagen oder Abschließen.

Scope
appointments.write — Termine erstellen, bearbeiten, bestätigen, absagen und abschließen (Automationen des Unternehmens laufen mit)
Erforderliche Funktion
appointments

Senden Sie das ETag in If-Match mit, dann überschreiben Sie nie versehentlich eine neuere Version.

Pfadparameter

NameTypBeschreibung
appointment erforderlich string (uuid) Die ID (UUID) des Termins.

Body (JSON)

FeldTypBeschreibung
title optional string Titel des Termins. höchstens 255 Zeichen
description optional string Beschreibung. kann leer sein (null) · höchstens 2000 Zeichen
location optional string Ort, zum Beispiel die Adresse des Kunden. kann leer sein (null) · höchstens 255 Zeichen
starts_at optional string (date-time) Beginn (UTC). Leer bei einer Einladung, bei der der Kunde noch eine Zeit wählt. Bei der Eingabe: ISO 8601 mit Zeitzone.
ends_at optional string (date-time) Ende (UTC). Ohne ends_at beim Erstellen: die Dauer der Terminart oder die Standarddauer.
all_day optional boolean Ein ganztägiger Termin. Zeiten stehen in der Antwort in UTC: Rechnen Sie für das Datum in die Zeitzone des Unternehmens (Europe/Amsterdam) zurück, sonst fällt ein Termin, der um 00:00 beginnt, auf den Vortag.
appointment_type_id optional string (uuid) Die Terminart, oder null. kann leer sein (null)
user_id optional string Der Benutzer, der den Termin hat, oder null. kann leer sein (null)
notes optional string Interne Notiz zum Termin. kann leer sein (null) · höchstens 2000 Zeichen

Beispielanfrage

cURL
curl -X PATCH "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "starts_at": "2026-10-02T09:00:00Z"
}'
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('PATCH', 'appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', [
    'json' => [
        'starts_at' => '2026-10-02T09:00:00Z',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
  "starts_at": "2026-10-02T09:00:00Z"
}),
});

const { data } = await response.json();
Python
import os

import requests

response = requests.patch(
    "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
    },
    json={
        "starts_at": "2026-10-02T09:00:00Z"
    },
)
data = response.json()["data"]

Antwort 200

Beispielantwort
{
  "data": {
    "object": "appointment",
    "id": "9d3f7d83-4f8b-4a0e-9d5c-6b7f8a9bacb4",
    "title": "Inmeten veranda",
    "description": null,
    "status": "confirmed",
    "starts_at": "2026-10-01T08:00:00Z",
    "ends_at": "2026-10-01T09:00:00Z",
    "all_day": false,
    "location": "Dorpsstraat 1, Utrecht",
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "contact": {
      "name": "Jan de Vries",
      "email": "jan@example.com",
      "phone": "+31 6 12345678"
    },
    "user_id": "usr_0k3j9x21m4zq8p",
    "appointment_type_id": "9d3f7ea4-5a9c-4b1f-8e6d-7c8a9bacbdc5",
    "deal_id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "quote_id": null,
    "invoice_id": null,
    "notes": null,
    "cancellation_reason": null,
    "confirmed_at": "2026-09-14T10:15:00Z",
    "cancelled_at": null,
    "rescheduled_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Mögliche Fehler

Zusätzlich kann jeder Endpunkt die allgemeinen Fehler zurückgeben, etwa einen ungültigen Schlüssel oder ein erreichtes Limit. Alle Fehlercodes ansehen.

Termin bestätigen

POST /api/v1/appointments/{appointment}/confirm

Setzt einen Termin auf bestätigt. Ist er bereits bestätigt, ändert sich nichts.

Scope
appointments.write — Termine erstellen, bearbeiten, bestätigen, absagen und abschließen (Automationen des Unternehmens laufen mit)
Erforderliche Funktion
appointments

Senden Sie einen Idempotency-Key mit, dann erzeugt ein erneuter Versuch nach einem Timeout keinen doppelten Datensatz.

Pfadparameter

NameTypBeschreibung
appointment erforderlich string (uuid) Die ID (UUID) des Termins.

Beispielanfrage

cURL
curl -X POST "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/confirm" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('POST', 'appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/confirm', [
    'headers' => [
        'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/confirm', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
    'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
  },
});

const { data } = await response.json();
Python
import os

import requests

response = requests.post(
    "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/confirm",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
        "Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    },
)
data = response.json()["data"]

Antwort 200

Beispielantwort
{
  "data": {
    "object": "appointment",
    "id": "9d3f7d83-4f8b-4a0e-9d5c-6b7f8a9bacb4",
    "title": "Inmeten veranda",
    "description": null,
    "status": "confirmed",
    "starts_at": "2026-10-01T08:00:00Z",
    "ends_at": "2026-10-01T09:00:00Z",
    "all_day": false,
    "location": "Dorpsstraat 1, Utrecht",
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "contact": {
      "name": "Jan de Vries",
      "email": "jan@example.com",
      "phone": "+31 6 12345678"
    },
    "user_id": "usr_0k3j9x21m4zq8p",
    "appointment_type_id": "9d3f7ea4-5a9c-4b1f-8e6d-7c8a9bacbdc5",
    "deal_id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "quote_id": null,
    "invoice_id": null,
    "notes": null,
    "cancellation_reason": null,
    "confirmed_at": "2026-09-14T10:15:00Z",
    "cancelled_at": null,
    "rescheduled_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Mögliche Fehler

Zusätzlich kann jeder Endpunkt die allgemeinen Fehler zurückgeben, etwa einen ungültigen Schlüssel oder ein erreichtes Limit. Alle Fehlercodes ansehen.

Termin absagen

POST /api/v1/appointments/{appointment}/cancel

Sagt den Termin ab, optional mit einem Grund. Ein abgeschlossener Termin kann nicht mehr abgesagt werden. Automationen auf „Termin abgesagt“ laufen wie im Kalender.

Scope
appointments.write — Termine erstellen, bearbeiten, bestätigen, absagen und abschließen (Automationen des Unternehmens laufen mit)
Erforderliche Funktion
appointments

Senden Sie einen Idempotency-Key mit, dann erzeugt ein erneuter Versuch nach einem Timeout keinen doppelten Datensatz.

Pfadparameter

NameTypBeschreibung
appointment erforderlich string (uuid) Die ID (UUID) des Termins.

Body (JSON)

FeldTypBeschreibung
reason optional string Der Grund der Absage (optional). kann leer sein (null) · höchstens 500 Zeichen

Beispielanfrage

cURL
curl -X POST "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/cancel" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
  -d '{
  "reason": "Klant is verhinderd"
}'
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('POST', 'appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/cancel', [
    'headers' => [
        'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
    ],
    'json' => [
        'reason' => 'Klant is verhinderd',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/cancel', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
  },
  body: JSON.stringify({
  "reason": "Klant is verhinderd"
}),
});

const { data } = await response.json();
Python
import os

import requests

response = requests.post(
    "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/cancel",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
        "Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    },
    json={
        "reason": "Klant is verhinderd"
    },
)
data = response.json()["data"]

Antwort 200

Beispielantwort
{
  "data": {
    "object": "appointment",
    "id": "9d3f7d83-4f8b-4a0e-9d5c-6b7f8a9bacb4",
    "title": "Inmeten veranda",
    "description": null,
    "status": "confirmed",
    "starts_at": "2026-10-01T08:00:00Z",
    "ends_at": "2026-10-01T09:00:00Z",
    "all_day": false,
    "location": "Dorpsstraat 1, Utrecht",
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "contact": {
      "name": "Jan de Vries",
      "email": "jan@example.com",
      "phone": "+31 6 12345678"
    },
    "user_id": "usr_0k3j9x21m4zq8p",
    "appointment_type_id": "9d3f7ea4-5a9c-4b1f-8e6d-7c8a9bacbdc5",
    "deal_id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "quote_id": null,
    "invoice_id": null,
    "notes": null,
    "cancellation_reason": null,
    "confirmed_at": "2026-09-14T10:15:00Z",
    "cancelled_at": null,
    "rescheduled_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Mögliche Fehler

Zusätzlich kann jeder Endpunkt die allgemeinen Fehler zurückgeben, etwa einen ungültigen Schlüssel oder ein erreichtes Limit. Alle Fehlercodes ansehen.

Termin abschließen

POST /api/v1/appointments/{appointment}/complete

Schließt den Termin ab. Steht die Lead-Umwandlung des Unternehmens auf „Termin abgeschlossen“, wird ein Lead dabei zum Kunden, genau wie im Kalender; bei den anderen Einstellungen bleibt er Lead.

Scope
appointments.write — Termine erstellen, bearbeiten, bestätigen, absagen und abschließen (Automationen des Unternehmens laufen mit)
Erforderliche Funktion
appointments

Senden Sie einen Idempotency-Key mit, dann erzeugt ein erneuter Versuch nach einem Timeout keinen doppelten Datensatz.

Pfadparameter

NameTypBeschreibung
appointment erforderlich string (uuid) Die ID (UUID) des Termins.

Beispielanfrage

cURL
curl -X POST "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/complete" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('POST', 'appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/complete', [
    'headers' => [
        'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/complete', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
    'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
  },
});

const { data } = await response.json();
Python
import os

import requests

response = requests.post(
    "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/complete",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
        "Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    },
)
data = response.json()["data"]

Antwort 200

Beispielantwort
{
  "data": {
    "object": "appointment",
    "id": "9d3f7d83-4f8b-4a0e-9d5c-6b7f8a9bacb4",
    "title": "Inmeten veranda",
    "description": null,
    "status": "confirmed",
    "starts_at": "2026-10-01T08:00:00Z",
    "ends_at": "2026-10-01T09:00:00Z",
    "all_day": false,
    "location": "Dorpsstraat 1, Utrecht",
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "contact": {
      "name": "Jan de Vries",
      "email": "jan@example.com",
      "phone": "+31 6 12345678"
    },
    "user_id": "usr_0k3j9x21m4zq8p",
    "appointment_type_id": "9d3f7ea4-5a9c-4b1f-8e6d-7c8a9bacbdc5",
    "deal_id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "quote_id": null,
    "invoice_id": null,
    "notes": null,
    "cancellation_reason": null,
    "confirmed_at": "2026-09-14T10:15:00Z",
    "cancelled_at": null,
    "rescheduled_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Mögliche Fehler

Zusätzlich kann jeder Endpunkt die allgemeinen Fehler zurückgeben, etwa einen ungültigen Schlüssel oder ein erreichtes Limit. Alle Fehlercodes ansehen.

Nachricht an den Kunden senden

POST /api/v1/appointments/{appointment}/notify

Sendet dem Kunden per E-Mail eine Bestätigung, Verschiebung, Absage oder Erinnerung, mit der Vorlage, die das Unternehmen in Klantly eingerichtet hat. Die Nachricht muss zum Status des Termins passen. Hat das Unternehmen diese Vorlage ausgeschaltet, erhalten Sie 409 und es wird nichts gesendet. Erfordert den Scope appointments.send.

Scope
appointments.send — Terminnachrichten per E-Mail an Kunden senden
Erforderliche Funktion
appointments

Senden Sie einen Idempotency-Key mit, dann erzeugt ein erneuter Versuch nach einem Timeout keinen doppelten Datensatz.

Pfadparameter

NameTypBeschreibung
appointment erforderlich string (uuid) Die ID (UUID) des Termins.

Body (JSON)

FeldTypBeschreibung
message erforderlich string Welche Nachricht: confirmation (Bestätigung), reschedule (Verschiebung), cancellation (Absage) oder reminder (Erinnerung). einer von: confirmation, reschedule, cancellation, reminder

Beispielanfrage

cURL
curl -X POST "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/notify" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
  -d '{
  "message": "confirmation"
}'
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('POST', 'appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/notify', [
    'headers' => [
        'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
    ],
    'json' => [
        'message' => 'confirmation',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/notify', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
  },
  body: JSON.stringify({
  "message": "confirmation"
}),
});

const { data } = await response.json();
Python
import os

import requests

response = requests.post(
    "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/notify",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
        "Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    },
    json={
        "message": "confirmation"
    },
)
data = response.json()["data"]

Antwort 200

Beispielantwort
{
  "data": {
    "object": "appointment",
    "id": "9d3f7d83-4f8b-4a0e-9d5c-6b7f8a9bacb4",
    "title": "Inmeten veranda",
    "description": null,
    "status": "confirmed",
    "starts_at": "2026-10-01T08:00:00Z",
    "ends_at": "2026-10-01T09:00:00Z",
    "all_day": false,
    "location": "Dorpsstraat 1, Utrecht",
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "contact": {
      "name": "Jan de Vries",
      "email": "jan@example.com",
      "phone": "+31 6 12345678"
    },
    "user_id": "usr_0k3j9x21m4zq8p",
    "appointment_type_id": "9d3f7ea4-5a9c-4b1f-8e6d-7c8a9bacbdc5",
    "deal_id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "quote_id": null,
    "invoice_id": null,
    "notes": null,
    "cancellation_reason": null,
    "confirmed_at": "2026-09-14T10:15:00Z",
    "cancelled_at": null,
    "rescheduled_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Mögliche Fehler

Zusätzlich kann jeder Endpunkt die allgemeinen Fehler zurückgeben, etwa einen ungültigen Schlüssel oder ein erreichtes Limit. Alle Fehlercodes ansehen.

Termin löschen

DELETE /api/v1/appointments/{appointment}

Löscht den Termin endgültig, auch aus dem verknüpften Google-Kalender. Soll er nur entfallen, sagen Sie ihn stattdessen ab.

Scope
appointments.delete — Termine löschen
Erforderliche Funktion
appointments

Pfadparameter

NameTypBeschreibung
appointment erforderlich string (uuid) Die ID (UUID) des Termins.

Beispielanfrage

cURL
curl -X DELETE "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('DELETE', 'appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70');

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
  },
});

const { data } = await response.json();
Python
import os

import requests

response = requests.delete(
    "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
    },
)
data = response.json()["data"]

Antwort 200

Beispielantwort
{
  "data": {
    "object": "note",
    "id": "9d3f7b41-2d6f-4e8c-9b3a-4f5d6e7a8b92",
    "deleted": true
  }
}

Mögliche Fehler

Zusätzlich kann jeder Endpunkt die allgemeinen Fehler zurückgeben, etwa einen ungültigen Schlüssel oder ein erreichtes Limit. Alle Fehlercodes ansehen.

Das Objekt

Alle Felder sind immer vorhanden; ein Feld ohne Wert ist null.

FeldTypBeschreibung
object string Immer „appointment“.
id string (uuid) Eindeutige ID (UUID).
title string Titel des Termins.
description string Beschreibung. kann leer sein (null)
status string pending (noch nicht bestätigt), confirmed, cancelled (abgesagt) oder completed (abgeschlossen). Beim Erstellen pending oder confirmed (Standard). einer von: pending, confirmed, cancelled, completed
starts_at string (date-time) Beginn (UTC). Leer bei einer Einladung, bei der der Kunde noch eine Zeit wählt. Bei der Eingabe: ISO 8601 mit Zeitzone. kann leer sein (null)
ends_at string (date-time) Ende (UTC). Ohne ends_at beim Erstellen: die Dauer der Terminart oder die Standarddauer. kann leer sein (null)
all_day boolean Ein ganztägiger Termin. Zeiten stehen in der Antwort in UTC: Rechnen Sie für das Datum in die Zeitzone des Unternehmens (Europe/Amsterdam) zurück, sonst fällt ein Termin, der um 00:00 beginnt, auf den Vortag.
location string Ort, zum Beispiel die Adresse des Kunden. kann leer sein (null)
customer_id string (uuid) Der Kunde des Termins. Beim Erstellen erforderlich. kann leer sein (null)
contact object Die Kontaktdaten, mit denen der Termin angelegt wurde.
contact.name string Name. kann leer sein (null)
contact.email string E-Mail-Adresse; hierhin gehen Nachrichten an den Kunden. kann leer sein (null)
contact.phone string Telefonnummer. kann leer sein (null)
user_id string Der Benutzer, der den Termin hat, oder null. kann leer sein (null)
appointment_type_id string (uuid) Die Terminart, oder null. kann leer sein (null)
deal_id string (uuid) Der Deal auf dem Pipeline-Board, zu dem der Termin gehört (verknüpft Klantly selbst). kann leer sein (null)
quote_id string (uuid) Das verknüpfte Angebot, oder null. kann leer sein (null)
invoice_id string (uuid) Die verknüpfte Rechnung, oder null. kann leer sein (null)
notes string Interne Notiz zum Termin. kann leer sein (null)
cancellation_reason string Warum der Termin abgesagt wurde, oder null. kann leer sein (null)
confirmed_at string (date-time) Wann der Termin bestätigt wurde. kann leer sein (null)
cancelled_at string (date-time) Wann der Termin abgesagt wurde. kann leer sein (null)
rescheduled_at string (date-time) Wann der Termin zuletzt verschoben wurde. kann leer sein (null)
created_at string (date-time) Erstellt am (UTC).
updated_at string (date-time) Zuletzt geändert am (UTC).