Naar de inhoud

Developers

Eén ondertekende webhook. Schone JSON, met je eigen velden als sleutels.

Als een document is goedgekeurd, stuurt Vink de data als één JSON-POST naar je endpoint. Op deze pagina staat alles wat je nodig hebt om de ontvanger te bouwen.

Overzicht

Een Integration is een HTTPS-endpoint dat je in Vink toevoegt en aan één of meer formulieren koppelt. Als een document van dat formulier wordt goedgekeurd, door een mens of door Auto-Send, stuurt Vink één Delivery naar elke gekoppelde Integration.

De body is de Payload: de waarden van het document met de velden van het formulier als sleutels, in een kleine envelope. Elk verzoek is ondertekend, zodat je ontvanger kan controleren dat het van Vink komt.

  • Eén POST per Delivery, Content-Type: application/json
  • Ondertekend met HMAC-SHA256 in de header X-Vink-Signature
  • Ongeveer 8 uur lang opnieuw geprobeerd bij timeouts, 408, 429 en 5xx
  • At-least-once: ontdubbel op deliveryId

Vink leest pdf's met Gemini op Vertex AI, EU-regio.

Documenten naar binnen krijgen

Documenten komen vandaag via de app binnen: upload meerdere pdf's tegelijk, of mail ze in. Geen code? Laat een systeem mailen naar het Intake Address van het formulier, en elke pdf-bijlage wordt een document. Er is nog geen upload-API. Heb je die nodig? Laat het ons weten.

Envelope

Dit is een echte Payload van een demoformulier Invoices, met een lijstveld voor de factuurregels. De sleutels onder data zijn je eigen veldsleutels, dus elk formulier heeft zijn eigen vorm.

POSThttps://your-system.example/vink
{
  "event": "document.approved",
  "deliveryId": "dlv_3f6c2a1e-8b4d-4e2f-9a71-5c0d8e7b2f14",
  "test": false,
  "document": {
    "id": "k97d4m2x8q1v6c3n5b0e7h9r2t4w8a1f",
    "filename": "invoice-F-2026-0418.pdf",
    "uploadedAt": "2026-09-30T08:12:04.000Z"
  },
  "form": {
    "id": "jd72k9m3x5q8v1c4n6b0e3h7r2t9w5as",
    "version": 3
  },
  "approval": {
    "mode": "manual",
    "by": "k1754bq2m9x6c8v3n0b5e7h1r4t2w6yd",
    "at": "2026-09-30T08:14:51.000Z"
  },
  "data": {
    "supplier_name": "Drukkerij Hoekstra B.V.",
    "invoice_number": "F-2026-0418",
    "invoice_date": "2026-09-14",
    "purchase_order": null,
    "total_excl_vat": 1240,
    "vat_amount": 260.4,
    "iban": "NL91ABNA0417164300",
    "paid": false,
    "lines": [
      {
        "description": "Flyers A5, 5,000",
        "quantity": 5000,
        "amount": 740
      },
      {
        "description": "Posters A2, 200",
        "quantity": 200,
        "amount": 500
      }
    ],
    "credit_notes": []
  }
}

Drie regels waar je parser op kan rekenen

  • Elke sleutel is er altijd, ook bij optionele velden.
  • null betekent geen waarde.
  • [] betekent een lijst zonder regels.
SleutelBetekenis
eventAltijd document.approved.
deliveryIdUniek per Delivery. Blijft gelijk als een Delivery opnieuw wordt geprobeerd of opnieuw verstuurd, dus gebruik het om te ontdubbelen.
testtrue bij een test-send, false bij een echte Delivery.
documentHet id van het document, de bestandsnaam en wanneer het is geüpload (ISO 8601, UTC).
formHet id van het formulier en de formulierversie waarmee het document is gelezen.
approvalmanual of auto (Auto-Send), het id van de gebruiker die goedkeurde (null bij Auto-Send) en wanneer.
dataDe waarden, per veld. Getallen zijn getallen, datums zijn YYYY-MM-DD, ja/nee-velden zijn booleans en lijsten zijn arrays van objecten.

Handtekening controleren

Elk verzoek heeft een header met een tijdstempel en een HMAC-SHA256-handtekening. Elke Integration heeft een eigen secret dat begint met whsec_. Je vindt het bij de Integration in de app.

X-Vink-Signature: t=1790757291,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

Zo controleer je een verzoek

  1. Splits de header op komma's en lees t (Unix-seconden) en v1 (hex).
  2. Bereken HMAC-SHA256 met je secret over de string {t}.{rawBody}: de tijdstempel, een punt en de ruwe body precies zoals ontvangen.
  3. Vergelijk je uitkomst met v1 met een vergelijking in constante tijd.
  4. Weiger het verzoek als t meer dan 5 minuten van je eigen klok afwijkt. Zo kan een onderschept verzoek niet opnieuw worden afgespeeld.

Gebruik de ruwe bytes van de body. Als je de JSON parset en opnieuw serialiseert, veranderen witruimte en volgorde, en klopt de handtekening niet meer.

Node.js
import crypto from "node:crypto";

const TOLERANCE_SECONDS = 5 * 60;

// rawBody: the request body exactly as received (a Buffer or string),
// before any JSON parsing. With Express: express.raw({ type: "application/json" }).
export function verifyVink(rawBody, header, secret) {
  const parts = Object.fromEntries(
    (header ?? "").split(",").map((part) => part.trim().split("=", 2)),
  );
  const timestamp = Number(parts.t);
  if (!Number.isInteger(timestamp) || !parts.v1) return false;

  const age = Math.abs(Date.now() / 1000 - timestamp);
  if (age > TOLERANCE_SECONDS) return false;

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.`)
    .update(rawBody)
    .digest();
  const received = Buffer.from(parts.v1, "hex");
  return received.length === expected.length && crypto.timingSafeEqual(received, expected);
}

// if (!verifyVink(req.body, req.get("X-Vink-Signature"), process.env.VINK_SECRET)) {
//   return res.status(401).end();
// }

Bezorging en nieuwe pogingen

Vink wacht maximaal 15 seconden op je antwoord.

Jouw antwoordWat Vink doet
Elke 2xxBezorgd.
Timeout, netwerkfout, 408, 429 of 5xxOpnieuw geprobeerd na ongeveer 1 minuut, 5 minuten, 30 minuten, 2 uur en 6 uur: 6 pogingen in ongeveer 8 uur.
Elke andere 4xxMeteen mislukt. Een Admin kan een mislukte Delivery opnieuw versturen vanuit de app.

Een Retry-After-header (seconden of een HTTP-datum) wordt gerespecteerd, tot 24 uur.

Redirects worden niet gevolgd. Je endpoint moet HTTPS gebruiken.

Bezorging is at-least-once. Dezelfde Delivery kan twee keer aankomen, bijvoorbeeld als je ontvanger hem opsloeg maar een timeout gaf voordat hij antwoordde. Bewaar deliveryId en sla een Delivery over die je al hebt verwerkt.

Headers

Je kunt eigen headers aan een Integration toevoegen, zoals een API-sleutel of Basic auth. Markeer een header als geheim en de waarde wordt versleuteld opgeslagen en daarna alleen gemaskeerd getoond. Vink zet Content-Type en X-Vink-Signature zelf.

Vink · Document · Deliveries

Test-send

Stuur vanuit een Integration een test naar je endpoint voordat er een echt document weggaat. Kies voorbeeldwaarden voor elk veld, of lege waarden zodat je ontvanger null en [] ziet. Je kunt ook een goedgekeurd document opnieuw als test versturen.

Een test heeft "test": true, is net zo ondertekend als een echte en is nooit een Delivery: hij wordt niet opnieuw geprobeerd en staat niet in de bezorglog van een document. Het antwoord van je endpoint zie je meteen.

Vink · Integrations

Koppelservice

Geen developer, of geen tijd? Rob bouwt de koppeling voor je.

Een eenmalige klus, nooit onderdeel van een abonnement. Rob schrijft de ontvanger die de Payload in je systeem zet, of dat nu een ERP, boekhoudpakket, spreadsheet of database is, en richt samen met jou je formulieren in.

Wat je krijgt

  • Een ontvanger die de handtekening controleert en de data in je systeem zet
  • Je formulieren en velden samen ingericht, getest op je eigen documenten
  • Jij host het, of Rob host het op verzoek voor een vast bedrag per maand
  • Onderhoud en aanpassingen later, per klus gefactureerd

Wat we van je nodig hebben

  • In welk systeem de data moet komen, en toegang tot een testomgeving
  • Een paar voorbeelddocumenten
  • Eén persoon die weet hoe de data gebruikt wordt

Vanaf €950 per koppeling, excl. btw

Een vaste prijs, afgesproken voordat we beginnen.

Vraag naar een koppeling

Vertel ons iets over je systeem en documenten. Rob antwoordt persoonlijk.

We gebruiken je gegevens alleen om te antwoorden. Je aanvraag wordt naar ons gemaild en niet op de site bewaard.