API-referentie
Afspraken
Afspraken in de agenda: inplannen, verzetten, bevestigen, annuleren en afronden, en de klant een bericht sturen.
Endpoints
-
GET
/appointmentsAfspraken opvragen -
GET
/appointments/{appointment}Afspraak ophalen -
POST
/appointmentsAfspraak inplannen -
PATCH
/appointments/{appointment}Afspraak bijwerken -
POST
/appointments/{appointment}/confirmAfspraak bevestigen -
POST
/appointments/{appointment}/cancelAfspraak annuleren -
POST
/appointments/{appointment}/completeAfspraak afronden -
POST
/appointments/{appointment}/notifyBericht aan de klant sturen -
DELETE
/appointments/{appointment}Afspraak verwijderen
Afspraken opvragen
/api/v1/appointments
Een lijst van afspraken, nieuwste eerst. Filter op status, klant, gebruiker, begintijd of wijzigingsdatum. Sorteer op starts_at voor de volgorde van de agenda; afspraken zonder datum (een uitnodiging) vallen dan weg.
- Scope
-
appointments.read— Afspraken (met naam, e-mail en telefoon van de klant), afspraaktypes en beschikbaarheid lezen - Vereiste functie
appointments
Queryparameters
| Naam | Type | Omschrijving |
|---|---|---|
limit
|
integer | Aantal resultaten per pagina. van 1 tot 100 · standaard: 50 |
cursor
|
string | De next_cursor of prev_cursor uit meta van het vorige antwoord. |
sort
|
string | Sortering op created_at, updated_at of starts_at; een min-teken ervoor is aflopend. Bij starts_at vallen afspraken zonder datum weg. een van: -created_at, created_at, -updated_at, updated_at, -starts_at, starts_at · standaard: -created_at |
filter[status]
|
string | Alleen afspraken met deze status: pending (nog niet bevestigd), confirmed, cancelled of completed. een van: pending, confirmed, cancelled, completed |
filter[customer_id]
|
string (uuid) | Alleen wat bij deze klant hoort. |
filter[user_id]
|
string | Alleen afspraken van deze gebruiker (de id uit Gebruikers opvragen). |
filter[starts_from]
|
string (date-time) | Alleen afspraken die op of na dit tijdstip beginnen: ISO 8601 mét tijdzone. |
filter[starts_until]
|
string (date-time) | Alleen afspraken die vóór dit tijdstip beginnen: ISO 8601 mét tijdzone. |
filter[updated_since]
|
string (date-time) | Alleen wat sinds dit tijdstip is gewijzigd: ISO 8601 mét tijdzone, bijvoorbeeld 2026-09-14T10:15:00Z. Handig om te synchroniseren. |
Voorbeeldverzoek
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"$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'];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();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"]Antwoord 200
Het antwoord is een lijst met cursorpaginering: data bevat de objecten, meta de paginering.
{
"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
}
}Mogelijke fouten
-
403
insufficient_scope— Deze API-sleutel heeft geen toegang tot deze actie. -
422
validation_failed— De invoer is ongeldig.
Afspraak ophalen
/api/v1/appointments/{appointment}
Eén afspraak op id. Het antwoord bevat een ETag die je bij bijwerken in If-Match kunt meesturen.
- Scope
-
appointments.read— Afspraken (met naam, e-mail en telefoon van de klant), afspraaktypes en beschikbaarheid lezen - Vereiste functie
appointments
Padparameters
| Naam | Type | Omschrijving |
|---|---|---|
appointment verplicht |
string (uuid) | De id (UUID) van de afspraak. |
Voorbeeldverzoek
curl "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$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'];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();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"]Antwoord 200
{
"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"
}
}Mogelijke fouten
-
403
insufficient_scope— Deze API-sleutel heeft geen toegang tot deze actie. -
404
not_found— Niet gevonden.
Afspraak inplannen
/api/v1/appointments
Plant een afspraak in bij een klant; naam, e-mail en telefoon komen van de klant. Zonder ends_at duurt de afspraak zo lang als het afspraaktype, anders de standaardduur uit de afspraakinstellingen. Klantly controleert hier geen beschikbaarheid: jouw planning is leidend. De API stuurt de klant zelf geen mail; daarvoor is Bericht aan de klant sturen. Heeft het bedrijf automations op "afspraak ingepland", dan lopen die wél, net als bij een afspraak in de agenda.
- Scope
-
appointments.write— Afspraken aanmaken, wijzigen, bevestigen, annuleren en afronden (automations van het bedrijf lopen mee) - Vereiste functie
appointments
Stuur een Idempotency-Key mee, dan maakt een nieuwe poging na een time-out geen dubbel record.
Body (JSON)
| Veld | Type | Omschrijving |
|---|---|---|
customer_id
verplicht
|
string (uuid) | De klant van de afspraak. Verplicht bij aanmaken. |
title
optioneel
|
string | Titel van de afspraak. kan leeg zijn (null) · maximaal 255 tekens · verplicht zonder appointment_type_id |
description
optioneel
|
string | Omschrijving. kan leeg zijn (null) · maximaal 2000 tekens |
location
optioneel
|
string | Locatie, bijvoorbeeld het adres van de klant. kan leeg zijn (null) · maximaal 255 tekens |
starts_at
verplicht
|
string (date-time) | Begin (UTC). Leeg bij een uitnodiging waarvoor de klant nog een tijd kiest. Bij invoer: ISO 8601 mét tijdzone. |
ends_at
optioneel
|
string (date-time) | Einde (UTC). Zonder ends_at bij aanmaken: de duur van het afspraaktype of de standaardduur. kan leeg zijn (null) |
all_day
optioneel
|
boolean | Een afspraak voor de hele dag. Tijden staan in het antwoord in UTC: reken voor de datum terug naar de tijdzone van het bedrijf (Europe/Amsterdam), anders valt een afspraak die om 00:00 begint op de dag ervoor. |
appointment_type_id
optioneel
|
string (uuid) | Het afspraaktype, of null. kan leeg zijn (null) |
user_id
optioneel
|
string | De gebruiker die de afspraak heeft, of null. kan leeg zijn (null) |
status
optioneel
|
string | pending (nog niet bevestigd), confirmed, cancelled (geannuleerd) of completed (afgerond). Bij aanmaken pending of confirmed (standaard). een van: pending, confirmed |
notes
optioneel
|
string | Interne notitie bij de afspraak. kan leeg zijn (null) · maximaal 2000 tekens |
Voorbeeldverzoek
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"
}'$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'];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();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"]Antwoord 201
{
"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"
}
}Mogelijke fouten
-
403
insufficient_scope— Deze API-sleutel heeft geen toegang tot deze actie. -
422
validation_failed— De invoer is ongeldig. -
422
unknown_field— De invoer bevat een onbekend veld. -
415
unsupported_media_type— Dit formaat wordt niet ondersteund. -
413
payload_too_large— De body van het verzoek is te groot. -
422
idempotency_key_reused— Deze Idempotency-Key is al gebruikt voor een ander verzoek. -
409
idempotency_in_progress— Een verzoek met deze Idempotency-Key is nog bezig.
Afspraak bijwerken
/api/v1/appointments/{appointment}
Wijzigt alleen de velden die je meestuurt. Een nieuwe starts_at is een verzetting: rescheduled_at wordt gezet, en zonder ends_at blijft de duur gelijk. Krijgt een afspraak zonder datum een starts_at, dan komt ends_at erbij zoals bij aanmaken; een ends_at zonder begintijd kan niet (422). De status verander je met bevestigen, annuleren of afronden.
- Scope
-
appointments.write— Afspraken aanmaken, wijzigen, bevestigen, annuleren en afronden (automations van het bedrijf lopen mee) - Vereiste functie
appointments
Stuur de ETag mee in If-Match, dan overschrijf je nooit per ongeluk een nieuwere versie.
Padparameters
| Naam | Type | Omschrijving |
|---|---|---|
appointment verplicht |
string (uuid) | De id (UUID) van de afspraak. |
Body (JSON)
| Veld | Type | Omschrijving |
|---|---|---|
title
optioneel
|
string | Titel van de afspraak. maximaal 255 tekens |
description
optioneel
|
string | Omschrijving. kan leeg zijn (null) · maximaal 2000 tekens |
location
optioneel
|
string | Locatie, bijvoorbeeld het adres van de klant. kan leeg zijn (null) · maximaal 255 tekens |
starts_at
optioneel
|
string (date-time) | Begin (UTC). Leeg bij een uitnodiging waarvoor de klant nog een tijd kiest. Bij invoer: ISO 8601 mét tijdzone. |
ends_at
optioneel
|
string (date-time) | Einde (UTC). Zonder ends_at bij aanmaken: de duur van het afspraaktype of de standaardduur. |
all_day
optioneel
|
boolean | Een afspraak voor de hele dag. Tijden staan in het antwoord in UTC: reken voor de datum terug naar de tijdzone van het bedrijf (Europe/Amsterdam), anders valt een afspraak die om 00:00 begint op de dag ervoor. |
appointment_type_id
optioneel
|
string (uuid) | Het afspraaktype, of null. kan leeg zijn (null) |
user_id
optioneel
|
string | De gebruiker die de afspraak heeft, of null. kan leeg zijn (null) |
notes
optioneel
|
string | Interne notitie bij de afspraak. kan leeg zijn (null) · maximaal 2000 tekens |
Voorbeeldverzoek
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"
}'$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'];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();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"]Antwoord 200
{
"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"
}
}Mogelijke fouten
-
403
insufficient_scope— Deze API-sleutel heeft geen toegang tot deze actie. -
422
validation_failed— De invoer is ongeldig. -
422
unknown_field— De invoer bevat een onbekend veld. -
415
unsupported_media_type— Dit formaat wordt niet ondersteund. -
413
payload_too_large— De body van het verzoek is te groot. -
404
not_found— Niet gevonden. -
412
precondition_failed— Het record is intussen gewijzigd.
Afspraak bevestigen
/api/v1/appointments/{appointment}/confirm
Zet een afspraak op bevestigd. Is hij al bevestigd, dan verandert er niets.
- Scope
-
appointments.write— Afspraken aanmaken, wijzigen, bevestigen, annuleren en afronden (automations van het bedrijf lopen mee) - Vereiste functie
appointments
Stuur een Idempotency-Key mee, dan maakt een nieuwe poging na een time-out geen dubbel record.
Padparameters
| Naam | Type | Omschrijving |
|---|---|---|
appointment verplicht |
string (uuid) | De id (UUID) van de afspraak. |
Voorbeeldverzoek
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"$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'];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();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"]Antwoord 200
{
"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"
}
}Mogelijke fouten
-
403
insufficient_scope— Deze API-sleutel heeft geen toegang tot deze actie. -
404
not_found— Niet gevonden. -
409
invalid_state_transition— Deze actie kan niet in de huidige status. -
422
idempotency_key_reused— Deze Idempotency-Key is al gebruikt voor een ander verzoek. -
409
idempotency_in_progress— Een verzoek met deze Idempotency-Key is nog bezig.
Afspraak annuleren
/api/v1/appointments/{appointment}/cancel
Annuleert de afspraak, met optioneel een reden. Een afgeronde afspraak kan niet meer worden geannuleerd. Automations op "afspraak geannuleerd" lopen, net als in de agenda.
- Scope
-
appointments.write— Afspraken aanmaken, wijzigen, bevestigen, annuleren en afronden (automations van het bedrijf lopen mee) - Vereiste functie
appointments
Stuur een Idempotency-Key mee, dan maakt een nieuwe poging na een time-out geen dubbel record.
Padparameters
| Naam | Type | Omschrijving |
|---|---|---|
appointment verplicht |
string (uuid) | De id (UUID) van de afspraak. |
Body (JSON)
| Veld | Type | Omschrijving |
|---|---|---|
reason
optioneel
|
string | De reden van annuleren (optioneel). kan leeg zijn (null) · maximaal 500 tekens |
Voorbeeldverzoek
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"
}'$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'];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();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"]Antwoord 200
{
"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"
}
}Mogelijke fouten
-
403
insufficient_scope— Deze API-sleutel heeft geen toegang tot deze actie. -
422
validation_failed— De invoer is ongeldig. -
422
unknown_field— De invoer bevat een onbekend veld. -
415
unsupported_media_type— Dit formaat wordt niet ondersteund. -
413
payload_too_large— De body van het verzoek is te groot. -
404
not_found— Niet gevonden. -
409
invalid_state_transition— Deze actie kan niet in de huidige status. -
422
idempotency_key_reused— Deze Idempotency-Key is al gebruikt voor een ander verzoek. -
409
idempotency_in_progress— Een verzoek met deze Idempotency-Key is nog bezig.
Afspraak afronden
/api/v1/appointments/{appointment}/complete
Rondt de afspraak af. Staat de omzetting van leads bij het bedrijf op "afspraak afgerond", dan wordt een lead daarbij klant, net als in de agenda; bij de andere instellingen blijft hij lead.
- Scope
-
appointments.write— Afspraken aanmaken, wijzigen, bevestigen, annuleren en afronden (automations van het bedrijf lopen mee) - Vereiste functie
appointments
Stuur een Idempotency-Key mee, dan maakt een nieuwe poging na een time-out geen dubbel record.
Padparameters
| Naam | Type | Omschrijving |
|---|---|---|
appointment verplicht |
string (uuid) | De id (UUID) van de afspraak. |
Voorbeeldverzoek
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"$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'];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();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"]Antwoord 200
{
"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"
}
}Mogelijke fouten
-
403
insufficient_scope— Deze API-sleutel heeft geen toegang tot deze actie. -
404
not_found— Niet gevonden. -
409
invalid_state_transition— Deze actie kan niet in de huidige status. -
422
idempotency_key_reused— Deze Idempotency-Key is al gebruikt voor een ander verzoek. -
409
idempotency_in_progress— Een verzoek met deze Idempotency-Key is nog bezig.
Bericht aan de klant sturen
/api/v1/appointments/{appointment}/notify
Mailt de klant een bevestiging, verzetting, annulering of herinnering, met het sjabloon dat het bedrijf in Klantly heeft ingesteld. Het bericht moet passen bij de status van de afspraak. Heeft het bedrijf dat sjabloon uitgezet, dan volgt 409 en gaat er niets weg. Vraagt de scope appointments.send.
- Scope
-
appointments.send— Afspraakberichten naar klanten mailen - Vereiste functie
appointments
Stuur een Idempotency-Key mee, dan maakt een nieuwe poging na een time-out geen dubbel record.
Padparameters
| Naam | Type | Omschrijving |
|---|---|---|
appointment verplicht |
string (uuid) | De id (UUID) van de afspraak. |
Body (JSON)
| Veld | Type | Omschrijving |
|---|---|---|
message
verplicht
|
string | Welk bericht: confirmation (bevestiging), reschedule (verzetting), cancellation (annulering) of reminder (herinnering). een van: confirmation, reschedule, cancellation, reminder |
Voorbeeldverzoek
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"
}'$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'];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();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"]Antwoord 200
{
"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"
}
}Mogelijke fouten
-
403
insufficient_scope— Deze API-sleutel heeft geen toegang tot deze actie. -
422
validation_failed— De invoer is ongeldig. -
422
unknown_field— De invoer bevat een onbekend veld. -
415
unsupported_media_type— Dit formaat wordt niet ondersteund. -
413
payload_too_large— De body van het verzoek is te groot. -
404
not_found— Niet gevonden. -
409
invalid_state_transition— Deze actie kan niet in de huidige status. -
422
idempotency_key_reused— Deze Idempotency-Key is al gebruikt voor een ander verzoek. -
409
idempotency_in_progress— Een verzoek met deze Idempotency-Key is nog bezig.
Afspraak verwijderen
/api/v1/appointments/{appointment}
Verwijdert de afspraak definitief, ook uit de gekoppelde Google-agenda. Wil je hem alleen laten vervallen, annuleer hem dan.
- Scope
-
appointments.delete— Afspraken verwijderen - Vereiste functie
appointments
Padparameters
| Naam | Type | Omschrijving |
|---|---|---|
appointment verplicht |
string (uuid) | De id (UUID) van de afspraak. |
Voorbeeldverzoek
curl -X DELETE "https://app.klantly.com/api/v1/appointments/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$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'];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();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"]Antwoord 200
{
"data": {
"object": "note",
"id": "9d3f7b41-2d6f-4e8c-9b3a-4f5d6e7a8b92",
"deleted": true
}
}Mogelijke fouten
-
403
insufficient_scope— Deze API-sleutel heeft geen toegang tot deze actie. -
404
not_found— Niet gevonden.
Het object
Alle velden zijn altijd aanwezig; een veld zonder waarde is null.
| Veld | Type | Omschrijving |
|---|---|---|
object |
string | Altijd "appointment". |
id |
string (uuid) | Unieke id (UUID). |
title |
string | Titel van de afspraak. |
description |
string | Omschrijving. kan leeg zijn (null) |
status |
string | pending (nog niet bevestigd), confirmed, cancelled (geannuleerd) of completed (afgerond). Bij aanmaken pending of confirmed (standaard). een van: pending, confirmed, cancelled, completed |
starts_at |
string (date-time) | Begin (UTC). Leeg bij een uitnodiging waarvoor de klant nog een tijd kiest. Bij invoer: ISO 8601 mét tijdzone. kan leeg zijn (null) |
ends_at |
string (date-time) | Einde (UTC). Zonder ends_at bij aanmaken: de duur van het afspraaktype of de standaardduur. kan leeg zijn (null) |
all_day |
boolean | Een afspraak voor de hele dag. Tijden staan in het antwoord in UTC: reken voor de datum terug naar de tijdzone van het bedrijf (Europe/Amsterdam), anders valt een afspraak die om 00:00 begint op de dag ervoor. |
location |
string | Locatie, bijvoorbeeld het adres van de klant. kan leeg zijn (null) |
customer_id |
string (uuid) | De klant van de afspraak. Verplicht bij aanmaken. kan leeg zijn (null) |
contact |
object | De contactgegevens waarmee de afspraak is gemaakt. |
contact.name |
string | Naam. kan leeg zijn (null) |
contact.email |
string | E-mailadres; hierheen gaan berichten aan de klant. kan leeg zijn (null) |
contact.phone |
string | Telefoonnummer. kan leeg zijn (null) |
user_id |
string | De gebruiker die de afspraak heeft, of null. kan leeg zijn (null) |
appointment_type_id |
string (uuid) | Het afspraaktype, of null. kan leeg zijn (null) |
deal_id |
string (uuid) | De deal op het pipelinebord waar de afspraak bij hoort (koppelt Klantly zelf). kan leeg zijn (null) |
quote_id |
string (uuid) | De gekoppelde offerte, of null. kan leeg zijn (null) |
invoice_id |
string (uuid) | De gekoppelde factuur, of null. kan leeg zijn (null) |
notes |
string | Interne notitie bij de afspraak. kan leeg zijn (null) |
cancellation_reason |
string | Waarom de afspraak is geannuleerd, of null. kan leeg zijn (null) |
confirmed_at |
string (date-time) | Wanneer de afspraak werd bevestigd. kan leeg zijn (null) |
cancelled_at |
string (date-time) | Wanneer de afspraak werd geannuleerd. kan leeg zijn (null) |
rescheduled_at |
string (date-time) | Wanneer de afspraak voor het laatst werd verzet. kan leeg zijn (null) |
created_at |
string (date-time) | Aangemaakt op (UTC). |
updated_at |
string (date-time) | Laatst gewijzigd op (UTC). |