Klantly Developers

API-referentie

Werkbonnen

Werkbonnen met regels en checklist: aanmaken vanuit bijvoorbeeld een ERP, bijwerken, de status wijzigen en afgeronde werkbonnen ophalen.

Endpoints

Werkbonnen opvragen

GET /api/v1/work-orders

Een lijst van werkbonnen, nieuwste eerst, met regels, checklist en foto’s. Filter op status, klant, gebruiker, afspraak of wijzigingsdatum. Met filter[status]=completed en filter[updated_since] haal je afgerond werk op.

Scope
work_orders.read — Werkbonnen lezen, met naam, adres en contactgegevens van de klant
Vereiste functie
work_orders

Queryparameters

NaamTypeOmschrijving
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 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 werkbonnen met deze status. een van: draft, planned, in_progress, completed, invoiced, cancelled
filter[customer_id] string (uuid) Alleen wat bij deze klant hoort.
filter[assigned_user_id] string Alleen wat aan deze gebruiker is toegewezen (de id uit Gebruikers opvragen).
filter[appointment_id] string (uuid) Alleen werkbonnen bij deze afspraak.
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
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"]

Antwoord 200

Het antwoord is een lijst met cursorpaginering: data bevat de objecten, meta de paginering.

Voorbeeldantwoord
{
  "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
  }
}

Mogelijke fouten

Daarnaast kan elk endpoint de algemene fouten geven, zoals een ongeldige sleutel of een bereikte limiet. Bekijk alle foutcodes.

Werkbon ophalen

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

Eén werkbon op id, met regels, checklist, foto’s (alleen de gegevens) en de stand van de handtekening.

Scope
work_orders.read — Werkbonnen lezen, met naam, adres en contactgegevens van de klant
Vereiste functie
work_orders

Padparameters

NaamTypeOmschrijving
work_order verplicht string (uuid) De id (UUID) van de werkbon.

Voorbeeldverzoek

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

Antwoord 200

Voorbeeldantwoord
{
  "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"
  }
}

Mogelijke fouten

Daarnaast kan elk endpoint de algemene fouten geven, zoals een ongeldige sleutel of een bereikte limiet. Bekijk alle foutcodes.

Werkbon aanmaken

POST /api/v1/work-orders

Maakt een werkbon aan bij een klant, als concept of ingepland. Klantly geeft hem een nummer en rekent de totalen uit; naam, adres en contact komen van de klant.

Scope
work_orders.write — Werkbonnen aanmaken en wijzigen, en de status aanpassen (afronden kan een reviewverzoek sturen)
Vereiste functie
work_orders

Stuur een Idempotency-Key mee, dan maakt een nieuwe poging na een time-out geen dubbel record.

Body (JSON)

VeldTypeOmschrijving
customer_id verplicht string (uuid) De klant. Verplicht bij aanmaken; naam, adres en contact komen van de klant.
status optioneel string draft (concept), planned (ingepland), in_progress (bezig), completed (afgerond), invoiced (gefactureerd) of cancelled (geannuleerd). Bij aanmaken draft of planned. een van: draft, planned
title optioneel string Titel. kan leeg zijn (null) · maximaal 255 tekens
type optioneel string Soort werk, bijvoorbeeld installatie, reparatie of onderhoud. kan leeg zijn (null) · maximaal 64 tekens
location optioneel string Waar het werk plaatsvindt, als dat niet het adres van de klant is. kan leeg zijn (null) · maximaal 255 tekens
description optioneel string Omschrijving van het werk of de klacht. kan leeg zijn (null) · maximaal 20000 tekens
work_performed optioneel string Wat er is gedaan. kan leeg zijn (null) · maximaal 20000 tekens
customer_notes optioneel string Opmerkingen voor de klant; staan op de werkbon. kan leeg zijn (null) · maximaal 20000 tekens
scheduled_at optioneel string (date-time) Wanneer het werk gepland staat (UTC). Bij invoer: ISO 8601 mét tijdzone. kan leeg zijn (null)
assigned_user_id optioneel string De monteur of gebruiker die het werk doet, of null. kan leeg zijn (null)
appointment_id optioneel string (uuid) De afspraak waar de werkbon bij hoort, of null. kan leeg zijn (null)
quote_id optioneel string (uuid) De offerte waar de werkbon uit komt, of null. kan leeg zijn (null)
language optioneel string Taal van de werkbon: nl, en, de of fr. een van: nl, en, de, fr
items optioneel array De regels (maximaal 200). Bij invoer: een lijst met per regel name (verplicht) en optioneel type, description, sku, quantity, unit, unit_price, discount_percentage, discount_amount, tax_rate, is_taxable en minutes; de lijst vervangt alle regels.
checklist optioneel array De checklist (maximaal 200 punten). Bij invoer: per punt label (verplicht) en optioneel checked, required en note; de lijst vervangt de hele checklist.

Voorbeeldverzoek

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

Antwoord 201

Voorbeeldantwoord
{
  "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"
  }
}

Mogelijke fouten

Daarnaast kan elk endpoint de algemene fouten geven, zoals een ongeldige sleutel of een bereikte limiet. Bekijk alle foutcodes.

Werkbon bijwerken

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

Wijzigt alleen de velden die je meestuurt. items en checklist vervangen de regels en de checklist als geheel; de regels krijgen daarbij nieuwe id's. Een regel en het totaal mogen niet boven 99.999.999,99 uitkomen. Een gefactureerde werkbon kan niet meer veranderen.

Scope
work_orders.write — Werkbonnen aanmaken en wijzigen, en de status aanpassen (afronden kan een reviewverzoek sturen)
Vereiste functie
work_orders

Stuur de ETag mee in If-Match, dan overschrijf je nooit per ongeluk een nieuwere versie.

Padparameters

NaamTypeOmschrijving
work_order verplicht string (uuid) De id (UUID) van de werkbon.

Body (JSON)

VeldTypeOmschrijving
title optioneel string Titel. kan leeg zijn (null) · maximaal 255 tekens
type optioneel string Soort werk, bijvoorbeeld installatie, reparatie of onderhoud. kan leeg zijn (null) · maximaal 64 tekens
location optioneel string Waar het werk plaatsvindt, als dat niet het adres van de klant is. kan leeg zijn (null) · maximaal 255 tekens
description optioneel string Omschrijving van het werk of de klacht. kan leeg zijn (null) · maximaal 20000 tekens
work_performed optioneel string Wat er is gedaan. kan leeg zijn (null) · maximaal 20000 tekens
customer_notes optioneel string Opmerkingen voor de klant; staan op de werkbon. kan leeg zijn (null) · maximaal 20000 tekens
scheduled_at optioneel string (date-time) Wanneer het werk gepland staat (UTC). Bij invoer: ISO 8601 mét tijdzone. kan leeg zijn (null)
assigned_user_id optioneel string De monteur of gebruiker die het werk doet, of null. kan leeg zijn (null)
appointment_id optioneel string (uuid) De afspraak waar de werkbon bij hoort, of null. kan leeg zijn (null)
quote_id optioneel string (uuid) De offerte waar de werkbon uit komt, of null. kan leeg zijn (null)
language optioneel string Taal van de werkbon: nl, en, de of fr. een van: nl, en, de, fr
items optioneel array De regels (maximaal 200). Bij invoer: een lijst met per regel name (verplicht) en optioneel type, description, sku, quantity, unit, unit_price, discount_percentage, discount_amount, tax_rate, is_taxable en minutes; de lijst vervangt alle regels.
checklist optioneel array De checklist (maximaal 200 punten). Bij invoer: per punt label (verplicht) en optioneel checked, required en note; de lijst vervangt de hele checklist.

Voorbeeldverzoek

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

Antwoord 200

Voorbeeldantwoord
{
  "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"
  }
}

Mogelijke fouten

Daarnaast kan elk endpoint de algemene fouten geven, zoals een ongeldige sleutel of een bereikte limiet. Bekijk alle foutcodes.

Status van een werkbon wijzigen

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

Zet de werkbon op concept, ingepland, bezig, afgerond of geannuleerd. Bij bezig en afgerond worden started_at en completed_at gezet. Afronden kan, net als in de app, een reviewverzoek naar de klant sturen als het bedrijf dat heeft ingesteld. Gefactureerd zet alleen Klantly zelf.

Scope
work_orders.write — Werkbonnen aanmaken en wijzigen, en de status aanpassen (afronden kan een reviewverzoek sturen)
Vereiste functie
work_orders

Stuur een Idempotency-Key mee, dan maakt een nieuwe poging na een time-out geen dubbel record.

Padparameters

NaamTypeOmschrijving
work_order verplicht string (uuid) De id (UUID) van de werkbon.

Body (JSON)

VeldTypeOmschrijving
status verplicht string draft (concept), planned (ingepland), in_progress (bezig), completed (afgerond), invoiced (gefactureerd) of cancelled (geannuleerd). Bij aanmaken draft of planned. een van: draft, planned, in_progress, completed, cancelled

Voorbeeldverzoek

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

Antwoord 200

Voorbeeldantwoord
{
  "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"
  }
}

Mogelijke fouten

Daarnaast kan elk endpoint de algemene fouten geven, zoals een ongeldige sleutel of een bereikte limiet. Bekijk alle foutcodes.

Werkbon verwijderen

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

Verwijdert de werkbon. Een gefactureerde werkbon kan niet worden verwijderd.

Scope
work_orders.delete — Werkbonnen verwijderen
Vereiste functie
work_orders

Padparameters

NaamTypeOmschrijving
work_order verplicht string (uuid) De id (UUID) van de werkbon.

Voorbeeldverzoek

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

Antwoord 200

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

Mogelijke fouten

Daarnaast kan elk endpoint de algemene fouten geven, zoals een ongeldige sleutel of een bereikte limiet. Bekijk alle foutcodes.

Het object

Alle velden zijn altijd aanwezig; een veld zonder waarde is null.

VeldTypeOmschrijving
object string Altijd "work_order".
id string (uuid) Unieke id (UUID).
number string Werkbonnummer, bijvoorbeeld WB-2026-00042; geeft Klantly zelf.
status string draft (concept), planned (ingepland), in_progress (bezig), completed (afgerond), invoiced (gefactureerd) of cancelled (geannuleerd). Bij aanmaken draft of planned. een van: draft, planned, in_progress, completed, invoiced, cancelled
title string Titel. kan leeg zijn (null)
type string Soort werk, bijvoorbeeld installatie, reparatie of onderhoud. kan leeg zijn (null)
location string Waar het werk plaatsvindt, als dat niet het adres van de klant is. kan leeg zijn (null)
description string Omschrijving van het werk of de klacht. kan leeg zijn (null)
work_performed string Wat er is gedaan. kan leeg zijn (null)
customer_notes string Opmerkingen voor de klant; staan op de werkbon. kan leeg zijn (null)
customer_id string (uuid) De klant. Verplicht bij aanmaken; naam, adres en contact komen van de klant. kan leeg zijn (null)
customer object De klantgegevens op de werkbon, zoals ze bij het aanmaken waren.
customer.type string individual (particulier) of business (bedrijf). kan leeg zijn (null)
customer.name string Naam; bij een bedrijf de bedrijfsnaam. kan leeg zijn (null)
customer.email string E-mailadres. kan leeg zijn (null)
customer.phone string Telefoonnummer. kan leeg zijn (null)
customer.address string Straat en huisnummer. kan leeg zijn (null)
customer.postal_code string Postcode. kan leeg zijn (null)
customer.city string Plaats. kan leeg zijn (null)
customer.country string Land. kan leeg zijn (null)
deal_id string (uuid) De deal op het pipelinebord, of null. kan leeg zijn (null)
appointment_id string (uuid) De afspraak waar de werkbon bij hoort, of null. kan leeg zijn (null)
quote_id string (uuid) De offerte waar de werkbon uit komt, of null. kan leeg zijn (null)
invoice_id string (uuid) De factuur van de werkbon, of null. kan leeg zijn (null)
assigned_user_id string De monteur of gebruiker die het werk doet, of null. kan leeg zijn (null)
language string Taal van de werkbon: nl, en, de of fr. een van: nl, en, de, fr
currency string Altijd "EUR".
subtotal string Totaal zonder btw, als tekst met twee decimalen.
tax_amount string Btw-bedrag.
total string Totaal inclusief btw.
scheduled_at string (date-time) Wanneer het werk gepland staat (UTC). Bij invoer: ISO 8601 mét tijdzone. kan leeg zijn (null)
started_at string (date-time) Wanneer het werk begon. kan leeg zijn (null)
completed_at string (date-time) Wanneer het werk klaar was. kan leeg zijn (null)
sent_at string (date-time) Wanneer de werkbon naar de klant is gestuurd. kan leeg zijn (null)
signature object De handtekening van de klant (alleen de gegevens, geen afbeelding).
signature.is_signed boolean Is de werkbon ondertekend.
signature.signed_by_name string Naam van wie ondertekende. kan leeg zijn (null)
signature.signed_at string (date-time) Wanneer er werd ondertekend. kan leeg zijn (null)
items array<object> De regels (maximaal 200). Bij invoer: een lijst met per regel name (verplicht) en optioneel type, description, sku, quantity, unit, unit_price, discount_percentage, discount_amount, tax_rate, is_taxable en minutes; de lijst vervangt alle regels.
items.object string Altijd "work_order_item".
items.id string (uuid) Id van de regel. Verandert telkens als je items meestuurt (de regels worden vervangen).
items.type string labor (arbeid), material (materiaal) of other. een van: labor, material, other
items.name string Omschrijving op de werkbon.
items.description string Toelichting. kan leeg zijn (null)
items.sku string Artikelnummer. kan leeg zijn (null)
items.quantity string Aantal.
items.unit string Eenheid, bijvoorbeeld uur of stuk. kan leeg zijn (null)
items.unit_price string Prijs per eenheid zonder btw.
items.discount_percentage string Korting in procenten.
items.discount_amount string Vaste korting op de regel zonder btw; telt alleen als discount_percentage 0 is.
items.line_total string Regeltotaal zonder btw; rekent Klantly uit.
items.is_taxable boolean Valt de regel onder de btw.
items.tax_rate string Btw-percentage (standaard 21, ook als het bedrijf een ander tarief gebruikt: stuur het dan mee).
items.minutes integer Gewerkte minuten, bij arbeid. kan leeg zijn (null)
checklist array<object> De checklist (maximaal 200 punten). Bij invoer: per punt label (verplicht) en optioneel checked, required en note; de lijst vervangt de hele checklist.
checklist.object string Altijd "work_order_checklist_item".
checklist.id string (uuid) Id van het punt.
checklist.label string Het punt, bijvoorbeeld "Druk gecontroleerd".
checklist.checked boolean Afgevinkt.
checklist.required boolean Verplicht om af te vinken.
checklist.note string Opmerking bij het punt. kan leeg zijn (null)
photos array<object> De foto’s bij de werkbon (alleen de gegevens; de bestanden zitten nog niet in de API).
photos.object string Altijd "work_order_photo".
photos.id string (uuid) Id van de foto.
photos.kind string before (voor), after (na) of other. kan leeg zijn (null) · een van: before, after, other
photos.caption string Bijschrift. kan leeg zijn (null)
photos.created_at string (date-time) Geüpload op (UTC).
created_at string (date-time) Aangemaakt op (UTC).
updated_at string (date-time) Laatst gewijzigd op (UTC).