Bouw je eigen boek-frontend
De publieke API van het VenueFlow-boekingsplatform. Gebruikt een venue VenueFlow, dan haal je hiermee faciliteiten en beschikbare tijden op en maak je boekingen aan — alles wat je nodig hebt voor een eigen reserveer-scherm. Het is dezelfde API die onze widget gebruikt.
X-Tenant-header.
Authenticatie & CORS
De publieke endpoints hebben geen API-sleutel. Je geeft per aanroep de venue op via de
X-Tenant-header, met de slug van de venue:
X-Tenant: sauna-de-bron
https://www.jouwvenue.nl) op de toegestane origins
van de venue in de admin. Draait je frontend op een eigen API-domein
(bijv. boeken.jouwvenue.nl), dan is het same-origin en heb je geen CORS-config nodig.
Tijden zijn lokale tijd van de venue (geen tijdzone-suffix, bijv. 2026-09-01T09:00). Bedragen in euro.
De boek-flow in 3 stappen
| # | Stap | Endpoint |
|---|---|---|
| 1 | Toon wat de venue aanbiedt | GET /api/site/facilities |
| 2 | Toon vrije tijden op een dag | GET /api/site/facilities/{id}/slots |
| 3 | Maak de boeking (evt. betalen) | POST /api/site/bookings |
Faciliteiten ophalen
Alle boekbare faciliteiten, plus de dag-grens en extra velden die de venue verzamelt.
Request
curl https://api.venueflow.eu/api/site/facilities \ -H "X-Tenant: sauna-de-bron"
const res = await fetch("https://api.venueflow.eu/api/site/facilities", {
headers: { "X-Tenant": "sauna-de-bron" }
});
const { facilities, fields } = await res.json(); Antwoord 200 OK
{
"live": true,
"day_start": "00:00",
"facilities": [
{
"id": 1,
"name": "Privésauna",
"mode": "FULL", // FULL = exclusief · CAPACITY = meerdere gasten
"capacity": 1,
"duration_minutes": 90,
"price_eur": 45, // per persoon (0 = gratis)
"open_days": [1,2,3,4,5,6,7] // 1 = maandag … 7 = zondag
}
],
"fields": [
{ "key": "telefoon", "label": "Telefoon", "type": "tel", "required": true }
]
} | Veld | Betekenis |
|---|---|
live | Neemt de venue online boekingen aan? Zo niet: toon een "binnenkort"-melding. |
mode | CAPACITY (meerdere gasten) of FULL (privé/exclusief). |
open_days | Open weekdagen, 1 = maandag … 7 = zondag. |
fields | Extra velden (text/tel/select/checkbox/textarea) — meesturen in extra. |
Beschikbare tijden ophalen
De boekbare tijdslots van één faciliteit op een gekozen dag.
Request
curl "https://api.venueflow.eu/api/site/facilities/2/slots?date=2026-09-01" \ -H "X-Tenant: sauna-de-bron"
const res = await fetch(
"https://api.venueflow.eu/api/site/facilities/2/slots?date=2026-09-01",
{ headers: { "X-Tenant": "sauna-de-bron" } }
);
const { slots } = await res.json(); Antwoord 200 OK
{
"facility": "Wellness dagpas",
"date": "2026-09-01",
"slots": [
{ "id": 2101, "starts_at": "2026-09-01T09:00", "ends_at": "2026-09-01T10:00",
"free": 17, "capacity": 20, "bookable": true },
{ "id": 2102, "starts_at": "2026-09-01T10:00", "ends_at": "2026-09-01T11:00",
"free": 0, "capacity": 20, "bookable": false }
]
} bookable om te bepalen of een tijd te kiezen is (true = niet vol, niet geblokkeerd).
free is het aantal resterende plekken — handig voor "nog 2 vrij".Beschikbaarheid per dag (bereik)
Per dag over een bereik: is er iets te boeken en hoeveel vrij. Ideaal om in een kalender in één keer volle en gesloten dagen te dimmen — zonder per dag een aparte call. Bereik max 62 dagen.
curl "https://api.venueflow.eu/api/site/facilities/2/availability?from=2026-09-01&to=2026-09-30" \ -H "X-Tenant: sauna-de-bron"
Antwoord 200 OK
{
"facility": "Wellness dagpas",
"from": "2026-09-01", "to": "2026-09-30",
"days": [
{ "date": "2026-09-01", "free": 42, "bookable": true },
{ "date": "2026-09-02", "free": 0, "bookable": false }, // vol of gesloten
{ "date": "2026-09-03", "free": 18, "bookable": true }
]
} Eén slot herverifiëren
Check vlak vóór het boeken of een specifiek slot nog vrij is — lichter dan de hele dag-lijst. Handig voor een "nog vrij?"-knop of een laatste check vlak voor submit.
curl "https://api.venueflow.eu/api/site/slots/2101" \ -H "X-Tenant: sauna-de-bron"
Antwoord 200 OK
{
"id": 2101, "facility_id": 2,
"starts_at": "2026-09-01T09:00", "ends_at": "2026-09-01T10:00",
"capacity": 20, "free": 17, "bookable": true
} Boeking aanmaken
Maakt een boeking op een tijdslot. Stuur de velden uit fields mee in extra.
Request
curl -X POST https://api.venueflow.eu/api/site/bookings \
-H "X-Tenant: sauna-de-bron" \
-H "Content-Type: application/json" \
-d '{
"slot_id": 2101,
"customer_name": "Petra Jansen",
"customer_email": "petra@voorbeeld.nl",
"people": 2,
"extra": { "telefoon": "0612345678" },
"redirect_url": "https://www.jouwvenue.nl/bedankt"
}' const res = await fetch("https://api.venueflow.eu/api/site/bookings", {
method: "POST",
headers: {
"X-Tenant": "sauna-de-bron",
"Content-Type": "application/json"
},
body: JSON.stringify({
slot_id: 2101,
customer_name: "Petra Jansen",
customer_email: "petra@voorbeeld.nl",
people: 2,
extra: { telefoon: "0612345678" },
redirect_url: "https://www.jouwvenue.nl/bedankt"
})
});
const { booking, payment } = await res.json();
if (payment?.checkout_url) location.href = payment.checkout_url; // naar betalen | Veld | Omschrijving |
|---|---|
slot_id verplicht | Het id van het gekozen slot. |
customer_name verplicht | Naam van de gast. |
customer_email verplicht | E-mail voor de bevestiging. |
people | Aantal personen (bij CAPACITY). Standaard 1. |
extra | Object met venue-velden: { key: waarde }. |
redirect_url | Waar de gast na betalen terugkomt. |
Antwoord 201 Created
{
"booking": { "id": 812, "status": "pending_payment", "amount_eur": 55, … },
"ticket_url": "https://app.venueflow.eu/ticket?t=…", // bekijken/annuleren
"payment": { // alleen als er betaald moet worden
"status": "open",
"checkout_url": "https://pay.mollie.com/…"
}
} payment in het antwoord? Dan is de boeking meteen bevestigd
(gratis of geen betaalkoppeling) — toon direct je bedankscherm. De ticket_url is een getekende link
naar de ticketpagina (bekijken/annuleren) die je aan de gast kunt tonen of mailen.Dit open endpoint is afgeremd op max 20 boekingen per IP per uur (anders 429).
Foutafhandeling
Fouten komen als JSON met een error-tekst en een passende HTTP-status:
{ "error": "Deze venue is nog niet live." } | Status | Betekenis |
|---|---|
200 / 201 | Gelukt. |
400 | Geen venue opgegeven — X-Tenant ontbreekt. |
404 | Niet gevonden — bijv. onbekend faciliteit-id. |
422 | Validatiefout, venue niet live, of slot vol. |
429 | Te veel boekingen vanaf dit IP (max 20/uur). |
Liever niet zelf bouwen?
Gebruik de kant-en-klare VenueFlow-widget — één regel HTML, drie stijlen (weekstrip, kalender, dagbalk), instelbare kleur. Praat met exact dezelfde API.
<!-- kies variant: strip · calendar · timeline --> <venueflow-booking tenant="sauna-de-bron" api="https://api.venueflow.eu" variant="strip" accent="#0f766e"></venueflow-booking> <script src="https://venueflow.nl/widget/venueflow-widget.js"></script>
Kant-en-klare pakketten
Voor de meeste platforms hoef je niets te bouwen — pak een pakket en vul je tenant en api in.
WordPress
Installeer de plugin (Plugins → Nieuw → Upload) en plaats [venueflow]. Kleur en variant stel je in bij Instellingen → VenueFlow.
React / Next.js
Eén component in components/. Props: variant, accent, radius.
Zie ook de installatie-README. Alle pakketten laden dezelfde kern
(https://venueflow.nl/widget/venueflow-widget.js) en praten met de API op https://api.venueflow.eu.