Introductie
Taskport biedt een JSON API voor integraties met externe systemen zoals CRM-, planning-, ticketing-, backoffice- of partnerplatformen. De publieke API bestaat uit drie hoofdflows:
- Incoming API: opdrachten en contractor-interne berichten naar Taskport schrijven
- Planning API: planvoorstellen ophalen en opdrachten plannen binnen de scope van de bearer-token
- Outbound Sync API: wijzigingen vanuit Taskport ophalen via een cursor-based event feed
Basis-URL
https://taskport.nl
Dataformaat
Taskport gebruikt JSON voor request payloads en responses.
| Header | Waarde |
|---|---|
Content-Type | application/json |
Accept | application/json |
HTTP-methodes
| Methode | Gebruik |
|---|---|
POST | Incoming API voor create, update en internal messaging, plus Planning API voor suggesties en inplannen |
GET | Outbound Sync API voor read-only event synchronisatie |
Authenticatie
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
Accept: application/json
Authorization: Bearer YOUR_API_TOKEN
Accept: application/json
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
Accept: application/json
Rechten
- Voor outbound moet de token outbound-rechten hebben, technisch:
can_use_outbound_api = 1. - Voor incoming is een actieve token voldoende, tenzij incoming-scopes actief zijn; dan moet
can_use_incoming_api = 1op de token staan. - Voor planning moet de token planning-rechten hebben, technisch:
can_use_planning_api = 1. - Dezelfde token mag incoming, planning en outbound combineren als de bijbehorende rechten op die token aanwezig zijn.
Rate limits
| Bucket | Limiet | Periode |
|---|---|---|
| Unauthenticated requests per IP | 20 | per 60 seconden |
| Authenticated requests per token | 60 | per 60 seconden |
| Authenticated requests per IP | 90 | per 60 seconden |
429 Too Many Requests stuurt Taskport ook een Retry-After-header terug.
Fouten
missing_api_token | Geen bearer-token meegestuurd |
invalid_api_token | Ongeldig API-token |
forbidden_scope | Token heeft niet de juiste rechten |
token_misconfigured | Token is niet volledig geconfigureerd |
rate_limited | Te veel verzoeken, probeer later opnieuw |
invalid_json | Request body is geen geldige JSON |
create_identifier_required | Bij create ontbreekt zowel my_id als idempotency_key |
missing_required_fields | Verplichte create-velden ontbreken |
customer_create_failed | Klant aanmaken mislukt |
site_create_failed | Site aanmaken mislukt |
job_create_failed | Opdracht aanmaken mislukt |
job_update_failed | Opdracht, afbeeldingen of vereiste historie bijwerken mislukt; de transactie wordt teruggedraaid |
request_too_large | JSON-body overschrijdt 30 MiB |
unsupported_media_type | Gebruik application/json; geen multipart-upload |
| Afbeeldingsfouten | Ongeldige afbeelding of verwerking mislukt; zie foutcodes en index |
message_store_failed | Bericht opslaan mislukt |
internal_server_error | Onverwachte interne fout |
job_not_found | Opdracht niet gevonden binnen de scope van de token |
geo_pending | Locatie is nog niet planbaar; geocoding loopt nog |
technician_not_found | Technicus niet toegankelijk binnen deze company |
technician_unavailable | Technicus heeft op deze dag geen werkvenster |
outside_workday | Slot valt buiten werktijden |
overlaps_break | Slot overlapt met lunch/pauze |
time_off_conflict | Technicus is afwezig of vrij gepland |
overlap_conflict | Slot overlapt met een bestaande opdracht |
suggest_plan_failed | Taskport kon geen voorstel berekenen binnen de huidige randvoorwaarden |
200 | Succesvolle create, update, message append of outbound read |
400 | Ongeldige request, JSON of queryparameter |
401 | Niet geauthenticeerd |
403 | Token heeft onvoldoende rechten |
404 | Niet gevonden waar van toepassing |
405 | Methode niet toegestaan |
413 | Request body te groot |
415 | Content-Type niet ondersteund |
422 | Ongeldige afbeelding of afbeeldingslimiet overschreden |
429 | Rate limit overschreden |
500 | Interne fout |
200 OK, niet 201 Created.
Quick start
- Gebruik een actieve integration bearer-token. Voor outbound moet die token outbound-rechten hebben.
- Maak of update opdrachten via
POST /api/contractor_incoming_api.php. Klantgegevens en opdrachtgegevens gaan samen in dezelfde request. - Vraag daarna, zodra de locatie gereed is, planvoorstellen op via
POST /api/contractor_planning_api.phpmetaction = suggest_plan. - Lees wijzigingen terug via
GET /api/outbound_sync_api.phpen bewaar steeds de nieuwstenext_cursor.
Een bestaande klant kan meerdere werklocaties hebben. Na herkenning van de klant wordt
hetzelfde volledige werkadres hergebruikt; een ander adres krijgt een eigen locatie
onder die klant. Nieuwe locatienamen bestaan uit straat en huisnummer.
Het bestaande hoofdadres en zelfgekozen locatienamen blijven behouden.
Gebruik voor iedere nieuwe opdracht een eigen my_id of
idempotency_key.
Kan een nieuw werkadres nog niet worden bepaald, dan blijft
planning_ready = false; coördinaten van een ander klantadres of de
vorige opdrachtlocatie worden niet overgenomen. Een bestaande, bekende locatie
blijft bruikbaar bij een tijdelijke adreszoekstoring. Een al geplande opdracht
wordt niet door een incoming adresupdate naar een andere locatie verplaatst.
Incoming API
De incoming API is bedoeld voor externe systemen die opdrachten of contractor-interne berichten naar Taskport willen sturen.
POST https://taskport.nl/api/contractor_incoming_api.php
POST https://taskport.nl/api/intercom_incoming_api.php
Opdracht aanmaken / bijwerken
Deze route wordt gebruikt om nieuwe opdrachten aan te maken of bestaande opdrachten bij te werken.
Taskport gebruikt hiervoor my_id als externe sleutel.
Bij een nieuwe opdracht worden klantgegevens en opdrachtgegevens samen ingestuurd.
Bij een update zoekt Taskport eerst op my_id en werkt daarna de bestaande opdracht bij.
Velden bij aanmaken
Verplicht bij aanmaken:
namestreethouse_numberzipcodecitymobileemailtitleurgencyslamy_idofidempotency_key
Stuur daarnaast minstens één niet-lege omschrijving mee. Gebruik description voor
de werkomschrijving van een installatie en problem_description voor het probleem bij service.
Bestaande koppelingen die alleen problem_description sturen blijven werken, ook bij installaties.
description wordt ook bij service geaccepteerd.
Geef bij voorkeur expliciet job_type: "install" of job_type: "service" mee.
Taskport herkent deze als Installatie en Service; die labels zijn eveneens geldig.
Zonder type wordt een nieuwe opdracht als service aangemaakt.
Ontbreken beide omschrijvingen, dan noemt de validatiefout description bij installatie
en problem_description bij service of andere typen.
serial_number is optioneel voor alle nieuwe opdrachten. Het veld mag ontbreken,
null of een lege string zijn. Een nog onbekend serienummer kan later op de werkbon
worden ingevuld; stuur hiervoor geen fictief serienummer mee.
Met het optionele veld attachments
kun je direct meerdere afbeeldingen aan de nieuwe opdracht toevoegen.
Velden bij bijwerken
Verplicht bij bijwerken:
my_id
my_id al, dan werkt Taskport de bestaande opdracht bij. Als my_id bij create ontbreekt, voorkomt idempotency_key dubbele opdrachten bij retries.
Zonder job_type of een van de alternatieve typevelden blijft het bestaande opdrachttype behouden.
Als beide omschrijvingsvelden ontbreken of leeg zijn, blijft de bestaande werkomschrijving staan. Een ontbrekend,
null of leeg serial_number wist geen bestaand serienummer.
Een update met alleen een serienummer verandert de werkomschrijving niet.
Een update mag alleen my_id en attachments
bevatten om extra afbeeldingen toe te voegen. Bestaande afbeeldingen blijven behouden.
Wijzigingshistorie
Werkelijk opgeslagen wijzigingen verschijnen in de opdrachttijdlijn als Bijgewerkt via API, met de koppeling, datum en oude en nieuwe veldwaarden. Ook de volledige omschrijving blijft terug te lezen. Een herhaald verzoek zonder gewijzigde opdrachtgegevens voegt geen dubbele wijzigingsmelding toe. De technische verzoekregistratie blijft wel bestaan.
500 met job_update_failed
en wordt de opdrachtwijziging teruggedraaid. Het verzoek-ID koppelt de
interne historie aan de technische logging. Bronlinks worden afgeschermd.
Oude updates zonder deze veldhistorie worden niet achteraf gereconstrueerd.
Afbeeldingen meesturen
Stuur bij aanmaken of bijwerken een optionele JSON-array attachments mee.
Iedere afbeelding wordt een algemene opdrachtafbeelding, op dezelfde plaats als handmatig
toegevoegde afbeeldingen. Dit veld voegt afbeeldingen toe; het vervangt of verwijdert
geen bestaande afbeeldingen en vult geen fotovraag op de werkbon in.
| Veld per afbeelding | Type | Omschrijving |
|---|---|---|
filename | string | Bestandsnaam van maximaal 255 bytes, bijvoorbeeld meterkast.jpg. |
content_type | string | image/jpeg, image/png of image/webp; moet overeenkomen met de echte bestandsinhoud. |
content_base64 | string | Het volledige bestand als base64, zonder data:-prefix, spaties of regelafbrekingen. Een bestandsnaam, lokaal pad of URL is geen bestandsinhoud. |
Alle drie de velden zijn per afbeelding verplicht. Gebruik Content-Type: application/json;
deze route accepteert hiervoor geen multipart-upload of afbeelding-URL.
Laat attachments weg of stuur [] als je geen afbeeldingen wilt toevoegen.
Grenzen en verwerking
- Maximaal 10 afbeeldingen per verzoek.
- Maximaal 10 MiB per origineel en 20 MiB voor alle originelen samen, gemeten na base64-decodering.
- Maximaal 20 miljoen pixels per afbeelding en maximaal 10.000 pixels per zijde.
- De volledige JSON-body mag maximaal 30 MiB zijn; base64 is groter dan het oorspronkelijke bestand.
- Taskport past de EXIF-oriëntatie van JPEG toe, verwijdert metadata en slaat een gecomprimeerde JPEG op van maximaal 1.600 pixels aan de langste zijde en maximaal 450 KiB. Transparantie krijgt een witte achtergrond.
Herhalen en later toevoegen
Stuur een later verzoek met dezelfde my_id om nieuwe afbeeldingen aan dezelfde
opdracht toe te voegen. Dezelfde originele bestandsbytes via deze API opnieuw insturen
voegt binnen die opdracht geen tweede afbeelding toe, ook niet onder een andere bestandsnaam.
Een gewijzigd of opnieuw geëxporteerd bestand kan wel als een nieuwe afbeelding gelden.
Deduplicatie geldt per opdracht; dezelfde foto mag bij een andere opdracht worden gebruikt.
Resultaat en historie
Als attachments is meegestuurd, bevat de succesvolle response
attachments, attachments_saved en attachments_duplicates.
Per afbeelding geeft index de positie in je request aan, beginnend bij 0.
id is het afbeeldings-ID; status is stored voor
een nieuwe afbeelding of duplicate voor een al opgeslagen afbeelding.
original_filename bevat de bestandsnaam, content_type
is na compressie image/jpeg en file_size is de opgeslagen grootte in bytes.
Nieuwe afbeeldingen krijgen een vermelding in de opdrachttijdlijn met de koppeling en bestandsnamen. Een herhaling met uitsluitend bestaande afbeeldingen voegt geen tweede afbeeldingsmelding toe. Opslag van opdrachtwijzigingen, nieuwe afbeeldingen en de vereiste historie valt in dezelfde transactie. Bij een opslagfout wordt die transactie teruggedraaid.
Afbeeldingsfouten
| Code | HTTP | Betekenis |
|---|---|---|
attachments_invalid, attachment_invalid | 422 | Verkeerde lijst- of objectstructuur. |
attachment_filename_invalid | 422 | Bestandsnaam ontbreekt, is ongeldig of overschrijdt 255 bytes. |
attachment_type_invalid, attachment_type_unsupported, attachment_type_mismatch | 422 | MIME-type ontbreekt, is niet ondersteund of past niet bij de bestandsinhoud. |
attachment_base64_invalid, attachment_image_invalid | 422 | Base64 is ongeldig of de afbeelding kan niet worden gelezen. |
attachments_limit_exceeded, attachment_size_exceeded, attachments_total_size_exceeded, attachment_dimensions_exceeded | 422 | Het aantal, de bestandsgrootte of de beeldafmetingen overschrijdt een limiet. |
attachment_resource_limit | 422 | Onvoldoende verwerkingsruimte voor deze afbeelding. Verklein de afbeelding vóór het opnieuw insturen. |
attachment_processing_failed | 500 | Afbeeldingen konden niet veilig worden verwerkt; er is niets opgeslagen. |
Bij een afbeeldingsvalidatiefout bevat de response attachments_saved: 0
en attachment_index, beginnend bij 0. De index is null
als de fout de hele lijst betreft. Bijvoorbeeld een ongeldige tweede afbeelding:
{
"ok": false,
"code": "attachment_base64_invalid",
"error": "De afbeelding bevat ongeldige base64. Gebruik base64 zonder data-URL of witruimte.",
"attachment_index": 1,
"attachments_saved": 0
}
Interne notitie toevoegen
Gebruik hetzelfde endpoint om contractor-interne notities aan een bestaande opdracht toe te voegen.
Verplicht voor een bericht:
my_idmessaging.messagemessaging.external_message_id
Optioneel:
messaging.message_typemessaging.created_at
Veldreference
| Veld | Type | Omschrijving |
|---|---|---|
name | string | Klantnaam |
street | string | Straat |
house_number | string | Huisnummer |
zipcode | string | Postcode |
city | string | Woonplaats |
mobile | string | Mobiel nummer |
email | string | E-mailadres |
serial_number | string of null | Optioneel serienummer; mag bij aanmaken ontbreken of leeg zijn en kan later op de werkbon worden ingevuld. Ontbrekend of leeg bij een update behoudt het bestaande serienummer. |
title | string | Korte opdrachttitel |
description | string | Algemene werkomschrijving; aanbevolen voor installaties. Bij aanmaken is minstens één van description en problem_description vereist. |
problem_description | string | Probleemomschrijving voor service; ook geaccepteerd als omschrijving voor bestaande koppelingen. Mag bij een installatie ontbreken als description is ingevuld. |
job_type | string | Werkbontype code of label. Aanbevolen: install (Installatie) of service (Service). Andere ingestelde typen, bijvoorbeeld vervanging_easee, blijven mogelijk. Zonder type geldt service bij aanmaken; een update behoudt het bestaande type. |
job_type_code | string | Alternatieve veldnaam voor job_type |
work_type | string | Alternatieve veldnaam voor job_type |
urgency | string | Urgentie |
sla | string | SLA-label |
my_id | string | Externe opdrachtreferentie |
idempotency_key | string | Idempotency-sleutel voor create-retries |
price_ex | number | Optionele API-prijs exclusief btw |
api_price_ex | number | Alternatieve veldnaam voor price_ex |
purchase_ex | number | Alternatieve veldnaam voor price_ex |
calculated_price | number | Alternatieve veldnaam voor price_ex |
source_url | string | Link naar het bronrecord |
intercom_url | string | Alternatieve veldnaam voor source_url |
attachments | array | Optionele lijst met maximaal 10 afbeeldingen bij create of update. Elk object bevat filename, content_type en content_base64. Zie afbeeldingen meesturen voor grenzen, compressie en retries. |
description vooraan in de werkomschrijving.
Een verschillende problem_description blijft daaronder bewaard als Probleem:
bij service of Aanvullende informatie: bij installatie. Identieke teksten worden niet
dubbel opgenomen. Als beide omschrijvingsvelden bij een update ontbreken of leeg zijn,
blijft de bestaande tekst behouden.
Voorbeeld: installatie aanmaken zonder serienummer
Het serienummer is nog niet bekend. De installatiewerkzaamheden staan in description;
problem_description is voor deze request niet nodig. Twee afbeeldingen worden
optioneel meegestuurd. Vervang beide BASE64_…-waarden door de volledige base64-inhoud
van je eigen bestanden, of laat attachments helemaal weg.
curl -X POST "https://taskport.nl/api/contractor_incoming_api.php" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data-raw '{
"name": "Jane Example",
"street": "Harbor Lane",
"house_number": "14A",
"zipcode": "1012AB",
"city": "Amsterdam",
"mobile": "+31612345678",
"email": "jane.example@example.test",
"my_id": "SRC-INSTALL-90010002",
"title": "Laadpaal installeren",
"description": "Laadpaal aan de gevel installeren en aansluiten op een nieuwe groep.",
"job_type": "install",
"urgency": "normal",
"sla": "standard_24h",
"attachments": [
{
"filename": "meterkast.jpg",
"content_type": "image/jpeg",
"content_base64": "BASE64_VAN_METERKAST_JPEG"
},
{
"filename": "installatieplek.png",
"content_type": "image/png",
"content_base64": "BASE64_VAN_INSTALLATIEPLEK_PNG"
}
]
}'
{
"ok": true,
"action": "job_created",
"job_id": 60002,
"my_id": "SRC-INSTALL-90010002",
"geo_status": "ok",
"geo_message": "Locatie gecontroleerd. Planvoorstellen zijn beschikbaar.",
"planning_ready": true,
"attachments_saved": 2,
"attachments_duplicates": 0,
"attachments": [
{
"index": 0,
"id": 701,
"status": "stored",
"original_filename": "meterkast.jpg",
"content_type": "image/jpeg",
"file_size": 142330
},
{
"index": 1,
"id": 702,
"status": "stored",
"original_filename": "installatieplek.png",
"content_type": "image/jpeg",
"file_size": 121406
}
]
}
Voorbeeld: service aanmaken
Een bestaande servicekoppeling kan problem_description blijven gebruiken.
In dit voorbeeld is het serienummer bekend en wordt het optioneel meegestuurd.
curl -X POST "https://taskport.nl/api/contractor_incoming_api.php" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data-raw '{
"name": "Jane Example",
"street": "Harbor Lane",
"house_number": "14A",
"zipcode": "1012AB",
"city": "Amsterdam",
"mobile": "+31612345678",
"email": "jane.example@example.test",
"my_id": "SRC-90010001",
"serial_number": "SRC_009001",
"title": "kWh meter defect",
"problem_description": "Customer reports that the charger no longer registers meter values.",
"job_type": "service",
"urgency": "normal",
"sla": "standard_24h"
}'
{
"ok": true,
"action": "job_created",
"job_id": 60001,
"my_id": "SRC-90010001",
"geo_status": "ok",
"geo_message": "Locatie gecontroleerd. Planvoorstellen zijn beschikbaar.",
"planning_ready": true
}
Voorbeeld: opdracht bijwerken
curl -X POST "https://taskport.nl/api/contractor_incoming_api.php" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data-raw '{
"my_id": "SRC-90010001",
"title": "kWh meter defect - revisie 2",
"urgency": "high"
}'
{
"ok": true,
"action": "job_updated",
"job_id": 60001,
"my_id": "SRC-90010001",
"geo_status": "pending",
"geo_message": "Locatie wordt verwerkt. Planvoorstellen zijn meestal binnen 1 minuut beschikbaar.",
"planning_ready": false
}
messaging toe, dan kan de response extra velden bevatten zoals message_action, thread_id en message_id. Bij een dubbel external_message_id wordt message_action = duplicate_ignored teruggegeven.
{
"ok": true,
"action": "job_updated",
"job_id": 60001,
"my_id": "SRC-90010001",
"geo_status": "ok",
"geo_message": "Locatie gecontroleerd. Planvoorstellen zijn beschikbaar.",
"planning_ready": true,
"message_action": "message_added",
"thread_id": 123,
"message_id": 456
}
Voorbeeld: afbeeldingen aan een bestaande opdracht toevoegen
Gebruik de externe referentie van een bestaande opdracht binnen je koppeling.
Vervang de BASE64_…-waarden door volledige base64 zonder data:-prefix.
Eerder opgeslagen afbeeldingen blijven staan; andere opdrachtvelden hoeven niet opnieuw mee.
curl -X POST "https://taskport.nl/api/contractor_incoming_api.php" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data-raw '{
"my_id": "SRC-INSTALL-90010002",
"attachments": [
{
"filename": "kabelroute.jpg",
"content_type": "image/jpeg",
"content_base64": "BASE64_VAN_KABELROUTE_JPEG"
},
{
"filename": "gevel.webp",
"content_type": "image/webp",
"content_base64": "BASE64_VAN_GEVEL_WEBP"
}
]
}'
{
"ok": true,
"action": "job_updated",
"job_id": 60002,
"my_id": "SRC-INSTALL-90010002",
"geo_status": "ok",
"geo_message": "Locatie gecontroleerd. Planvoorstellen zijn beschikbaar.",
"planning_ready": true,
"attachments_saved": 2,
"attachments_duplicates": 0,
"attachments": [
{
"index": 0,
"id": 703,
"status": "stored",
"original_filename": "kabelroute.jpg",
"content_type": "image/jpeg",
"file_size": 133780
},
{
"index": 1,
"id": 704,
"status": "stored",
"original_filename": "gevel.webp",
"content_type": "image/jpeg",
"file_size": 108216
}
]
}
attachments_saved 0 en attachments_duplicates 2.
Beide items houden hun afbeeldings-ID en krijgen status: "duplicate".
Planning API
De planning API is bedoeld voor externe systemen die, binnen de scope van hun bearer-token, planvoorstellen willen ophalen of een opdracht zelf willen inplannen.
POST https://taskport.nl/api/contractor_planning_api.php
Planning werkt alleen als de token can_use_planning_api = 1 heeft én de opdracht
binnen de company/contractor-scope van die token valt.
geo_status terug in plaats van een vage timeout.
Acties
| Action | Doel |
|---|---|
suggest_plan | Geeft beschikbare planvensters terug voor een bestaande opdracht |
plan_job | Plant een opdracht in op een gekozen technicus en starttijd |
move_job | Verplaatst een al geplande opdracht naar een nieuw slot |
remove_from_planning | Haalt een opdracht uit de planning en zet de status terug naar created |
Planvoorstellen ophalen
Gebruik action = suggest_plan om beschikbare vensters op te vragen.
curl -X POST "https://taskport.nl/api/contractor_planning_api.php" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data-raw '{
"action": "suggest_plan",
"my_id": "SRC-90010001",
"month": "2026-05"
}'
{
"ok": true,
"action": "suggest_plan",
"job_id": 60001,
"my_id": "SRC-90010001",
"site_id": 981,
"geo_status": "ok",
"geo_message": "Locatie gecontroleerd. Planvoorstellen zijn beschikbaar.",
"planning_ready": true,
"windows": [
{
"date": "2026-05-01",
"dayname": "vrijdag",
"window_key": "middag",
"label": "Middag",
"technician_id": 12,
"technician_name": "Patrick",
"scheduled_start": "2026-05-01 14:00:00",
"scheduled_end": "2026-05-01 15:30:00"
}
],
"duration": 90,
"job_location": {
"lat": 52.3771,
"lng": 4.8980
}
}
200 OK, maar met
planning_ready = false en een lege windows-array.
{
"ok": true,
"action": "suggest_plan",
"job_id": 60001,
"my_id": "SRC-90010001",
"site_id": 981,
"geo_status": "pending",
"geo_message": "Locatie wordt verwerkt. Planvoorstellen zijn meestal binnen 1 minuut beschikbaar.",
"planning_ready": false,
"windows": [],
"duration": null,
"job_location": null
}
Opdracht plannen of verplaatsen
Gebruik action = plan_job of action = move_job om het gekozen venster vast te leggen.
Een eerste boeking blijft concept. Na interne goedkeuring volgt
pending_customer en na klantbevestiging scheduled.
Bij een herplanning bepaalt de bestaande workflow de status; lees de response en latere
statusupdates. Een succesvolle boeking is niet
automatisch een bevestigde afspraak.
Als scheduled_end ontbreekt, berekent Taskport die automatisch op basis van de duur van de opdracht.
curl -X POST "https://taskport.nl/api/contractor_planning_api.php" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data-raw '{
"action": "plan_job",
"my_id": "SRC-90010001",
"technician_id": 12,
"scheduled_start": "2026-05-01 14:00:00"
}'
{
"ok": true,
"action": "job_planned",
"job_id": 60001,
"my_id": "SRC-90010001",
"technician_id": 12,
"scheduled_start": "2026-05-01 14:00:00",
"scheduled_end": "2026-05-01 15:30:00",
"status": "concept"
}
Uit planning halen
Gebruik action = remove_from_planning om een opdracht terug te zetten naar ongepland.
{
"action": "remove_from_planning",
"my_id": "SRC-90010001"
}
{
"ok": true,
"action": "remove_from_planning",
"job_id": 60001,
"my_id": "SRC-90010001",
"status": "created"
}
Veldreference
| Veld | Type | Omschrijving |
|---|---|---|
action | string | suggest_plan, plan_job, move_job of remove_from_planning |
job_id | integer | Interne Taskport job-id; optioneel als my_id aanwezig is |
my_id | string | Externe opdrachtreferentie; aanbevolen lookup-veld |
month | string | Optioneel bij suggest_plan, formaat YYYY-MM |
technician_id | integer | Verplicht bij plan_job en move_job |
scheduled_start | datetime | Verplicht bij plan_job en move_job, lokale NL-tijd |
scheduled_end | datetime | Optioneel; wordt anders automatisch berekend |
geo_status | string | Responsveld: ok, pending of failed |
geo_message | string | Responsveld: leesbare uitleg over de huidige locatie-status |
planning_ready | boolean | Responsveld: geeft aan of Taskport al planvoorstellen kan geven |
Planning-fouten
| Code | HTTP | Omschrijving |
|---|---|---|
geo_pending | 409 | De locatie is nog niet routeklaar; probeer later opnieuw |
invalid_parameters | 400 | technician_id en scheduled_start ontbreken of zijn ongeldig |
outside_workday | 409 | Het gekozen slot valt buiten het werkvenster van de technicus |
overlaps_break | 409 | Het gekozen slot overlapt met de pauze van de technicus |
time_off_conflict | 409 | De technicus is vrij, afwezig of geblokkeerd op dit moment |
overlap_conflict | 409 | De technicus heeft al een andere opdracht op dit tijdstip |
Outbound Sync API
De outbound sync API is bedoeld voor externe systemen die wijzigingen vanuit Taskport willen uitlezen. Deze API is read-only en werkt via een cursor-based event feed.
Sync-events ophalen
Gebruik deze route om wijzigingen uit Taskport op te halen.
- haal events op vanaf een cursor
- verwerk ze in het eigen systeem
- bewaar
next_cursor - gebruik die cursor bij de volgende run
Queryparameters
| Parameter | Type | Verplicht | Omschrijving |
|---|---|---|---|
cursor | string | Nee | Laatst verwerkte eventcursor, bijvoorbeeld evt_0000000123 |
limit | integer | Nee | Aantal items, standaard 100, minimum 1, maximum 500 |
types | string | Nee | Komma-gescheiden lijst van event types |
entity_types | string | Nee | Komma-gescheiden lijst van entity types |
since | string | Nee | ISO datetime fallback als er nog geen cursor is |
Event-object
| Veld | Type | Omschrijving |
|---|---|---|
event_id | string | Unieke eventcursor |
event_type | string | Type event |
entity_type | string | Logische entity |
occurred_at | datetime | Publicatiemoment in UTC |
integration_id | integer | Interne koppeling |
contractor_id | integer | Interne contractor-id |
company_id | integer | Interne company-id |
taskport_id | integer | Interne Taskport-id |
external_id | string | Externe referentie, meestal my_id |
payload | object | Event-specifieke data |
payload.additional_work een samenvatting met count, total_price_ex_vat en items. Bij afgeronde werkbonnen staat dezelfde informatie ook in payload.workbon.additional_work; de losse regels blijven beschikbaar als payload.workbon.parts.
Event types
customer_updatedjob_createdjob_updatedworkorder_updatedmessage_addedjob_plannedjob_status_changed
customerjobworkorderjob_messagejob_planningjob_status
Statusupdates verwerken
Statusupdates worden via de bestaande GET-feed opgehaald; Taskport verstuurt hiervoor geen webhook. Gebruik dezelfde actieve bearer-token met outbound-rechten. De feed bevat uitsluitend events binnen de eigen koppeling en contractor-/companyscope.
pending_customer; pas na
klantbevestiging wordt dat scheduled.
Leid bevestiging niet af uit alleen job_planned of aanwezige plandatums.
- Vraag bijvoorbeeld elke minuut
GET /api/outbound_sync_api.php?cursor=<laatst-verwerkte-cursor>&limit=100op. Bestaande synchronisaties gaan verder vanaf hun opgeslagen cursor. - Verwerk
itemsin de geleverde volgorde. Gebruiktaskport_idvoor de koppeling naar de opdracht enevent_idom herhaalde levering zonder dubbele bijwerkingen te verwerken. - Bij
job_status_changedispayload.new_statusde nieuwe status;payload.old_statusis de vorige. Nieuwe statusmeldingen bevatten ook de aliaspayload.status. Reken bij oudere events niet op die alias. job_status_changedis leidend voor de status. Bewaar per opdracht het laatst verwerkte statusevent-ID.job_created,job_updatedenworkorder_updatedkunnen ookpayload.statusbevatten, maar zo'n momentopname kan vertraagd binnenkomen. Gebruik die status alleen voor initialisatie zolang nog geen expliciet statusevent voor de opdracht is verwerkt; overschrijf daarna de status niet meer vanuit een werkbonmomentopname. Andere werkbonvelden blijven bruikbaar. Bewaar deze keuze ook over herstarts heen.- Sla
next_cursorpas op nadat de hele batch lokaal succesvol is verwerkt, bij voorkeur in dezelfde lokale transactie. Bij een fout blijft de oude cursor staan; verwerk de batch opnieuw op basis vanevent_id. - Bij
has_more: truedirect de volgende batch ophalen. Bijhas_more: falsewachten tot de volgende poll. Geen items is normaal. Bij een HTTP-/verwerkingsfout de cursor niet vooruitzetten.
Gebruik bij voorkeur één ongefilterde feed. Wie types of
entity_types gebruikt, moet een afzonderlijke cursor per vaste filterset
bijhouden; wissel filters niet met dezelfde cursor.
Zonder cursor wordt de beschikbare historie opgehaald. since is alleen
voor een bewust gekozen startpunt en vervangt geen duurzaam opgeslagen cursor.
| Statuscode | Betekenis |
|---|---|
created | Nieuw, nog niet ingepland |
concept | Conceptplanning, nog intern goed te keuren |
pending_customer | Wachten op klantbevestiging |
scheduled | Gepland |
in_progress | In uitvoering |
paused | Gepauzeerd |
not_completed | Bezoek afgesloten, opdracht niet voltooid; opvolging nodig |
completed | Uitvoering afgerond |
validated | Werkbon gevalideerd; dit is geen betaalstatus |
cancelled | Geannuleerd |
Voorbeeld van de relevante velden in één statusitem (fictieve opdracht):
{
"event_id": "evt_0000001234",
"event_type": "job_status_changed",
"entity_type": "job_status",
"taskport_id": 12345,
"external_id": "DEMO-123",
"occurred_at": "2026-11-02T09:00:00+00:00",
"payload": {
"old_status": "concept",
"new_status": "pending_customer",
"status": "pending_customer",
"planned_at": "2026-11-13T09:00:00+00:00",
"planned_end": "2026-11-13T11:30:00+00:00",
"timezone": "Europe/Amsterdam"
}
}
Tijden zijn ISO-datums met expliciete UTC-offset; toon ze in
Europe/Amsterdam (in het voorbeeld 10:00–12:30).
Plandatums kunnen null zijn.
Bewaar onbekende toekomstige statuscodes zonder de synchronisatie stil te leggen.
Een succesvolle GET bewijst alleen dat de feed is geleverd, niet dat het externe
systeem de wijzigingen heeft opgeslagen.
De feed is geen volledige audit van iedere losse werkbonveldwijziging. Een echte statusovergang levert een statusmelding; opnieuw opslaan van dezelfde status hoeft geen nieuwe statusmelding op te leveren. Bestaande historische events worden niet herschreven of alsnog aangevuld.
Voorbeeldresponse
curl -X GET "https://taskport.nl/api/outbound_sync_api.php?cursor=evt_0000000123&limit=100" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
{
"ok": true,
"items": [
{
"event_id": "evt_0000001024",
"event_type": "job_created",
"entity_type": "job",
"occurred_at": "2026-03-18T12:41:30+00:00",
"integration_id": 17,
"contractor_id": 4,
"company_id": 1,
"taskport_id": 51425,
"external_id": "EXT-1001",
"payload": {
"customer_name": "Demo Klant",
"serial_number": "EXT_1001",
"title": "kWh meter defect",
"status": "created",
"additional_work": {
"count": 1,
"total_price_ex_vat": 42.5,
"items": [
{
"name": "Extra kabel",
"quantity": 5,
"unit_price": 8.5,
"total_price": 42.5
}
]
}
}
}
],
"next_cursor": "evt_0000001024",
"has_more": false,
"count": 1
}
X-Taskport-Integration-Id, X-Taskport-Event-Count en, als er een volgende pagina is, X-Taskport-Next-Cursor.
Request IDs
Gebruik bij support of troubleshooting altijd de request-id uit de response headers.
X-Taskport-Request-Id: <request-id>