API-referentie
Klanten
Klanten en leads: aanmaken, opzoeken, bijwerken en een lead omzetten naar klant.
Endpoints
-
GET
/customersKlanten opvragen -
GET
/customers/{customer}Klant ophalen -
POST
/customersKlant aanmaken -
PATCH
/customers/{customer}Klant bijwerken -
POST
/customers/{customer}/convertLead omzetten naar klant -
GET
/customers/{customer}/activitiesTijdlijn van een klant
Klanten opvragen
/api/v1/customers
Een lijst van klanten en leads, nieuwste eerst. Filter op status, type, e-mailadres of wijzigingsdatum, zoek met q en blader met de cursor uit meta.
- Scope
-
customers.read— Klanten en leads lezen
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. |
q |
string | Zoek in naam, e-mailadres, bedrijfsnaam en telefoonnummer. minimaal 2 tekens · maximaal 100 tekens |
sort |
string | Sortering op created_at of updated_at; een min-teken ervoor is aflopend. een van: -created_at, created_at, -updated_at, updated_at · standaard: -created_at |
filter[status] |
string | Alleen leads of alleen klanten. een van: lead, customer |
filter[type] |
string | Alleen particulieren of alleen bedrijven. een van: individual, business |
filter[email] |
string (email) | Precies dit e-mailadres (hoofdletters maken niet uit). |
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/customers?limit=50&filter[status]=lead" \
-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', 'customers', [
'query' => [
'limit' => 50,
'filter[status]' => 'lead',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/customers?limit=50&filter[status]=lead', {
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/customers",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
params={
"limit": 50,
"filter[status]": "lead"
},
)
data = response.json()["data"]Antwoord 200
Het antwoord is een lijst met cursorpaginering: data bevat de objecten, meta de paginering.
{
"data": [
{
"object": "customer",
"id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"type": "business",
"status": "lead",
"name": "Jan de Vries",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"company_name": "De Vries Bouw",
"vat_number": "NL123456789B01",
"coc_number": "12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"email_unsubscribed": false,
"converted_at": null,
"last_activity_at": "2026-09-14T10:15:00Z",
"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.
Klant ophalen
/api/v1/customers/{customer}
Eén klant op id. Het antwoord bevat een ETag die je bij bijwerken in If-Match kunt meesturen.
- Scope
-
customers.read— Klanten en leads lezen
Padparameters
| Naam | Type | Omschrijving |
|---|---|---|
customer verplicht |
string (uuid) | De id (UUID) van de klant. |
Voorbeeldverzoek
curl "https://app.klantly.com/api/v1/customers/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', 'customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/customers/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/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Antwoord 200
{
"data": {
"object": "customer",
"id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"type": "business",
"status": "lead",
"name": "Jan de Vries",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"company_name": "De Vries Bouw",
"vat_number": "NL123456789B01",
"coc_number": "12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"email_unsubscribed": false,
"converted_at": null,
"last_activity_at": "2026-09-14T10:15:00Z",
"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.
Klant aanmaken
/api/v1/customers
Maakt een nieuwe lead aan. Het e-mailadres is verplicht en uniek binnen je bedrijf: een bestaand adres geeft een validatiefout. Automations en de klanttijdlijn werken precies zoals bij aanmaken in Klantly zelf.
- Scope
-
customers.write— Klanten en leads aanmaken en wijzigen
Stuur een Idempotency-Key mee, dan maakt een nieuwe poging na een time-out geen dubbel record.
Body (JSON)
| Veld | Type | Omschrijving |
|---|---|---|
email
verplicht
|
string (email) | E-mailadres; uniek binnen je bedrijf. maximaal 255 tekens · uniek binnen je bedrijf |
type
optioneel
|
string | individual (particulier) of business (bedrijf). een van: individual, business |
name
optioneel
|
string | Naam van de contactpersoon. kan leeg zijn (null) · maximaal 255 tekens |
phone
optioneel
|
string | Telefoonnummer. kan leeg zijn (null) · maximaal 255 tekens |
address
optioneel
|
string | Straat en huisnummer. kan leeg zijn (null) · maximaal 255 tekens |
city
optioneel
|
string | Plaats. kan leeg zijn (null) · maximaal 255 tekens |
postal_code
optioneel
|
string | Postcode. kan leeg zijn (null) · maximaal 64 tekens |
country
optioneel
|
string | Land. kan leeg zijn (null) · minimaal 2 tekens · maximaal 2 tekens |
company_name
optioneel
|
string | Bedrijfsnaam, bij een zakelijke klant. kan leeg zijn (null) · maximaal 255 tekens |
vat_number
optioneel
|
string | Btw-nummer. kan leeg zijn (null) · maximaal 20 tekens |
coc_number
optioneel
|
string | KvK-nummer. kan leeg zijn (null) · maximaal 30 tekens |
Voorbeeldverzoek
curl -X POST "https://app.klantly.com/api/v1/customers" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
-d '{
"email": "jan@example.com",
"name": "Jan de Vries",
"type": "business",
"company_name": "De Vries Bouw",
"city": "Utrecht"
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'customers', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
'json' => [
'email' => 'jan@example.com',
'name' => 'Jan de Vries',
'type' => 'business',
'company_name' => 'De Vries Bouw',
'city' => 'Utrecht',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/customers', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
body: JSON.stringify({
"email": "jan@example.com",
"name": "Jan de Vries",
"type": "business",
"company_name": "De Vries Bouw",
"city": "Utrecht"
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/customers",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
json={
"email": "jan@example.com",
"name": "Jan de Vries",
"type": "business",
"company_name": "De Vries Bouw",
"city": "Utrecht"
},
)
data = response.json()["data"]Antwoord 201
{
"data": {
"object": "customer",
"id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"type": "business",
"status": "lead",
"name": "Jan de Vries",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"company_name": "De Vries Bouw",
"vat_number": "NL123456789B01",
"coc_number": "12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"email_unsubscribed": false,
"converted_at": null,
"last_activity_at": "2026-09-14T10:15:00Z",
"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. -
403
limit_reached— De limiet van het abonnement is bereikt. -
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.
Klant bijwerken
/api/v1/customers/{customer}
Wijzigt alleen de velden die je meestuurt. De status verandert niet via dit endpoint; gebruik daarvoor Lead omzetten naar klant.
- Scope
-
customers.write— Klanten en leads aanmaken en wijzigen
Stuur de ETag mee in If-Match, dan overschrijf je nooit per ongeluk een nieuwere versie.
Padparameters
| Naam | Type | Omschrijving |
|---|---|---|
customer verplicht |
string (uuid) | De id (UUID) van de klant. |
Body (JSON)
| Veld | Type | Omschrijving |
|---|---|---|
email
optioneel
|
string (email) | E-mailadres; uniek binnen je bedrijf. maximaal 255 tekens · uniek binnen je bedrijf |
type
optioneel
|
string | individual (particulier) of business (bedrijf). een van: individual, business |
name
optioneel
|
string | Naam van de contactpersoon. kan leeg zijn (null) · maximaal 255 tekens |
phone
optioneel
|
string | Telefoonnummer. kan leeg zijn (null) · maximaal 255 tekens |
address
optioneel
|
string | Straat en huisnummer. kan leeg zijn (null) · maximaal 255 tekens |
city
optioneel
|
string | Plaats. kan leeg zijn (null) · maximaal 255 tekens |
postal_code
optioneel
|
string | Postcode. kan leeg zijn (null) · maximaal 64 tekens |
country
optioneel
|
string | Land. kan leeg zijn (null) · minimaal 2 tekens · maximaal 2 tekens |
company_name
optioneel
|
string | Bedrijfsnaam, bij een zakelijke klant. kan leeg zijn (null) · maximaal 255 tekens |
vat_number
optioneel
|
string | Btw-nummer. kan leeg zijn (null) · maximaal 20 tekens |
coc_number
optioneel
|
string | KvK-nummer. kan leeg zijn (null) · maximaal 30 tekens |
Voorbeeldverzoek
curl -X PATCH "https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "+31 6 12345678",
"city": "Amersfoort"
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('PATCH', 'customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', [
'json' => [
'phone' => '+31 6 12345678',
'city' => 'Amersfoort',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"phone": "+31 6 12345678",
"city": "Amersfoort"
}),
});
const { data } = await response.json();import os
import requests
response = requests.patch(
"https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
json={
"phone": "+31 6 12345678",
"city": "Amersfoort"
},
)
data = response.json()["data"]Antwoord 200
{
"data": {
"object": "customer",
"id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"type": "business",
"status": "lead",
"name": "Jan de Vries",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"company_name": "De Vries Bouw",
"vat_number": "NL123456789B01",
"coc_number": "12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"email_unsubscribed": false,
"converted_at": null,
"last_activity_at": "2026-09-14T10:15:00Z",
"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.
Lead omzetten naar klant
/api/v1/customers/{customer}/convert
Zet een lead om naar klant. Is het al een klant, dan verandert er niets en krijg je de klant gewoon terug.
- Scope
-
customers.write— Klanten en leads aanmaken en wijzigen
Stuur een Idempotency-Key mee, dan maakt een nieuwe poging na een time-out geen dubbel record.
Padparameters
| Naam | Type | Omschrijving |
|---|---|---|
customer verplicht |
string (uuid) | De id (UUID) van de klant. |
Voorbeeldverzoek
curl -X POST "https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/convert" \
-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', 'customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/convert', [
'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/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/convert', {
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/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/convert",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
)
data = response.json()["data"]Antwoord 200
{
"data": {
"object": "customer",
"id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"type": "business",
"status": "lead",
"name": "Jan de Vries",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"company_name": "De Vries Bouw",
"vat_number": "NL123456789B01",
"coc_number": "12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"email_unsubscribed": false,
"converted_at": null,
"last_activity_at": "2026-09-14T10:15:00Z",
"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. -
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.
Tijdlijn van een klant
/api/v1/customers/{customer}/activities
De tijdlijn van een klant, nieuwste eerst: offertes, facturen, afspraken, e-mails en meer. Verwijzingen naar gekoppelde records staan onder related.
- Scope
-
customers.read— Klanten en leads lezen
Padparameters
| Naam | Type | Omschrijving |
|---|---|---|
customer verplicht |
string (uuid) | De id (UUID) van de klant. |
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. |
filter[type] |
string | Alleen activiteiten van dit type, bijvoorbeeld quote_sent of invoice_created. maximaal 40 tekens |
Voorbeeldverzoek
curl "https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/activities" \
-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', 'customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/activities');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/activities', {
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/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/activities",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Antwoord 200
Het antwoord is een lijst met cursorpaginering: data bevat de objecten, meta de paginering.
{
"data": [
{
"object": "customer_activity",
"id": "9d3f7c62-3e7a-4f9d-8c4b-5a6e7f8a9ba3",
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"type": "quote_sent",
"title": null,
"description": null,
"related": {
"quote_id": null,
"invoice_id": null,
"appointment_id": null,
"work_order_id": null,
"task_id": null,
"deal_id": null,
"order_id": null,
"conversation_id": null
},
"happened_at": "2026-09-14T10:15:00Z",
"created_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. -
404
not_found— Niet gevonden. -
422
validation_failed— De invoer is ongeldig.
Het object
Alle velden zijn altijd aanwezig; een veld zonder waarde is null.
| Veld | Type | Omschrijving |
|---|---|---|
object |
string | Altijd "customer". |
id |
string (uuid) | Unieke id (UUID). |
type |
string | individual (particulier) of business (bedrijf). een van: individual, business |
status |
string | lead of customer (klant). een van: lead, customer |
name |
string | Naam van de contactpersoon. kan leeg zijn (null) |
email |
string (email) | E-mailadres; uniek binnen je bedrijf. |
phone |
string | Telefoonnummer. kan leeg zijn (null) |
company_name |
string | Bedrijfsnaam, bij een zakelijke klant. kan leeg zijn (null) |
vat_number |
string | Btw-nummer. kan leeg zijn (null) |
coc_number |
string | KvK-nummer. kan leeg zijn (null) |
address |
string | Straat en huisnummer. kan leeg zijn (null) |
postal_code |
string | Postcode. kan leeg zijn (null) |
city |
string | Plaats. kan leeg zijn (null) |
country |
string | Land. kan leeg zijn (null) |
email_unsubscribed |
boolean | Heeft zich afgemeld voor e-mail. |
converted_at |
string (date-time) | Wanneer de lead klant werd. kan leeg zijn (null) |
last_activity_at |
string (date-time) | Laatste activiteit in Klantly. kan leeg zijn (null) |
created_at |
string (date-time) | Aangemaakt op (UTC). |
updated_at |
string (date-time) | Laatst gewijzigd op (UTC). |