# Een API-aanvraag opbouwen De basis-URL is `https://api.vlows.io`. Maak eerst een API-key in de [console](/api-keys/) met de rechten voor je koppeling. De API gebruikt die key bij iedere aanvraag; je logt er niet in met je consolewachtwoord. ## De onderdelen van een aanvraag ```http PATCH /deliveries/v1/parcels/ Authorization: Bearer Content-Type: application/json If-Match: "3" {"parcel_weight": 1200} ``` Hier is `PATCH` de methode, staat het ID in het pad, staan toegang en versie in de headers en bevat de JSON-body de wijziging. Vervang placeholders zoals `` door echte ontvangen waarden, zonder de punthaken. De relatieve paden in deze wiki horen achter de basis-URL. ## Welke headers zijn nodig? | Header | Wanneer? | Hoe invullen? | | --- | --- | --- | | `Authorization` | Elke klantaanvraag | `Bearer ` gevolgd door de volledige `vlw_`-key. Eén spatie na Bearer; geen aanhalingstekens rond de key. | | `Content-Type` | POST/PATCH met JSON | Exact `application/json`. | | `Idempotency-Key` | Nieuwe levering, gebeurtenis of bezorgpoging | Unieke tekst van 8–128 bytes, zonder spaties aan begin/einde. Een UUID is geschikt. Bewaar dezelfde waarde voor een herhaling van dezelfde aanvraag. | | `If-Match` | Een levering met PATCH wijzigen | Neem de `ETag` van de laatste GET letterlijk over, inclusief dubbele aanhalingstekens, bijvoorbeeld `"3"`. | | `Accept` | Optioneel | `application/json`. | Een losse adrescontrole vereist geen `Idempotency-Key`. GET-aanvragen hebben geen JSON-body nodig. Een PATCH gebruikt `If-Match`; een idempotentiesleutel vervangt die versiecontrole niet. ## JSON correct invullen Gebruik één JSON-object per schrijfaanvraag. Geen commentaar, geen komma achter het laatste veld en geen twee objecten achter elkaar. De body mag maximaal 2 MiB zijn. ```json {"courier":"demo","country":"NL","postal_code":"9901KB","number":"16","parcel_weight":1200} ``` - Tekst staat tussen dubbele aanhalingstekens: `"number":"16"`. - Gehele getallen staan zonder aanhalingstekens: `"parcel_weight":1200`. - Keuzecodes zijn getallen: `"delivery_status":2`, niet `"in_transit"`. - Een lege tekstwaarde is `""`. `null` betekent geen waarde en is alleen geschikt waar de betreffende veldgids dat aangeeft. - Gebruik de veldnamen exact. Extra velden, bijvoorbeeld `customer_name` of `tracking_number`, horen niet bij het leveringscontract en worden geweigerd. Vul geen `0` in om te bedoelen dat je iets niet weet. Nul kan een echte code zijn: status 0 betekent aangemeld, uitkomst 0 betekent afgeleverd. Laat optionele, onbekende velden weg. Zie [Pakketvelden](/pakketvelden/) voor de precieze combinaties. ## Tijd omzetten naar Unix-seconden Tijdvelden in de invoer gebruiken **UTC-seconden sinds 1 januari 1970**. Een voorbeeld: 16 oktober 2026, 08:00:00 UTC is `1792137600`. Dit is alleen een uitlegwaarde; gebruik in een echte aanvraag de juiste waarnemingstijd of planning. | Situatie | Wat doe je? | | --- | --- | | Je bron heeft milliseconden | Deel door 1000 en rond naar beneden af. | | Je bron heeft een datum met tijdzone | Zet die datum om naar UTC en vervolgens naar Unix-seconden. | | Je bron heeft een lokale tijd zonder tijdzone | Bepaal eerst de juiste tijdzone, inclusief zomertijd. | | Je vraagt oracle-uren op | Rond de grens af op een veelvoud van 3600 seconden. | JavaScript: ```javascript const occurredAt = Math.floor(Date.now() / 1000); const fixedExample = Math.floor(Date.parse("2026-10-16T08:00:00Z") / 1000); ``` Python: ```python from datetime import datetime, timezone occurred_at = int(datetime.now(timezone.utc).timestamp()) fixed_example = int(datetime(2026, 10, 16, 8, 0, tzinfo=timezone.utc).timestamp()) ``` Aflever-, gebeurtenis- en pogingtijden mogen niet eerder zijn dan 1 januari 2000 en niet meer dan vijf minuten in de toekomst liggen. De ruimere planning- en oraclegrenzen staan in hun eigen veldgidsen. Servervelden zoals `created_at` en `updated_at` worden als datumstrings teruggegeven; kopieer die niet rechtstreeks naar een numeriek invoertijdveld. ## Waarden in het URL-pad `{id}` of `` betekent: gebruik de UUID uit `data.entry_id` van de aangemaakte levering, bijvoorbeeld `58ce079d-3d45-4af1-9bdb-e43ed17c60fa`. Het voorbeeld-ID verwijst niet naar een echte levering van jouw organisatie. Gebruik geen vervoerderscode, eigen ordernummer of volledige key als levering-ID. Objecten van andere organisaties zijn niet toegankelijk met jouw key. `metric` bij de oracle is letterlijk `activity`, `planned` of `coverage`. ## Queryparameters invullen Parameters staan na `?`; meerdere parameters scheid je met `&`. Bijvoorbeeld `?limit=25&status=2`. Gebruik elke parameter één keer en laat niet gebruikte parameters volledig weg. `limit=` is geen geldige limiet; weglaten kiest de standaard. Laat je HTTP-bibliotheek waarden URL-encoderen. Met curl kan dat zo: ```sh curl --fail-with-body --silent --show-error --get \ 'https://api.vlows.io/deliveries/v1/parcels' \ -H "Authorization: Bearer $API_KEY" \ --data-urlencode 'limit=25' \ --data-urlencode 'status=2' ``` Stuur alleen de filters die bij het endpoint staan. Er zijn bijvoorbeeld geen vrije datumfilters op de gebruiksaanvragen en geen zoekfilter op ontvangersnamen. ## Het antwoord lezen Succes geeft een JSON-object met `data` en `error: null`. `data` kan een object of lijst zijn; bij een leveringlijst staat de lijst in `data.items`. Een lege lijst betekent dat er geen resultaten zijn binnen de gekozen aanvraag. ```json {"data": [], "error": null} ``` Een fout heeft `data: null` en een `error` met `code`, `message` en `request_id`. De responseheader `X-Request-ID` helpt dezelfde aanvraag terugvinden. Bij het opvragen, aanmaken en wijzigen van één levering kan de header `ETag` de versie bevatten. ```json {"data": null, "error": {"code": "validation_failed", "message": "both time slot boundaries are required", "request_id": ""}} ``` Dit voorbeeld betekent dat één van de twee tijdvakgrenzen ontbreekt. Corrigeer het verzoek voordat je opnieuw probeert. De [foutengids](/foutmeldingen/) legt de overige statussen uit. ## Een aanvraag veilig herhalen Bewaar voor een schrijfactie de methode, URL, JSON-bytes en `Idempotency-Key` totdat je zeker weet wat het resultaat is. Bij een timeout herhaal je diezelfde aanvraag. Andere spaties of een andere veldvolgorde veranderen de bytes en kunnen met dezelfde sleutel tot `409 idempotency_conflict` leiden. Een nieuwe zakelijke actie krijgt een nieuwe sleutel. Een succesvolle herhaling heeft `Idempotency-Replayed: true` en telt niet opnieuw als verbruikseenheid. Bij een PATCH-versieconflict lees je eerst de laatste levering en beoordeel je de wijziging opnieuw.