# Gebeurtenissen & pogingen Gebruik een gebeurtenis voor voortgang zoals opgehaald of onderweg. Gebruik een bezorgpoging voor een daadwerkelijke uitkomst zoals afgeleverd, niet thuis of geweigerd. Beide aanvragen vereisen `deliveries:write`. ## Wat stuur je bij beide aanvragen mee? | Plaats | Veld | Invullen | | --- | --- | --- | | URL-pad | `{id}` | `entry_id` van de bestaande levering; een UUID. | | Header | `Authorization` | `Bearer `. | | Header | `Content-Type` | `application/json`. | | Header | `Idempotency-Key` | Een nieuwe unieke waarde van 8–128 bytes per gebeurtenis of poging. Bewaar die voor retries. | Je hoeft hier geen `If-Match` mee te sturen. De waarnemingstijd bepaalt of de nieuwe informatie ook de actuele toestand verandert. Zie [volgorde en tijdstippen](#volgorde-en-tijdstippen). ## Velden voor een gebeurtenis **Aanvraag:** `POST /deliveries/v1/parcels/{id}/events`. | Bodyveld | Invullen? | Type en toegestane waarden | Voorbeeld | | --- | --- | --- | --- | | `status` | Expliciet meesturen | Geheel getal: 0 aangemeld, 1 opgehaald, 2 onderweg, 3 in bezorging. | `3` | | `occurred_at` | Verplicht | Unix-seconden UTC van de werkelijke gebeurtenis. Vanaf 1 januari 2000 tot maximaal vijf minuten in de toekomst. | `1792141200` | Laat `status` niet weg: bij weglaten gebruikt de API 0. Dat is een echte status en kan dus iets anders betekenen dan je bedoeling. Status 4 en 5 zijn op dit endpoint ongeldig; gebruik daarvoor een bezorgpoging. ```json {"status": 3, "occurred_at": 1792141200} ``` De voorbeeldtijd is 16 oktober 2026, 09:00 UTC. Vul voor je eigen aanvraag het werkelijke tijdstip in. Een complete aanroep met een voorbereid bestand `gebeurtenis.json`: ```sh curl --fail-with-body --silent --show-error \ -X POST "https://api.vlows.io/deliveries/v1/parcels/$ENTRY_ID/events" \ -H "Authorization: Bearer $API_KEY" \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: gebeurtenis-voorbeeld-0001' \ --data-binary @gebeurtenis.json ``` Bewaar het bestand en dezelfde sleutel als je na een timeout opnieuw probeert. ## Velden voor een bezorgpoging **Aanvraag:** `POST /deliveries/v1/parcels/{id}/attempts`. | Bodyveld | Invullen? | Type en regels | Voorbeeld | | --- | --- | --- | --- | | `time_attempt` | Verplicht | Unix-seconden UTC van de poging; dezelfde tijdgrenzen als een gebeurtenis. | `1792141500` | | `outcome` | Expliciet meesturen | Geheel getal 0–4 uit de uitkomsttabel. Bij weglaten gebruikt de API 0 (afgeleverd). | `1` | | `reason` | Optioneel | Geheel getal 0–10 uit de redentabel. Weglaten betekent 0. | `1` | | `delivered` | Optioneel, alleen bij uitkomst 0 of 2 | Object met de daadwerkelijk gebruikte afleveradresvelden; zie hieronder. | Zie volledig voorbeeld. | | `attempt_no` | Niet invullen | Vlows wijst het pogingnummer toe. Een eigen niet-nul pogingnummer wordt geweigerd. | Weglaten. | Voorbeeld: niet thuis. Uitkomst 1 is mislukt; reden 1 betekent niet thuis. ```json {"time_attempt": 1792141500, "outcome": 1, "reason": 1} ``` Het `delivered`-object hoort niet bij een mislukte, geweigerde of opnieuw ingeplande poging. Een poging heeft geen losse `status` of `occurred_at`: gebruik de veldnamen van dit endpoint. ## Uitkomsten | `outcome` | Naam | Betekenis | Actuele bezorgstatus als deze poging wordt toegepast | | --- | --- | --- | --- | | 0 | `delivered` | Afgeleverd. | 4 | | 1 | `failed` | Mislukt. | 5 | | 2 | `delivered_alternative` | Afgeleverd op een andere plek. | 4 | | 3 | `refused` | Geweigerd. | 5 | | 4 | `rescheduled` | Opnieuw ingepland. | 3 | De API zet bij een toegepaste aflevering ook `time_delivered` op het tijdstip van de poging. Je stuurt dat veld niet apart mee bij deze aanvraag. ## Redenen | `reason` | Naam | Gebruik | | --- | --- | --- | | 0 | `none` | Geen aanvullende reden; standaard bij weglaten. | | 1 | `not_home` | Ontvanger niet thuis. | | 2 | `address_not_found` | Adres niet gevonden. | | 3 | `no_access` | Geen toegang. | | 4 | `refused` | Ontvanger weigert. | | 5 | `damaged` | Beschadigd. | | 6 | `out_of_time` | Geen tijd meer. | | 7 | `vehicle_traffic` | Voertuig- of verkeersprobleem. | | 8 | `weather` | Weersomstandigheden. | | 9 | `business_closed` | Bedrijf gesloten. | | 10 | `other` | Andere reden. | Kies een reden die bij de waarneming past. Er is geen vrij tekstveld voor opmerkingen bij een poging; stuur geen extra `notes` of `description` mee. ## Velden binnen delivered Dit object is optioneel bij uitkomst 0 en 2. Zodra je het meestuurt, zijn land, postcode en nummer verplicht. Zonder het object wordt geen nieuw afleveradres opgegeven. | Veld binnen `delivered` | Verplicht in dit object? | Formaat | Voorbeeld | | --- | --- | --- | --- | | `delivered_country` | Ja | Tekst, exact NL. | `"NL"` | | `delivered_postal_code` | Ja | Nederlandse postcode als tekst. | `"9901KB"` | | `delivered_number` | Ja | Huisnummer als tekst. | `"16"` | | `delivered_city` | Nee | Tekst, maximaal 32 UTF-8-bytes. | `"Delfzijl"` | | `delivered_street` | Nee | Tekst, maximaal 32 UTF-8-bytes. | `"Voorbeeldstraat"` | | `delivered_addition` | Nee | Tekst, maximaal 32 UTF-8-bytes. | `"A"` | | `delivered_location_type` | Nee | Code 0–6; zie [locaties](/pakketvelden/#service--en-locatiecodes). | `0` | Ook land, postcode en nummer vallen onder de tekstlimiet van 32 UTF-8-bytes. Gebruik de exacte namen met `delivered_`, geen `country`, `postal_code` of `number` binnen dit object. Volledig voorbeeld van een aflevering aan de deur: ```json { "time_attempt": 1792141800, "outcome": 0, "reason": 0, "delivered": { "delivered_country": "NL", "delivered_postal_code": "9901KB", "delivered_number": "16", "delivered_location_type": 0 } } ``` Sla het JSON-object van de gewenste poging op als `poging.json` en verstuur het zo: ```sh curl --fail-with-body --silent --show-error \ -X POST "https://api.vlows.io/deliveries/v1/parcels/$ENTRY_ID/attempts" \ -H "Authorization: Bearer $API_KEY" \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: poging-voorbeeld-0001' \ --data-binary @poging.json ``` `ENTRY_ID` is de eerder ontvangen leverings-UUID; `API_KEY` komt uit je geheime configuratie. Gebruik per nieuwe poging een nieuwe idempotentiesleutel. Een herhaling na een timeout gebruikt juist dezelfde sleutel en hetzelfde bestand. Gebruik je eigen adres en de echte aflevertijd. De API controleert het adres via de BAG. De betekenis van de uitkomst staat bij [Adrescontrole](/adressen/). ## Wat krijg je terug? Beide POST-aanvragen geven bij succes 201 en dezelfde antwoordstructuur: ```json { "data": { "event_id": "", "entry_id": "", "applied_to_current_state": true, "version": 4 }, "error": null } ``` `event_id` identificeert de opgeslagen gebeurtenis, ook als die voortkomt uit een bezorgpoging. `version` is de nieuwe leveringsversie. `applied_to_current_state` vertelt of de gebeurtenis ook de actuele toestand heeft aangepast. Voor de actuele `ETag` en complete levering doe je daarna een GET op de levering. ## Volgorde en tijdstippen Vlows bewaart de echte waarnemingstijd én het moment van ontvangst. Een oudere gebeurtenis kan worden opgeslagen met `applied_to_current_state: false`, zodat de historie compleet blijft zonder de nieuwste toestand te overschrijven. Twee verschillende statussen op exact dezelfde seconde geven `409 ambiguous_event_order`. Een gewone registratie krijgt als begintijd het registratiemoment. Meld daarna de feitelijke nieuwe waarnemingen; stuur geen verzonnen tussenstappen of aangepaste tijden alleen om een conflict te omzeilen. Voor gebeurtenissen die de actuele toestand veranderen gelden deze overgangen. Een gelijke status blijft toegestaan. | Huidige status | Volgende toegestane andere statussen | | --- | --- | | 0 aangemeld | 1, 2, 3, 4, 5 | | 1 opgehaald | 2, 3, 4, 5 | | 2 onderweg | 3, 4, 5 | | 3 in bezorging | 2, 4, 5 | | 4 afgeleverd | Geen andere status; afgeleverd is een eindstatus. | | 5 mislukt | 2, 3, 4 | Status 4 en 5 meld je altijd via een poging. Een ongeldige overgang geeft `409 invalid_transition`. Een late poging krijgt een pogingnummer in ontvangstvolgorde, ook als het waarnemingstijdstip ouder is. ## Geschiedenis uitlezen Gebruik `deliveries:read` en de leverings-UUID in het pad. Beide GET-aanvragen hebben geen body of queryvelden. | Aanvraag | Velden per resultaat in `data` | | --- | --- | | `GET /deliveries/v1/parcels/{id}/events` | `event_id`, `occurred_at`, `received_at`, `status`, `source`. | | `GET /deliveries/v1/parcels/{id}/attempts` | `attempt_no`, `time_attempt`, `outcome`, `reason`, `address`. | `occurred_at` en `time_attempt` zijn Unix-seconden; `received_at` is een serverdatumstring. `source` geeft de herkomst van de gebeurtenis weer. Gebeurtenissen staan op waarnemingstijd en zijn begrensd op 1000 resultaten, zonder cursor. Pogingen staan op pogingnummer; maximaal 127 per levering. `address` bevat de opgeslagen adrescontrole bij de poging. ## Fouten voorkomen Gebruik `status` en `occurred_at` bij gebeurtenissen; gebruik `outcome` en `time_attempt` bij pogingen. Stuur tijd als seconden, geen milliseconden. Geef alleen bij aflevering een `delivered`-object mee en laat `attempt_no` weg. Bij een timeout herhaal je dezelfde bodybytes en idempotentiesleutel. Zie [Fouten & opnieuw proberen](/foutmeldingen/).