Taskport API

Taskport API Reference

Publieke developer reference voor externe systemen die met Taskport willen integreren. Deze pagina bevat alle informatie die nodig is om opdrachten naar Taskport te schrijven en wijzigingen vanuit Taskport terug te lezen.

Basis-URL https://taskport.nl
Authenticatie Bearer token
Incoming POST /api/contractor_incoming_api.php
Outbound GET /api/outbound_sync_api.php
Planning POST /api/contractor_planning_api.php

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
1 publieke reference Incoming + planning + outbound JSON over HTTPS

Basis-URL

https://taskport.nl

Dataformaat

Taskport gebruikt JSON voor request payloads en responses.

Header Waarde
Content-Typeapplication/json
Acceptapplication/json

HTTP-methodes

Methode Gebruik
POSTIncoming API voor create, update en internal messaging, plus Planning API voor suggesties en inplannen
GETOutbound Sync API voor read-only event synchronisatie

Authenticatie

Incoming
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
Accept: application/json
Outbound
Authorization: Bearer YOUR_API_TOKEN
Accept: application/json
Planning
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
Accept: application/json
Deze API’s zijn bruikbaar voor elke partij met een geldige bearer-token die de juiste rechten heeft voor de betreffende route.

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 = 1 op 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 IP20per 60 seconden
Authenticated requests per token60per 60 seconden
Authenticated requests per IP90per 60 seconden
Bij 429 Too Many Requests stuurt Taskport ook een Retry-After-header terug.

Fouten

Authenticatie en rechten
missing_api_tokenGeen bearer-token meegestuurd
invalid_api_tokenOngeldig API-token
forbidden_scopeToken heeft niet de juiste rechten
token_misconfiguredToken is niet volledig geconfigureerd
rate_limitedTe veel verzoeken, probeer later opnieuw
Incoming validatie
invalid_jsonRequest body is geen geldige JSON
create_identifier_requiredBij create ontbreekt zowel my_id als idempotency_key
missing_required_fieldsVerplichte create-velden ontbreken
customer_create_failedKlant aanmaken mislukt
site_create_failedSite aanmaken mislukt
job_create_failedOpdracht aanmaken mislukt
job_update_failedOpdracht, afbeeldingen of vereiste historie bijwerken mislukt; de transactie wordt teruggedraaid
request_too_largeJSON-body overschrijdt 30 MiB
unsupported_media_typeGebruik application/json; geen multipart-upload
AfbeeldingsfoutenOngeldige afbeelding of verwerking mislukt; zie foutcodes en index
message_store_failedBericht opslaan mislukt
internal_server_errorOnverwachte interne fout
Planning validatie
job_not_foundOpdracht niet gevonden binnen de scope van de token
geo_pendingLocatie is nog niet planbaar; geocoding loopt nog
technician_not_foundTechnicus niet toegankelijk binnen deze company
technician_unavailableTechnicus heeft op deze dag geen werkvenster
outside_workdaySlot valt buiten werktijden
overlaps_breakSlot overlapt met lunch/pauze
time_off_conflictTechnicus is afwezig of vrij gepland
overlap_conflictSlot overlapt met een bestaande opdracht
suggest_plan_failedTaskport kon geen voorstel berekenen binnen de huidige randvoorwaarden
HTTP-statuscodes
200Succesvolle create, update, message append of outbound read
400Ongeldige request, JSON of queryparameter
401Niet geauthenticeerd
403Token heeft onvoldoende rechten
404Niet gevonden waar van toepassing
405Methode niet toegestaan
413Request body te groot
415Content-Type niet ondersteund
422Ongeldige afbeelding of afbeeldingslimiet overschreden
429Rate limit overschreden
500Interne fout
Let op: de incoming API retourneert op dit moment bij een succesvolle create of update ook gewoon 200 OK, niet 201 Created.

Quick start

  1. Gebruik een actieve integration bearer-token. Voor outbound moet die token outbound-rechten hebben.
  2. Maak of update opdrachten via POST /api/contractor_incoming_api.php. Klantgegevens en opdrachtgegevens gaan samen in dezelfde request.
  3. Vraag daarna, zodra de locatie gereed is, planvoorstellen op via POST /api/contractor_planning_api.php met action = suggest_plan.
  4. Lees wijzigingen terug via GET /api/outbound_sync_api.php en bewaar steeds de nieuwste next_cursor.
Er is in deze publieke reference geen aparte klant-create endpoint. Een nieuwe opdracht wordt aangemaakt inclusief klantgegevens in dezelfde incoming request. Taskport maakt waar nodig ook direct een locatie aan en probeert die meteen te geocoden.

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.

Ondersteunde URL
POST https://taskport.nl/api/contractor_incoming_api.php
Alternatieve URL
POST https://taskport.nl/api/intercom_incoming_api.php
Beide URLs doen functioneel hetzelfde. Je kunt dus dezelfde incoming API via beide routes benaderen.
Verzoeken naar deze endpoints schrijven echte gegevens. Ook de incoming API-simulator voert echte requests uit; er is geen aparte dry-runmodus.

Opdracht aanmaken / bijwerken

POST /api/contractor_incoming_api.php

Deze route wordt gebruikt om nieuwe opdrachten aan te maken of bestaande opdrachten bij te werken. Taskport gebruikt hiervoor my_id als externe sleutel.

Aanmaken

Bij een nieuwe opdracht worden klantgegevens en opdrachtgegevens samen ingestuurd.

Bijwerken

Bij een update zoekt Taskport eerst op my_id en werkt daarna de bestaande opdracht bij.

Velden bij aanmaken

Verplicht bij aanmaken:

  • name
  • street
  • house_number
  • zipcode
  • city
  • mobile
  • email
  • title
  • urgency
  • sla
  • my_id of idempotency_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
Bestaat 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.

De opdrachtwijziging en bijbehorende historie worden samen opgeslagen. Mislukt dit, dan volgt 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 afbeeldingTypeOmschrijving
filenamestringBestandsnaam van maximaal 255 bytes, bijvoorbeeld meterkast.jpg.
content_typestringimage/jpeg, image/png of image/webp; moet overeenkomen met de echte bestandsinhoud.
content_base64stringHet 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.
Alle afbeeldingen worden gecontroleerd en gecomprimeerd voordat het verzoek opdrachtgegevens opslaat. Is één afbeelding ongeldig, dan wordt het hele verzoek afgewezen. Bestaande afbeeldingen blijven in alle gevallen behouden.

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

CodeHTTPBetekenis
attachments_invalid, attachment_invalid422Verkeerde lijst- of objectstructuur.
attachment_filename_invalid422Bestandsnaam ontbreekt, is ongeldig of overschrijdt 255 bytes.
attachment_type_invalid, attachment_type_unsupported, attachment_type_mismatch422MIME-type ontbreekt, is niet ondersteund of past niet bij de bestandsinhoud.
attachment_base64_invalid, attachment_image_invalid422Base64 is ongeldig of de afbeelding kan niet worden gelezen.
attachments_limit_exceeded, attachment_size_exceeded, attachments_total_size_exceeded, attachment_dimensions_exceeded422Het aantal, de bestandsgrootte of de beeldafmetingen overschrijdt een limiet.
attachment_resource_limit422Onvoldoende verwerkingsruimte voor deze afbeelding. Verklein de afbeelding vóór het opnieuw insturen.
attachment_processing_failed500Afbeeldingen 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

POST /api/contractor_incoming_api.php

Gebruik hetzelfde endpoint om contractor-interne notities aan een bestaande opdracht toe te voegen.

Verplicht voor een bericht:

  • my_id
  • messaging.message
  • messaging.external_message_id

Optioneel:

  • messaging.message_type
  • messaging.created_at
Een bericht via deze koppeling is altijd contractor-intern en niet zichtbaar voor de klant.

Veldreference

Veld Type Omschrijving
namestringKlantnaam
streetstringStraat
house_numberstringHuisnummer
zipcodestringPostcode
citystringWoonplaats
mobilestringMobiel nummer
emailstringE-mailadres
serial_numberstring of nullOptioneel 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.
titlestringKorte opdrachttitel
descriptionstringAlgemene werkomschrijving; aanbevolen voor installaties. Bij aanmaken is minstens één van description en problem_description vereist.
problem_descriptionstringProbleemomschrijving voor service; ook geaccepteerd als omschrijving voor bestaande koppelingen. Mag bij een installatie ontbreken als description is ingevuld.
job_typestringWerkbontype 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_codestringAlternatieve veldnaam voor job_type
work_typestringAlternatieve veldnaam voor job_type
urgencystringUrgentie
slastringSLA-label
my_idstringExterne opdrachtreferentie
idempotency_keystringIdempotency-sleutel voor create-retries
price_exnumberOptionele API-prijs exclusief btw
api_price_exnumberAlternatieve veldnaam voor price_ex
purchase_exnumberAlternatieve veldnaam voor price_ex
calculated_pricenumberAlternatieve veldnaam voor price_ex
source_urlstringLink naar het bronrecord
intercom_urlstringAlternatieve veldnaam voor source_url
attachmentsarrayOptionele 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.
Zijn beide omschrijvingen ingevuld, dan staat 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
}
Voeg je in dezelfde request ook 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
    }
  ]
}
Stuur je exact dezelfde twee bestanden opnieuw naar deze opdracht, dan is 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.

Planning endpoint
POST https://taskport.nl/api/contractor_planning_api.php
Belangrijk

Planning werkt alleen als de token can_use_planning_api = 1 heeft én de opdracht binnen de company/contractor-scope van die token valt.

Taskport probeert bij het eerste planningsverzoek ontbrekende locatiegegevens nog netjes af te handelen. Als een locatie nog niet routeklaar is, krijg je een duidelijke geo_status terug in plaats van een vage timeout.

Acties

Action Doel
suggest_planGeeft beschikbare planvensters terug voor een bestaande opdracht
plan_jobPlant een opdracht in op een gekozen technicus en starttijd
move_jobVerplaatst een al geplande opdracht naar een nieuw slot
remove_from_planningHaalt een opdracht uit de planning en zet de status terug naar created

Planvoorstellen ophalen

POST /api/contractor_planning_api.php

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
  }
}
Als de locatie nog niet planbaar is, krijg je nog steeds 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

POST /api/contractor_planning_api.php

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

POST /api/contractor_planning_api.php

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
actionstringsuggest_plan, plan_job, move_job of remove_from_planning
job_idintegerInterne Taskport job-id; optioneel als my_id aanwezig is
my_idstringExterne opdrachtreferentie; aanbevolen lookup-veld
monthstringOptioneel bij suggest_plan, formaat YYYY-MM
technician_idintegerVerplicht bij plan_job en move_job
scheduled_startdatetimeVerplicht bij plan_job en move_job, lokale NL-tijd
scheduled_enddatetimeOptioneel; wordt anders automatisch berekend
geo_statusstringResponsveld: ok, pending of failed
geo_messagestringResponsveld: leesbare uitleg over de huidige locatie-status
planning_readybooleanResponsveld: geeft aan of Taskport al planvoorstellen kan geven

Planning-fouten

Code HTTP Omschrijving
geo_pending409De locatie is nog niet routeklaar; probeer later opnieuw
invalid_parameters400technician_id en scheduled_start ontbreken of zijn ongeldig
outside_workday409Het gekozen slot valt buiten het werkvenster van de technicus
overlaps_break409Het gekozen slot overlapt met de pauze van de technicus
time_off_conflict409De technicus is vrij, afwezig of geblokkeerd op dit moment
overlap_conflict409De 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

GET /api/outbound_sync_api.php

Gebruik deze route om wijzigingen uit Taskport op te halen.

  1. haal events op vanaf een cursor
  2. verwerk ze in het eigen systeem
  3. bewaar next_cursor
  4. gebruik die cursor bij de volgende run

Queryparameters

Parameter Type Verplicht Omschrijving
cursorstringNeeLaatst verwerkte eventcursor, bijvoorbeeld evt_0000000123
limitintegerNeeAantal items, standaard 100, minimum 1, maximum 500
typesstringNeeKomma-gescheiden lijst van event types
entity_typesstringNeeKomma-gescheiden lijst van entity types
sincestringNeeISO datetime fallback als er nog geen cursor is

Event-object

Veld Type Omschrijving
event_idstringUnieke eventcursor
event_typestringType event
entity_typestringLogische entity
occurred_atdatetimePublicatiemoment in UTC
integration_idintegerInterne koppeling
contractor_idintegerInterne contractor-id
company_idintegerInterne company-id
taskport_idintegerInterne Taskport-id
external_idstringExterne referentie, meestal my_id
payloadobjectEvent-specifieke data
Als er meerwerk op de opdracht is geregistreerd, bevat 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

Belangrijkste event types
  • customer_updated
  • job_created
  • job_updated
  • workorder_updated
  • message_added
  • job_planned
  • job_status_changed
Belangrijkste entity types
  • customer
  • job
  • workorder
  • job_message
  • job_planning
  • job_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.

Concept → Wachten op klant → Gepland. Een eerste API-boeking legt een concept vast, geen bevestigde klantafspraak. Interne goedkeuring geeft pending_customer; pas na klantbevestiging wordt dat scheduled. Leid bevestiging niet af uit alleen job_planned of aanwezige plandatums.
  1. Vraag bijvoorbeeld elke minuut GET /api/outbound_sync_api.php?cursor=<laatst-verwerkte-cursor>&limit=100 op. Bestaande synchronisaties gaan verder vanaf hun opgeslagen cursor.
  2. Verwerk items in de geleverde volgorde. Gebruik taskport_id voor de koppeling naar de opdracht en event_id om herhaalde levering zonder dubbele bijwerkingen te verwerken.
  3. Bij job_status_changed is payload.new_status de nieuwe status; payload.old_status is de vorige. Nieuwe statusmeldingen bevatten ook de alias payload.status. Reken bij oudere events niet op die alias.
  4. job_status_changed is leidend voor de status. Bewaar per opdracht het laatst verwerkte statusevent-ID. job_created, job_updated en workorder_updated kunnen ook payload.status bevatten, 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.
  5. Sla next_cursor pas 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 van event_id.
  6. Bij has_more: true direct de volgende batch ophalen. Bij has_more: false wachten 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.

StatuscodeBetekenis
createdNieuw, nog niet ingepland
conceptConceptplanning, nog intern goed te keuren
pending_customerWachten op klantbevestiging
scheduledGepland
in_progressIn uitvoering
pausedGepauzeerd
not_completedBezoek afgesloten, opdracht niet voltooid; opvolging nodig
completedUitvoering afgerond
validatedWerkbon gevalideerd; dit is geen betaalstatus
cancelledGeannuleerd

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
}
De outbound response kan ook deze headers bevatten: 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>
Dit document is de enige publieke API-pagina die extern gedeeld hoeft te worden.