Klantly Developers

API reference

Service requests

Customer reports (malfunctions, warranty, complaints) with photos: create them from a customer portal for example, assign them and follow their status. The actual work with hours and invoicing is the work order. You link an appointment with appointment_id; signing, picking the moment itself and converting to a work order are done by a person in Klantly or in the app.

Endpoints

List service requests

GET /api/v1/services

A list of service requests, newest first, with photos. Filter by status, priority, customer, employee, quote or change date.

Scope
services.read — Read service requests, with the customer's name, address and contact details
Required feature
work_orders

Query parameters

NameTypeDescription
limit integer Number of results per page. from 1 to 100 · default: 50
cursor string The next_cursor or prev_cursor from meta of the previous response.
sort string The field to sort on; a minus sign in front means descending. Which fields you can choose and what the default is are listed with this parameter. one of: -created_at, created_at, -updated_at, updated_at · default: -created_at
filter[status] string Only requests with this status. one of: draft, planned, in_progress, completed, cancelled
filter[priority] string Only requests with this priority. one of: low, normal, high, urgent
filter[customer_id] string (uuid) Only what belongs to this customer.
filter[assigned_user_id] string Only what is assigned to this user (the id from List users).
filter[quote_id] string (uuid) Only what belongs to this quote.
filter[updated_since] string (date-time) Only what changed since this moment: ISO 8601 with a time zone, for example 2026-09-14T10:15:00Z. Useful for synchronising. Overlap your previous moment by a few minutes, because the clock of your system and that of Klantly do not run exactly in sync, and because a change made just after your previous moment would otherwise fall just outside it. The boundary is inclusive: something changed exactly at this moment is included.

Example request

cURL
curl "https://app.klantly.com/api/v1/services?filter[status]=planned&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', 'services', [
    'query' => [
        'filter[status]' => 'planned',
        'sort' => '-updated_at',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/services?filter[status]=planned&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/services",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
    },
    params={
        "filter[status]": "planned",
        "sort": "-updated_at"
    },
)
data = response.json()["data"]

Response 200

The response is a list with cursor pagination: data contains the objects, meta the pagination.

Example response
{
  "data": [
    {
      "object": "service",
      "id": "9d3f8339-9ed1-4f6e-8dbc-c1dfe0f1a2bb",
      "number": "SV-2026-00042",
      "status": "planned",
      "priority": "high",
      "category": "malfunction",
      "title": "Lekkage bij de dakgoot",
      "location": null,
      "description": "Water loopt langs de gevel na regen.",
      "resolution": 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"
      },
      "quote_id": null,
      "appointment_id": null,
      "work_order_id": null,
      "assigned_user_id": "usr_0k3j9x21m4zq8p",
      "language": "nl",
      "reported_at": null,
      "scheduled_at": "2026-10-01T08:00:00Z",
      "started_at": null,
      "completed_at": null,
      "signature": {
        "is_signed": false,
        "signed_by_name": null,
        "signed_at": 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
  }
}

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

Get a service request

GET /api/v1/services/{service}

One service request by id, with photos (including a download link) and the state of the signature.

Scope
services.read — Read service requests, with the customer's name, address and contact details
Required feature
work_orders

Path parameters

NameTypeDescription
service required string (uuid) The id (UUID) of the service request.

Example request

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

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

Response 200

Example response
{
  "data": {
    "object": "service",
    "id": "9d3f8339-9ed1-4f6e-8dbc-c1dfe0f1a2bb",
    "number": "SV-2026-00042",
    "status": "planned",
    "priority": "high",
    "category": "malfunction",
    "title": "Lekkage bij de dakgoot",
    "location": null,
    "description": "Water loopt langs de gevel na regen.",
    "resolution": 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"
    },
    "quote_id": null,
    "appointment_id": null,
    "work_order_id": null,
    "assigned_user_id": "usr_0k3j9x21m4zq8p",
    "language": "nl",
    "reported_at": null,
    "scheduled_at": "2026-10-01T08:00:00Z",
    "started_at": null,
    "completed_at": null,
    "signature": {
      "is_signed": false,
      "signed_by_name": null,
      "signed_at": null
    },
    "photos": [],
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

Create a service request

POST /api/v1/services

Creates a request for a customer, as a draft or scheduled. Klantly gives it a number from its own series (SV-year-sequence by default); name, address and contact details come from the customer. Without reported_at, that is the moment of creation.

Scope
services.write — Create and change service requests, change their status and add photos
Required feature
work_orders

Send an Idempotency-Key and a retry after a timeout will never create a duplicate record.

Body (JSON)

FieldTypeDescription
customer_id required string (uuid) The customer. Required on create; name, address and contact details come from the customer.
title required string Subject of the request. Required on create. at most 255 characters
status optional string draft, planned (scheduled), in_progress, completed or cancelled. On create: draft or planned. one of: draft, planned
category optional string Type of request, for example malfunction, warranty, maintenance, complaint, question or other. Free text: a company may use its own types. can be empty (null) · at most 64 characters
priority optional string low, normal, high or urgent. Defaults to normal. one of: low, normal, high, urgent
location optional string Where the problem is, if that is not the customer’s address. can be empty (null) · at most 255 characters
description optional string The problem as the customer reports it. can be empty (null) · at most 20000 characters
resolution optional string What was done to solve it. can be empty (null) · at most 20000 characters
customer_notes optional string Remarks for the customer. can be empty (null) · at most 20000 characters
reported_at optional string (date-time) When the request came in (UTC). Empty on create means the moment of creation. On input: ISO 8601 with a time zone. can be empty (null)
scheduled_at optional string (date-time) When the service visit is scheduled (UTC). On input: ISO 8601 with a time zone. can be empty (null)
assigned_user_id optional string The employee handling the request, or null. can be empty (null)
appointment_id optional string (uuid) The appointment for the service visit, or null. can be empty (null)
quote_id optional string (uuid) The quote the request belongs to, or null. can be empty (null)
language optional string Language of the request: nl, en, de or fr. one of: nl, en, de, fr

Example request

cURL
curl -X POST "https://app.klantly.com/api/v1/services" \
  -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": "Lekkage bij de dakgoot",
  "category": "malfunction",
  "priority": "high",
  "description": "Water loopt langs de gevel na regen."
}'
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('POST', 'services', [
    'headers' => [
        'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
    ],
    'json' => [
        'customer_id' => '9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70',
        'title' => 'Lekkage bij de dakgoot',
        'category' => 'malfunction',
        'priority' => 'high',
        'description' => 'Water loopt langs de gevel na regen.',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/services', {
  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": "Lekkage bij de dakgoot",
  "category": "malfunction",
  "priority": "high",
  "description": "Water loopt langs de gevel na regen."
}),
});

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

import requests

response = requests.post(
    "https://app.klantly.com/api/v1/services",
    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": "Lekkage bij de dakgoot",
        "category": "malfunction",
        "priority": "high",
        "description": "Water loopt langs de gevel na regen."
    },
)
data = response.json()["data"]

Response 201

Example response
{
  "data": {
    "object": "service",
    "id": "9d3f8339-9ed1-4f6e-8dbc-c1dfe0f1a2bb",
    "number": "SV-2026-00042",
    "status": "planned",
    "priority": "high",
    "category": "malfunction",
    "title": "Lekkage bij de dakgoot",
    "location": null,
    "description": "Water loopt langs de gevel na regen.",
    "resolution": 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"
    },
    "quote_id": null,
    "appointment_id": null,
    "work_order_id": null,
    "assigned_user_id": "usr_0k3j9x21m4zq8p",
    "language": "nl",
    "reported_at": null,
    "scheduled_at": "2026-10-01T08:00:00Z",
    "started_at": null,
    "completed_at": null,
    "signature": {
      "is_signed": false,
      "signed_by_name": null,
      "signed_at": null
    },
    "photos": [],
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

Update a service request

PATCH /api/v1/services/{service}

Only changes the fields you send. You do not set the work-order link yourself: it appears when you convert the request in Klantly.

Scope
services.write — Create and change service requests, change their status and add photos
Required feature
work_orders

Send the ETag in If-Match and you will never accidentally overwrite a newer version.

Path parameters

NameTypeDescription
service required string (uuid) The id (UUID) of the service request.

Body (JSON)

FieldTypeDescription
title optional string Subject of the request. Required on create. at most 255 characters
category optional string Type of request, for example malfunction, warranty, maintenance, complaint, question or other. Free text: a company may use its own types. can be empty (null) · at most 64 characters
priority optional string low, normal, high or urgent. Defaults to normal. one of: low, normal, high, urgent
location optional string Where the problem is, if that is not the customer’s address. can be empty (null) · at most 255 characters
description optional string The problem as the customer reports it. can be empty (null) · at most 20000 characters
resolution optional string What was done to solve it. can be empty (null) · at most 20000 characters
customer_notes optional string Remarks for the customer. can be empty (null) · at most 20000 characters
reported_at optional string (date-time) When the request came in (UTC). Empty on create means the moment of creation. On input: ISO 8601 with a time zone. can be empty (null)
scheduled_at optional string (date-time) When the service visit is scheduled (UTC). On input: ISO 8601 with a time zone. can be empty (null)
assigned_user_id optional string The employee handling the request, or null. can be empty (null)
appointment_id optional string (uuid) The appointment for the service visit, or null. can be empty (null)
quote_id optional string (uuid) The quote the request belongs to, or null. can be empty (null)
language optional string Language of the request: nl, en, de or fr. one of: nl, en, de, fr

Example request

cURL
curl -X PATCH "https://app.klantly.com/api/v1/services/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "resolution": "Goot opnieuw afgekit en getest."
}'
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('PATCH', 'services/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', [
    'json' => [
        'resolution' => 'Goot opnieuw afgekit en getest.',
    ],
]);

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

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

import requests

response = requests.patch(
    "https://app.klantly.com/api/v1/services/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
    },
    json={
        "resolution": "Goot opnieuw afgekit en getest."
    },
)
data = response.json()["data"]

Response 200

Example response
{
  "data": {
    "object": "service",
    "id": "9d3f8339-9ed1-4f6e-8dbc-c1dfe0f1a2bb",
    "number": "SV-2026-00042",
    "status": "planned",
    "priority": "high",
    "category": "malfunction",
    "title": "Lekkage bij de dakgoot",
    "location": null,
    "description": "Water loopt langs de gevel na regen.",
    "resolution": 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"
    },
    "quote_id": null,
    "appointment_id": null,
    "work_order_id": null,
    "assigned_user_id": "usr_0k3j9x21m4zq8p",
    "language": "nl",
    "reported_at": null,
    "scheduled_at": "2026-10-01T08:00:00Z",
    "started_at": null,
    "completed_at": null,
    "signature": {
      "is_signed": false,
      "signed_by_name": null,
      "signed_at": null
    },
    "photos": [],
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

Change the status of a service request

POST /api/v1/services/{service}/status

Sets the request to draft, scheduled, in progress, completed or cancelled. For in progress and completed, started_at and completed_at are stamped. If "signature required for service" is on in the work-order settings, an unsigned request cannot be completed (invalid_state_transition).

Scope
services.write — Create and change service requests, change their status and add photos
Required feature
work_orders

Send an Idempotency-Key and a retry after a timeout will never create a duplicate record.

Path parameters

NameTypeDescription
service required string (uuid) The id (UUID) of the service request.

Body (JSON)

FieldTypeDescription
status required string draft, planned (scheduled), in_progress, completed or cancelled. On create: draft or planned. one of: draft, planned, in_progress, completed, cancelled

Example request

cURL
curl -X POST "https://app.klantly.com/api/v1/services/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', 'services/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/services/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/services/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"]

Response 200

Example response
{
  "data": {
    "object": "service",
    "id": "9d3f8339-9ed1-4f6e-8dbc-c1dfe0f1a2bb",
    "number": "SV-2026-00042",
    "status": "planned",
    "priority": "high",
    "category": "malfunction",
    "title": "Lekkage bij de dakgoot",
    "location": null,
    "description": "Water loopt langs de gevel na regen.",
    "resolution": 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"
    },
    "quote_id": null,
    "appointment_id": null,
    "work_order_id": null,
    "assigned_user_id": "usr_0k3j9x21m4zq8p",
    "language": "nl",
    "reported_at": null,
    "scheduled_at": "2026-10-01T08:00:00Z",
    "started_at": null,
    "completed_at": null,
    "signature": {
      "is_signed": false,
      "signed_by_name": null,
      "signed_at": null
    },
    "photos": [],
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

Delete a service request

DELETE /api/v1/services/{service}

Deletes the request, including its photos.

Scope
services.delete — Delete service requests
Required feature
work_orders

Path parameters

NameTypeDescription
service required string (uuid) The id (UUID) of the service request.

Example request

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

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

Response 200

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

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

The object

All fields are always present; a field without a value is null.

FieldTypeDescription
object string Always "service".
id string (uuid) Unique id (UUID).
number string Number of the request, for example SV-2026-00042; Klantly assigns it from its own series, separate from work orders.
status string draft, planned (scheduled), in_progress, completed or cancelled. On create: draft or planned. one of: draft, planned, in_progress, completed, cancelled
priority string low, normal, high or urgent. Defaults to normal. one of: low, normal, high, urgent
category string Type of request, for example malfunction, warranty, maintenance, complaint, question or other. Free text: a company may use its own types. can be empty (null)
title string Subject of the request. Required on create.
location string Where the problem is, if that is not the customer’s address. can be empty (null)
description string The problem as the customer reports it. can be empty (null)
resolution string What was done to solve it. can be empty (null)
customer_notes string Remarks for the customer. can be empty (null)
customer_id string (uuid) The customer. Required on create; name, address and contact details come from the customer. can be empty (null)
customer object The customer details on the request, as they were when it was created.
customer.type string individual or business. can be empty (null)
customer.name string Name; for a business, the company name. can be empty (null)
customer.email string Email address. can be empty (null)
customer.phone string Phone number. can be empty (null)
customer.address string Street and house number. can be empty (null)
customer.postal_code string Postal code. can be empty (null)
customer.city string City. can be empty (null)
customer.country string Country. can be empty (null)
quote_id string (uuid) The quote the request belongs to, or null. can be empty (null)
appointment_id string (uuid) The appointment for the service visit, or null. can be empty (null)
work_order_id string (uuid) The work order that came out of this request, or null. You do not set this yourself: it appears when the request is converted in Klantly. can be empty (null)
assigned_user_id string The employee handling the request, or null. can be empty (null)
language string Language of the request: nl, en, de or fr. one of: nl, en, de, fr
reported_at string (date-time) When the request came in (UTC). Empty on create means the moment of creation. On input: ISO 8601 with a time zone. can be empty (null)
scheduled_at string (date-time) When the service visit is scheduled (UTC). On input: ISO 8601 with a time zone. can be empty (null)
started_at string (date-time) When work on the request started. can be empty (null)
completed_at string (date-time) When the request was completed. can be empty (null)
signature object The customer’s signature on handover (details only, no image).
signature.is_signed boolean Whether the request has been signed.
signature.signed_by_name string Name of the signatory. can be empty (null)
signature.signed_at string (date-time) When it was signed. can be empty (null)
photos array<object> The photos on the request. Uploading goes through POST /services/{id}/photos.
photos.object string Always "service_photo".
photos.id string (uuid) Id of the photo.
photos.kind string issue (the report), progress, completion (the handover) or other. can be empty (null) · one of: issue, progress, completion, other
photos.caption string Caption of the photo. can be empty (null)
photos.download_url string (uri) A signed link to the photo, valid for fifteen minutes and openable without an API key.
photos.created_at string (date-time) When the photo was added (UTC).
created_at string (date-time) When the request was created (UTC).
updated_at string (date-time) When the request last changed (UTC).