Klantly Developers

API-Referenz

Arbeitsaufträge

Arbeitsaufträge mit Positionen und Checkliste: zum Beispiel aus einem ERP erstellen, bearbeiten, den Status ändern und abgeschlossene Aufträge abrufen.

Endpunkte

Arbeitsaufträge auflisten

GET /api/v1/work-orders

Eine Liste von Arbeitsaufträgen, neueste zuerst, mit Positionen, Checkliste und Fotos. Filtern Sie nach Status, Kunde, Benutzer, Termin oder Änderungsdatum. Mit filter[status]=completed und filter[updated_since] holen Sie abgeschlossene Arbeit ab.

Scope
work_orders.read — Arbeitsaufträge lesen, mit Name, Adresse und Kontaktdaten des Kunden
Erforderliche Funktion
work_orders

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 oder updated_at; ein Minuszeichen davor sortiert absteigend. einer von: -created_at, created_at, -updated_at, updated_at · Standard: -created_at
filter[status] string Nur Arbeitsaufträge mit diesem Status. einer von: draft, planned, in_progress, completed, invoiced, cancelled
filter[customer_id] string (uuid) Nur was zu diesem Kunden gehört.
filter[assigned_user_id] string Nur was diesem Benutzer zugewiesen ist (die ID aus Benutzer auflisten).
filter[appointment_id] string (uuid) Nur Arbeitsaufträge zu diesem Termin.
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/work-orders?filter[status]=completed&sort=-updated_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', 'work-orders', [
    'query' => [
        'filter[status]' => 'completed',
        'sort' => '-updated_at',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/work-orders?filter[status]=completed&sort=-updated_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/work-orders",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
    },
    params={
        "filter[status]": "completed",
        "sort": "-updated_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": "work_order",
      "id": "9d3f8328-9ed0-4f5d-8cab-b0cedfe0f1a9",
      "number": "WB-2026-00042",
      "status": "planned",
      "title": "Onderhoud cv-ketel",
      "type": "onderhoud",
      "location": null,
      "description": null,
      "work_performed": null,
      "customer_notes": null,
      "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
      "customer": {
        "type": "business",
        "name": "De Vries Bouw",
        "email": "jan@example.com",
        "phone": "+31 6 12345678",
        "address": "Dorpsstraat 1",
        "postal_code": "3511 AB",
        "city": "Utrecht",
        "country": "NL"
      },
      "deal_id": null,
      "appointment_id": null,
      "quote_id": null,
      "invoice_id": null,
      "assigned_user_id": "usr_0k3j9x21m4zq8p",
      "language": "nl",
      "currency": "EUR",
      "subtotal": "90.00",
      "tax_amount": "18.90",
      "total": "108.90",
      "scheduled_at": "2026-10-01T08:00:00Z",
      "started_at": null,
      "completed_at": null,
      "sent_at": null,
      "signature": {
        "is_signed": false,
        "signed_by_name": null,
        "signed_at": null
      },
      "items": [
        {
          "object": "work_order_item",
          "id": "9d3f856a-b0f2-4b7f-8ecd-d2e0f1a2b3cb",
          "type": "labor",
          "name": "Arbeid",
          "description": null,
          "sku": null,
          "quantity": "2.00",
          "unit": "uur",
          "unit_price": "45.00",
          "discount_percentage": "0.00",
          "discount_amount": "0.00",
          "line_total": "90.00",
          "is_taxable": true,
          "tax_rate": "21.00",
          "minutes": 120
        }
      ],
      "checklist": [
        {
          "object": "work_order_checklist_item",
          "id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dc",
          "label": "Druk gecontroleerd",
          "checked": false,
          "required": true,
          "note": null
        }
      ],
      "photos": [],
      "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.

Arbeitsauftrag abrufen

GET /api/v1/work-orders/{work_order}

Ein Arbeitsauftrag nach ID, mit Positionen, Checkliste, Fotos (nur die Daten) und dem Stand der Unterschrift.

Scope
work_orders.read — Arbeitsaufträge lesen, mit Name, Adresse und Kontaktdaten des Kunden
Erforderliche Funktion
work_orders

Pfadparameter

NameTypBeschreibung
work_order erforderlich string (uuid) Die ID (UUID) des Arbeitsauftrags.

Beispielanfrage

cURL
curl "https://app.klantly.com/api/v1/work-orders/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', 'work-orders/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70');

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/work-orders/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/work-orders/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
    },
)
data = response.json()["data"]

Antwort 200

Beispielantwort
{
  "data": {
    "object": "work_order",
    "id": "9d3f8328-9ed0-4f5d-8cab-b0cedfe0f1a9",
    "number": "WB-2026-00042",
    "status": "planned",
    "title": "Onderhoud cv-ketel",
    "type": "onderhoud",
    "location": null,
    "description": null,
    "work_performed": null,
    "customer_notes": null,
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "customer": {
      "type": "business",
      "name": "De Vries Bouw",
      "email": "jan@example.com",
      "phone": "+31 6 12345678",
      "address": "Dorpsstraat 1",
      "postal_code": "3511 AB",
      "city": "Utrecht",
      "country": "NL"
    },
    "deal_id": null,
    "appointment_id": null,
    "quote_id": null,
    "invoice_id": null,
    "assigned_user_id": "usr_0k3j9x21m4zq8p",
    "language": "nl",
    "currency": "EUR",
    "subtotal": "90.00",
    "tax_amount": "18.90",
    "total": "108.90",
    "scheduled_at": "2026-10-01T08:00:00Z",
    "started_at": null,
    "completed_at": null,
    "sent_at": null,
    "signature": {
      "is_signed": false,
      "signed_by_name": null,
      "signed_at": null
    },
    "items": [
      {
        "object": "work_order_item",
        "id": "9d3f856a-b0f2-4b7f-8ecd-d2e0f1a2b3cb",
        "type": "labor",
        "name": "Arbeid",
        "description": null,
        "sku": null,
        "quantity": "2.00",
        "unit": "uur",
        "unit_price": "45.00",
        "discount_percentage": "0.00",
        "discount_amount": "0.00",
        "line_total": "90.00",
        "is_taxable": true,
        "tax_rate": "21.00",
        "minutes": 120
      }
    ],
    "checklist": [
      {
        "object": "work_order_checklist_item",
        "id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dc",
        "label": "Druk gecontroleerd",
        "checked": false,
        "required": true,
        "note": null
      }
    ],
    "photos": [],
    "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.

Arbeitsauftrag erstellen

POST /api/v1/work-orders

Erstellt einen Arbeitsauftrag für einen Kunden, als Entwurf oder geplant. Klantly vergibt eine Nummer und berechnet die Summen; Name, Adresse und Kontaktdaten kommen vom Kunden.

Scope
work_orders.write — Arbeitsaufträge erstellen und bearbeiten sowie den Status ändern (Abschließen kann eine Bewertungsanfrage senden)
Erforderliche Funktion
work_orders

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. Beim Erstellen erforderlich; Name, Adresse und Kontaktdaten kommen vom Kunden.
status optional string draft (Entwurf), planned (geplant), in_progress (in Arbeit), completed (abgeschlossen), invoiced (abgerechnet) oder cancelled (storniert). Beim Erstellen draft oder planned. einer von: draft, planned
title optional string Titel. kann leer sein (null) · höchstens 255 Zeichen
type optional string Art der Arbeit, zum Beispiel Installation, Reparatur oder Wartung. kann leer sein (null) · höchstens 64 Zeichen
location optional string Wo die Arbeit stattfindet, wenn nicht an der Adresse des Kunden. kann leer sein (null) · höchstens 255 Zeichen
description optional string Beschreibung der Arbeit oder der Beschwerde. kann leer sein (null) · höchstens 20000 Zeichen
work_performed optional string Was erledigt wurde. kann leer sein (null) · höchstens 20000 Zeichen
customer_notes optional string Hinweise für den Kunden; stehen auf dem Arbeitsauftrag. kann leer sein (null) · höchstens 20000 Zeichen
scheduled_at optional string (date-time) Wann die Arbeit geplant ist (UTC). Bei der Eingabe: ISO 8601 mit Zeitzone. kann leer sein (null)
assigned_user_id optional string Der Techniker oder Benutzer, der die Arbeit erledigt, oder null. kann leer sein (null)
appointment_id optional string (uuid) Der Termin, zu dem der Arbeitsauftrag gehört, oder null. kann leer sein (null)
quote_id optional string (uuid) Das Angebot, aus dem der Arbeitsauftrag stammt, oder null. kann leer sein (null)
language optional string Sprache des Arbeitsauftrags: nl, en, de oder fr. einer von: nl, en, de, fr
items optional array Die Positionen (höchstens 200). Bei der Eingabe: eine Liste mit pro Position name (erforderlich) und optional type, description, sku, quantity, unit, unit_price, discount_percentage, discount_amount, tax_rate, is_taxable und minutes; die Liste ersetzt alle Positionen.
checklist optional array Die Checkliste (höchstens 200 Punkte). Bei der Eingabe: pro Punkt label (erforderlich) und optional checked, required und note; die Liste ersetzt die ganze Checkliste.

Beispielanfrage

cURL
curl -X POST "https://app.klantly.com/api/v1/work-orders" \
  -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": "Onderhoud cv-ketel",
  "status": "planned",
  "scheduled_at": "2026-10-01T08:00:00Z",
  "items": [
    {
      "type": "labor",
      "name": "Arbeid",
      "quantity": 2,
      "unit_price": "45.00"
    }
  ]
}'
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('POST', 'work-orders', [
    'headers' => [
        'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
    ],
    'json' => [
        'customer_id' => '9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70',
        'title' => 'Onderhoud cv-ketel',
        'status' => 'planned',
        'scheduled_at' => '2026-10-01T08:00:00Z',
        'items' => [
            0 => [
                'type' => 'labor',
                'name' => 'Arbeid',
                'quantity' => 2,
                'unit_price' => '45.00',
            ],
        ],
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/work-orders', {
  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": "Onderhoud cv-ketel",
  "status": "planned",
  "scheduled_at": "2026-10-01T08:00:00Z",
  "items": [
    {
      "type": "labor",
      "name": "Arbeid",
      "quantity": 2,
      "unit_price": "45.00"
    }
  ]
}),
});

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

import requests

response = requests.post(
    "https://app.klantly.com/api/v1/work-orders",
    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": "Onderhoud cv-ketel",
        "status": "planned",
        "scheduled_at": "2026-10-01T08:00:00Z",
        "items": [
            {
                "type": "labor",
                "name": "Arbeid",
                "quantity": 2,
                "unit_price": "45.00"
            }
        ]
    },
)
data = response.json()["data"]

Antwort 201

Beispielantwort
{
  "data": {
    "object": "work_order",
    "id": "9d3f8328-9ed0-4f5d-8cab-b0cedfe0f1a9",
    "number": "WB-2026-00042",
    "status": "planned",
    "title": "Onderhoud cv-ketel",
    "type": "onderhoud",
    "location": null,
    "description": null,
    "work_performed": null,
    "customer_notes": null,
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "customer": {
      "type": "business",
      "name": "De Vries Bouw",
      "email": "jan@example.com",
      "phone": "+31 6 12345678",
      "address": "Dorpsstraat 1",
      "postal_code": "3511 AB",
      "city": "Utrecht",
      "country": "NL"
    },
    "deal_id": null,
    "appointment_id": null,
    "quote_id": null,
    "invoice_id": null,
    "assigned_user_id": "usr_0k3j9x21m4zq8p",
    "language": "nl",
    "currency": "EUR",
    "subtotal": "90.00",
    "tax_amount": "18.90",
    "total": "108.90",
    "scheduled_at": "2026-10-01T08:00:00Z",
    "started_at": null,
    "completed_at": null,
    "sent_at": null,
    "signature": {
      "is_signed": false,
      "signed_by_name": null,
      "signed_at": null
    },
    "items": [
      {
        "object": "work_order_item",
        "id": "9d3f856a-b0f2-4b7f-8ecd-d2e0f1a2b3cb",
        "type": "labor",
        "name": "Arbeid",
        "description": null,
        "sku": null,
        "quantity": "2.00",
        "unit": "uur",
        "unit_price": "45.00",
        "discount_percentage": "0.00",
        "discount_amount": "0.00",
        "line_total": "90.00",
        "is_taxable": true,
        "tax_rate": "21.00",
        "minutes": 120
      }
    ],
    "checklist": [
      {
        "object": "work_order_checklist_item",
        "id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dc",
        "label": "Druk gecontroleerd",
        "checked": false,
        "required": true,
        "note": null
      }
    ],
    "photos": [],
    "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.

Arbeitsauftrag bearbeiten

PATCH /api/v1/work-orders/{work_order}

Ändert nur die Felder, die Sie mitsenden. items und checklist ersetzen die Positionen und die Checkliste als Ganzes; die Positionen erhalten dabei neue IDs. Eine Position und die Summe dürfen 99.999.999,99 nicht übersteigen. Ein abgerechneter Arbeitsauftrag kann nicht mehr geändert werden.

Scope
work_orders.write — Arbeitsaufträge erstellen und bearbeiten sowie den Status ändern (Abschließen kann eine Bewertungsanfrage senden)
Erforderliche Funktion
work_orders

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

Pfadparameter

NameTypBeschreibung
work_order erforderlich string (uuid) Die ID (UUID) des Arbeitsauftrags.

Body (JSON)

FeldTypBeschreibung
title optional string Titel. kann leer sein (null) · höchstens 255 Zeichen
type optional string Art der Arbeit, zum Beispiel Installation, Reparatur oder Wartung. kann leer sein (null) · höchstens 64 Zeichen
location optional string Wo die Arbeit stattfindet, wenn nicht an der Adresse des Kunden. kann leer sein (null) · höchstens 255 Zeichen
description optional string Beschreibung der Arbeit oder der Beschwerde. kann leer sein (null) · höchstens 20000 Zeichen
work_performed optional string Was erledigt wurde. kann leer sein (null) · höchstens 20000 Zeichen
customer_notes optional string Hinweise für den Kunden; stehen auf dem Arbeitsauftrag. kann leer sein (null) · höchstens 20000 Zeichen
scheduled_at optional string (date-time) Wann die Arbeit geplant ist (UTC). Bei der Eingabe: ISO 8601 mit Zeitzone. kann leer sein (null)
assigned_user_id optional string Der Techniker oder Benutzer, der die Arbeit erledigt, oder null. kann leer sein (null)
appointment_id optional string (uuid) Der Termin, zu dem der Arbeitsauftrag gehört, oder null. kann leer sein (null)
quote_id optional string (uuid) Das Angebot, aus dem der Arbeitsauftrag stammt, oder null. kann leer sein (null)
language optional string Sprache des Arbeitsauftrags: nl, en, de oder fr. einer von: nl, en, de, fr
items optional array Die Positionen (höchstens 200). Bei der Eingabe: eine Liste mit pro Position name (erforderlich) und optional type, description, sku, quantity, unit, unit_price, discount_percentage, discount_amount, tax_rate, is_taxable und minutes; die Liste ersetzt alle Positionen.
checklist optional array Die Checkliste (höchstens 200 Punkte). Bei der Eingabe: pro Punkt label (erforderlich) und optional checked, required und note; die Liste ersetzt die ganze Checkliste.

Beispielanfrage

cURL
curl -X PATCH "https://app.klantly.com/api/v1/work-orders/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "work_performed": "Filter vervangen en de ketel ontlucht."
}'
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('PATCH', 'work-orders/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', [
    'json' => [
        'work_performed' => 'Filter vervangen en de ketel ontlucht.',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/work-orders/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
  "work_performed": "Filter vervangen en de ketel ontlucht."
}),
});

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

import requests

response = requests.patch(
    "https://app.klantly.com/api/v1/work-orders/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
    },
    json={
        "work_performed": "Filter vervangen en de ketel ontlucht."
    },
)
data = response.json()["data"]

Antwort 200

Beispielantwort
{
  "data": {
    "object": "work_order",
    "id": "9d3f8328-9ed0-4f5d-8cab-b0cedfe0f1a9",
    "number": "WB-2026-00042",
    "status": "planned",
    "title": "Onderhoud cv-ketel",
    "type": "onderhoud",
    "location": null,
    "description": null,
    "work_performed": null,
    "customer_notes": null,
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "customer": {
      "type": "business",
      "name": "De Vries Bouw",
      "email": "jan@example.com",
      "phone": "+31 6 12345678",
      "address": "Dorpsstraat 1",
      "postal_code": "3511 AB",
      "city": "Utrecht",
      "country": "NL"
    },
    "deal_id": null,
    "appointment_id": null,
    "quote_id": null,
    "invoice_id": null,
    "assigned_user_id": "usr_0k3j9x21m4zq8p",
    "language": "nl",
    "currency": "EUR",
    "subtotal": "90.00",
    "tax_amount": "18.90",
    "total": "108.90",
    "scheduled_at": "2026-10-01T08:00:00Z",
    "started_at": null,
    "completed_at": null,
    "sent_at": null,
    "signature": {
      "is_signed": false,
      "signed_by_name": null,
      "signed_at": null
    },
    "items": [
      {
        "object": "work_order_item",
        "id": "9d3f856a-b0f2-4b7f-8ecd-d2e0f1a2b3cb",
        "type": "labor",
        "name": "Arbeid",
        "description": null,
        "sku": null,
        "quantity": "2.00",
        "unit": "uur",
        "unit_price": "45.00",
        "discount_percentage": "0.00",
        "discount_amount": "0.00",
        "line_total": "90.00",
        "is_taxable": true,
        "tax_rate": "21.00",
        "minutes": 120
      }
    ],
    "checklist": [
      {
        "object": "work_order_checklist_item",
        "id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dc",
        "label": "Druk gecontroleerd",
        "checked": false,
        "required": true,
        "note": null
      }
    ],
    "photos": [],
    "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.

Status eines Arbeitsauftrags ändern

POST /api/v1/work-orders/{work_order}/status

Setzt den Arbeitsauftrag auf Entwurf, geplant, in Arbeit, abgeschlossen oder storniert. Bei in Arbeit und abgeschlossen werden started_at und completed_at gesetzt. Wie in der App kann das Abschließen dem Kunden eine Bewertungsanfrage senden, wenn das Unternehmen das eingerichtet hat. Abgerechnet setzt nur Klantly selbst.

Scope
work_orders.write — Arbeitsaufträge erstellen und bearbeiten sowie den Status ändern (Abschließen kann eine Bewertungsanfrage senden)
Erforderliche Funktion
work_orders

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

Pfadparameter

NameTypBeschreibung
work_order erforderlich string (uuid) Die ID (UUID) des Arbeitsauftrags.

Body (JSON)

FeldTypBeschreibung
status erforderlich string draft (Entwurf), planned (geplant), in_progress (in Arbeit), completed (abgeschlossen), invoiced (abgerechnet) oder cancelled (storniert). Beim Erstellen draft oder planned. einer von: draft, planned, in_progress, completed, cancelled

Beispielanfrage

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

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

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

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

import requests

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

Antwort 200

Beispielantwort
{
  "data": {
    "object": "work_order",
    "id": "9d3f8328-9ed0-4f5d-8cab-b0cedfe0f1a9",
    "number": "WB-2026-00042",
    "status": "planned",
    "title": "Onderhoud cv-ketel",
    "type": "onderhoud",
    "location": null,
    "description": null,
    "work_performed": null,
    "customer_notes": null,
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "customer": {
      "type": "business",
      "name": "De Vries Bouw",
      "email": "jan@example.com",
      "phone": "+31 6 12345678",
      "address": "Dorpsstraat 1",
      "postal_code": "3511 AB",
      "city": "Utrecht",
      "country": "NL"
    },
    "deal_id": null,
    "appointment_id": null,
    "quote_id": null,
    "invoice_id": null,
    "assigned_user_id": "usr_0k3j9x21m4zq8p",
    "language": "nl",
    "currency": "EUR",
    "subtotal": "90.00",
    "tax_amount": "18.90",
    "total": "108.90",
    "scheduled_at": "2026-10-01T08:00:00Z",
    "started_at": null,
    "completed_at": null,
    "sent_at": null,
    "signature": {
      "is_signed": false,
      "signed_by_name": null,
      "signed_at": null
    },
    "items": [
      {
        "object": "work_order_item",
        "id": "9d3f856a-b0f2-4b7f-8ecd-d2e0f1a2b3cb",
        "type": "labor",
        "name": "Arbeid",
        "description": null,
        "sku": null,
        "quantity": "2.00",
        "unit": "uur",
        "unit_price": "45.00",
        "discount_percentage": "0.00",
        "discount_amount": "0.00",
        "line_total": "90.00",
        "is_taxable": true,
        "tax_rate": "21.00",
        "minutes": 120
      }
    ],
    "checklist": [
      {
        "object": "work_order_checklist_item",
        "id": "9d3f868b-c1a3-4c8a-9fde-e3f1a2b3c4dc",
        "label": "Druk gecontroleerd",
        "checked": false,
        "required": true,
        "note": null
      }
    ],
    "photos": [],
    "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.

Arbeitsauftrag löschen

DELETE /api/v1/work-orders/{work_order}

Löscht den Arbeitsauftrag. Ein abgerechneter Arbeitsauftrag kann nicht gelöscht werden.

Scope
work_orders.delete — Arbeitsaufträge löschen
Erforderliche Funktion
work_orders

Pfadparameter

NameTypBeschreibung
work_order erforderlich string (uuid) Die ID (UUID) des Arbeitsauftrags.

Beispielanfrage

cURL
curl -X DELETE "https://app.klantly.com/api/v1/work-orders/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', 'work-orders/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70');

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/work-orders/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/work-orders/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 „work_order“.
id string (uuid) Eindeutige ID (UUID).
number string Nummer des Arbeitsauftrags, zum Beispiel WB-2026-00042; vergibt Klantly selbst.
status string draft (Entwurf), planned (geplant), in_progress (in Arbeit), completed (abgeschlossen), invoiced (abgerechnet) oder cancelled (storniert). Beim Erstellen draft oder planned. einer von: draft, planned, in_progress, completed, invoiced, cancelled
title string Titel. kann leer sein (null)
type string Art der Arbeit, zum Beispiel Installation, Reparatur oder Wartung. kann leer sein (null)
location string Wo die Arbeit stattfindet, wenn nicht an der Adresse des Kunden. kann leer sein (null)
description string Beschreibung der Arbeit oder der Beschwerde. kann leer sein (null)
work_performed string Was erledigt wurde. kann leer sein (null)
customer_notes string Hinweise für den Kunden; stehen auf dem Arbeitsauftrag. kann leer sein (null)
customer_id string (uuid) Der Kunde. Beim Erstellen erforderlich; Name, Adresse und Kontaktdaten kommen vom Kunden. kann leer sein (null)
customer object Die Kundendaten auf dem Arbeitsauftrag, wie sie beim Erstellen waren.
customer.type string individual (Privatperson) oder business (Unternehmen). kann leer sein (null)
customer.name string Name; bei einem Unternehmen der Firmenname. kann leer sein (null)
customer.email string E-Mail-Adresse. kann leer sein (null)
customer.phone string Telefonnummer. kann leer sein (null)
customer.address string Straße und Hausnummer. kann leer sein (null)
customer.postal_code string Postleitzahl. kann leer sein (null)
customer.city string Ort. kann leer sein (null)
customer.country string Land. kann leer sein (null)
deal_id string (uuid) Der Deal auf dem Pipeline-Board, oder null. kann leer sein (null)
appointment_id string (uuid) Der Termin, zu dem der Arbeitsauftrag gehört, oder null. kann leer sein (null)
quote_id string (uuid) Das Angebot, aus dem der Arbeitsauftrag stammt, oder null. kann leer sein (null)
invoice_id string (uuid) Die Rechnung des Arbeitsauftrags, oder null. kann leer sein (null)
assigned_user_id string Der Techniker oder Benutzer, der die Arbeit erledigt, oder null. kann leer sein (null)
language string Sprache des Arbeitsauftrags: nl, en, de oder fr. einer von: nl, en, de, fr
currency string Immer „EUR“.
subtotal string Summe ohne Umsatzsteuer, als Text mit zwei Dezimalstellen.
tax_amount string Umsatzsteuerbetrag.
total string Summe inklusive Umsatzsteuer.
scheduled_at string (date-time) Wann die Arbeit geplant ist (UTC). Bei der Eingabe: ISO 8601 mit Zeitzone. kann leer sein (null)
started_at string (date-time) Wann die Arbeit begann. kann leer sein (null)
completed_at string (date-time) Wann die Arbeit fertig war. kann leer sein (null)
sent_at string (date-time) Wann der Arbeitsauftrag an den Kunden gesendet wurde. kann leer sein (null)
signature object Die Unterschrift des Kunden (nur die Daten, kein Bild).
signature.is_signed boolean Ob der Arbeitsauftrag unterschrieben ist.
signature.signed_by_name string Name der Person, die unterschrieben hat. kann leer sein (null)
signature.signed_at string (date-time) Wann unterschrieben wurde. kann leer sein (null)
items array<object> Die Positionen (höchstens 200). Bei der Eingabe: eine Liste mit pro Position name (erforderlich) und optional type, description, sku, quantity, unit, unit_price, discount_percentage, discount_amount, tax_rate, is_taxable und minutes; die Liste ersetzt alle Positionen.
items.object string Immer „work_order_item“.
items.id string (uuid) ID der Position. Ändert sich jedes Mal, wenn Sie items senden (die Positionen werden ersetzt).
items.type string labor (Arbeit), material (Material) oder other. einer von: labor, material, other
items.name string Bezeichnung auf dem Arbeitsauftrag.
items.description string Erläuterung. kann leer sein (null)
items.sku string Artikelnummer. kann leer sein (null)
items.quantity string Menge.
items.unit string Einheit, zum Beispiel Stunde oder Stück. kann leer sein (null)
items.unit_price string Preis pro Einheit ohne Umsatzsteuer.
items.discount_percentage string Rabatt in Prozent.
items.discount_amount string Fester Rabatt auf die Position ohne Umsatzsteuer; zählt nur, wenn discount_percentage 0 ist.
items.line_total string Positionssumme ohne Umsatzsteuer; berechnet Klantly.
items.is_taxable boolean Ob die Position der Umsatzsteuer unterliegt.
items.tax_rate string Steuersatz in Prozent (Standard 21, auch wenn das Unternehmen einen anderen Satz verwendet: senden Sie ihn dann mit).
items.minutes integer Gearbeitete Minuten, bei Arbeit. kann leer sein (null)
checklist array<object> Die Checkliste (höchstens 200 Punkte). Bei der Eingabe: pro Punkt label (erforderlich) und optional checked, required und note; die Liste ersetzt die ganze Checkliste.
checklist.object string Immer „work_order_checklist_item“.
checklist.id string (uuid) ID des Punkts.
checklist.label string Der Punkt, zum Beispiel „Druck geprüft“.
checklist.checked boolean Abgehakt.
checklist.required boolean Muss abgehakt werden.
checklist.note string Anmerkung zum Punkt. kann leer sein (null)
photos array<object> Die Fotos zum Arbeitsauftrag (nur die Daten; die Dateien sind noch nicht in der API).
photos.object string Immer „work_order_photo“.
photos.id string (uuid) ID des Fotos.
photos.kind string before (vorher), after (nachher) oder other. kann leer sein (null) · einer von: before, after, other
photos.caption string Bildunterschrift. kann leer sein (null)
photos.created_at string (date-time) Hochgeladen am (UTC).
created_at string (date-time) Erstellt am (UTC).
updated_at string (date-time) Zuletzt geändert am (UTC).