Bouw met onze beschikbaarheidsgegevens
Plek in de Veste API
Gebruik de opgeslagen beschikbaarheid van FC Twente thuiswedstrijden in je eigen website, overzicht of analyse.
De API combineert vrije verkoop en extra plaatsen via de kaartenmarkt. Je leest de opgeslagen stand: een verzoek haalt geen nieuwe gegevens op bij de ticketshop. Kaarten kopen gaat via FC Twente.
Basis-URL
https://plekindeveste.net/local-apiBegin met /season-availability voor aantallen van alle wedstrijden in één verzoek. Gebruik /events om wedstrijd-ID’s te vinden en /history voor het verloop door de tijd.
Vraag de API aan vanuit je eigen backend en bewaar het antwoord daar tijdelijk. Rechtstreekse JavaScript-verzoeken vanuit een ander domein worden momenteel niet ondersteund: deze API stuurt geen CORS-toestemming mee. cURL, Python en server-side JavaScript hebben die browserbeperking niet.
Een eerste verzoek
Codevoorbeelden
Deze voorbeelden lezen alleen opgeslagen gegevens. De veldnamen zijn hoofdlettergevoelig.
curl --fail --max-time 20 -H "Accept: application/json" \
"https://plekindeveste.net/local-api/season-availability"JavaScript · Node.js 18+
// Node.js 18+ (server-side)
const response = await fetch(
'https://plekindeveste.net/local-api/season-availability',
{ headers: { Accept: 'application/json' }, signal: AbortSignal.timeout(20000) }
);
if (!response.ok) throw new Error('HTTP ' + response.status);
const matches = await response.json();
for (const match of matches.filter(m => m.isCurrent)) {
const stand = match.availability;
console.log(match.Name, stand?.availableCount ?? 'Nog geen meting',
stand?.capturedAt, stand?.complete);
}Python 3
# Python 3, zonder extra pakketten
import json
from urllib.request import Request, urlopen
request = Request(
'https://plekindeveste.net/local-api/season-availability',
headers={'Accept': 'application/json'}
)
with urlopen(request, timeout=20) as response:
matches = json.load(response)
for match in matches:
if match['isCurrent']:
stand = match['availability']
print(match['Name'], stand if stand is not None else 'Nog geen meting')Importeer openapi.json in bijvoorbeeld een API-client. De voorbeelden hieronder zijn illustratief; aantallen en tijdstippen zijn geen live stand.
/season-historyVerloop van alle wedstrijden
Alle opgeslagen wedstrijden met hun volledige metingen in history. Filter op de wedstrijddatum voor het gewenste seizoen. Bevat alleen tellingen, geen stoelen.
curl --fail --max-time 20 "https://plekindeveste.net/local-api/season-history"Voorbeeldantwoord
[
{
"EventId": 371,
"Name": "FC Twente - PSV",
"EventStartDateTime": "2026-09-20T12:30:00",
"isCurrent": true,
"firstSeen": "2026-09-15T01:00:00.000Z",
"lastSeen": "2026-09-16T10:00:00.000Z",
"removedAt": null,
"lastCapturedAt": "2026-09-16T10:01:00.000Z",
"measurementCount": 12,
"history": [
{
"id": 123,
"started_at": "2026-09-16T10:00:00.000Z",
"captured_at": "2026-09-16T10:01:00.000Z",
"complete": 1,
"marketplace_status": "loaded",
"interval_minutes": 360,
"total_count": 28292,
"available_count": 120,
"regular_count": 80,
"marketplace_count": 45,
"marketplace_extra_count": 40
}
]
}
]/eventsWedstrijden
Alle opgeslagen wedstrijden, inclusief archief. Filter zelf op isCurrent voor het huidige aanbod. Activiteiten en vrouwenwedstrijden zijn uitgesloten. Er is geen paginering.
| Veld / parameter | Betekenis |
|---|---|
EventId | Gebruik dit nummer als eventId bij de andere endpoints. |
isCurrent | true = aanwezig in de laatst opgehaalde wedstrijdlijst. Dit zegt niet of de aftrap al is geweest. |
lastCapturedAt / measurementCount | Laatste meting (kan onvolledig zijn) en aantal opgeslagen metingen. null betekent nog geen meting. |
firstSeen / lastSeen / removedAt | Eerste en laatste keer gezien in het aanbod; tijdstip van archivering of null. |
HasTicketsAvailable / CurrentlyOnSaleForUser | Optionele verkoopvlaggen uit de bron. Gebruik availability of totals voor de getelde beschikbare plaatsen. |
curl --fail --max-time 20 "https://plekindeveste.net/local-api/events"Voorbeeldantwoord
[
{
"EventId": 371,
"Name": "FC Twente - PSV",
"EventStartDateTime": "2026-09-20T12:30:00",
"isCurrent": true,
"firstSeen": "2026-09-15T01:00:00.000Z",
"lastSeen": "2026-09-16T10:00:00.000Z",
"removedAt": null,
"lastCapturedAt": "2026-09-16T10:01:00.000Z",
"measurementCount": 12
}
]/season-availabilityBeschikbaarheid van alle wedstrijden
De lichtste keuze voor een overzicht met actuele aantallen. Eén antwoord met de wedstrijden en hun laatst bewaarde stand. Bevat ook archiefwedstrijden. Een seizoen loopt van juli tot en met juni; groepeer zelf op de Nederlandse aftrapdatum. Er is geen season-parameter.
| Veld / parameter | Betekenis |
|---|---|
availability | null als er nog geen meting is. Anders een object met capturedAt, complete en aantallen. |
totalCount | Getelde capaciteit bij deze stand; niet automatisch de officiële stadioncapaciteit. Dit endpoint bevat geen capacityKnown-vlag. Gebruik voor een betrouwbaar percentage het dashboard en controleer data.capacityKnown. |
availableCount | Totaal unieke beschikbare standaardplaatsen. |
regularCount | Beschikbaar via vrije verkoop. |
marketplaceExtraCount | Extra beschikbare plaatsen via de kaartenmarkt, zonder overlap met vrije verkoop. |
complete | true als de benodigde bronnen geladen zijn. Een expliciet gesloten kaartenmarkt hoeft niet te worden opgehaald. Bij voorkeur wordt een volledige meting teruggegeven, ook als een recentere poging onvolledig is. |
curl --fail --max-time 20 "https://plekindeveste.net/local-api/season-availability"Voorbeeldantwoord
[
{
"EventId": 371,
"Name": "FC Twente - PSV",
"EventStartDateTime": "2026-09-20T12:30:00",
"isCurrent": true,
"firstSeen": "2026-09-15T01:00:00.000Z",
"lastSeen": "2026-09-16T10:00:00.000Z",
"removedAt": null,
"lastCapturedAt": "2026-09-16T10:01:00.000Z",
"measurementCount": 12,
"availability": {
"capturedAt": "2026-09-16T10:01:00.000Z",
"complete": true,
"marketplaceStatus": "loaded",
"marketplaceInferredZero": false,
"totalCount": 28292,
"availableCount": 120,
"regularCount": 80,
"marketplaceExtraCount": 40
}
}
]/events/{eventId}/dashboardVakken en stoelen
Uitgebreid antwoord met stadionindeling, vakken, stoelen en tellingen. Gebruik dit alleen als je die details nodig hebt. Geeft bij voorkeur de laatste volledige meting; zonder volledige meting de laatste onvolledige. HTTP 404 als er geen opgeslagen meting is.
| Veld / parameter | Betekenis |
|---|---|
eventId · verplicht | EventId uit GET /events. Het voorbeeld 371 is geen vaste standaard. |
snapshotId · optioneel | ID van een eerdere meting uit de history-route van deze wedstrijd. Zonder deze parameter krijg je de laatste beschikbare stand. |
| Veld / parameter | Betekenis |
|---|---|
snapshot / latestAttempt | snapshot beschrijft de getoonde stand. latestAttempt beschrijft de nieuwste opgeslagen poging; die kan nieuwer en onvolledig zijn. |
data.totals | Gecombineerde tellingen: availableCount = regularAvailableCount + marketplaceExtraCount. marketplaceAvailableCount kan overlap bevatten. |
data.sections | Vakgegevens. VenueBuildingBlockId is het vak-ID; Name is de zichtbare vaknaam. Gebruik de naam niet als ID. |
data.sectionAvailability | Object met vak-ID’s als sleutels. Elk vak bevat tellingen, section en seatMap.Rows[].Columns[] met stoelen. |
PlacementTypeId / IsAvailableForSale | Tel uitsluitend stoelen met PlacementTypeId === 1. IsAvailableForSale geeft de gecombineerde beschikbaarheid aan. Andere types en X/Y-indelingsmarkeringen tellen niet mee. |
RegularAvailable / MarketplaceAvailable | Per stoel de beschikbaarheid per bron. Tel een stoel die in beide voorkomt maar één keer. |
capacityKnown / availabilityRate | Bij capacityKnown === false is de capaciteit niet volledig bekend. Gebruik dan geen percentage vrij. availabilityRate is een percentage van 0–100. |
AvailableSeats / HasMarketplaceTicketsAvailable | Bronvelden voor het ophalen, geen gecombineerde telling. AvailableSeats kan op de kaartenmarkt 0 zijn terwijl er wel aanbod is. |
curl --fail --max-time 20 "https://plekindeveste.net/local-api/events/371/dashboard"Voorbeeldantwoord · verkort
{
"snapshot": {
"id": 123,
"startedAt": "2026-09-16T10:00:00.000Z",
"capturedAt": "2026-09-16T10:01:00.000Z",
"complete": true
},
"latestAttempt": {
"capturedAt": "2026-09-16T10:01:00.000Z",
"complete": true
},
"data": {
"eventMeta": {
"EventId": 371,
"Name": "FC Twente - PSV",
"EventStartDateTime": "2026-09-20T12:30:00"
},
"totals": {
"availableCount": 120,
"regularAvailableCount": 80,
"marketplaceAvailableCount": 45,
"marketplaceExtraCount": 40
},
"marketplace": {
"status": "loaded",
"channelId": 7,
"message": "Beide bronnen geladen"
}
}
}/events/{eventId}/history-sectionsVak-ID’s voor historie
De beschikbare vakken voor historische selectie, met naam en tribune. Gebruik id als sectionId of in sectionIds. Geeft [] als er geen vakgegevens zijn.
| Veld / parameter | Betekenis |
|---|---|
eventId · verplicht | EventId uit GET /events. Het voorbeeld 371 is geen vaste standaard. |
curl --fail --max-time 20 "https://plekindeveste.net/local-api/events/371/history-sections"Voorbeeldantwoord
[
{
"id": 391427,
"name": "Vak 134",
"tribune": "Lange zijde"
}
]/events/{eventId}/historyHistorische metingen
Chronologisch gesorteerde metingen, oudste eerst. Zonder parameters: het hele stadion, alleen volledige metingen. Geeft [] bij ontbrekende historie. Geen datumfilter of paginering; filter en bewaar het resultaat zelf.
| Veld / parameter | Betekenis |
|---|---|
eventId · verplicht | EventId uit GET /events. Het voorbeeld 371 is geen vaste standaard. |
includeIncomplete · optioneel | Gebruik 1 om ook onvolledige metingen te ontvangen. Standaard uitgesloten, behalve bij sectionIds. |
sectionId · optioneel | Eén vak-ID. Bevat ook section_id, snapshot_id, name en aanvullende tellingen. Niet combineren met sectionIds. |
sectionIds · optioneel | Maximaal 200 komma-gescheiden vak-ID’s. Dubbele ID’s tellen eenmaal. Geeft opgetelde tellingen per meting. Bevat altijd ook onvolledige metingen, ongeacht includeIncomplete. complete=1 alleen als alle geselecteerde vakken aanwezig zijn en de snapshot volledig is. Niet combineren met sectionId. |
| Veld / parameter | Betekenis |
|---|---|
captured_at / started_at | Eind- en begintijd van deze meting, in UTC. |
complete | 1 = volledig, 0 = onvolledig. Anders dan de boolean complete bij dashboard en seizoenoverzicht. |
available_count | Totaal beschikbaar = regular_count + marketplace_extra_count. |
marketplace_count | Alle beschikbare kaartenmarktplaatsen, inclusief mogelijke overlap. Niet optellen bij regular_count. |
total_count | Getelde capaciteit, niet automatisch de volledige officiële stadioncapaciteit. |
interval_minutes | Geplande tijd tussen metingen; voor nieuwe hostingmetingen 360. Oudere metingen kunnen een andere waarde hebben. |
sectionIds met ontbrekende vakken | Tellingen kunnen gedeeltelijk zijn, of 0 als niets gevonden is. Gebruik alleen complete === 1 voor een volledige vergelijking; een onvolledige 0 betekent niet uitverkocht. |
curl --fail --max-time 20 "https://plekindeveste.net/local-api/events/371/history"/events/371/history?includeIncomplete=1
/events/371/history?sectionId=391427&includeIncomplete=1
/events/371/history?sectionIds=391427,390337Voorbeeldantwoord
[
{
"id": 123,
"started_at": "2026-09-16T10:00:00.000Z",
"captured_at": "2026-09-16T10:01:00.000Z",
"complete": 1,
"marketplace_status": "loaded",
"interval_minutes": 360,
"total_count": 28292,
"available_count": 120,
"regular_count": 80,
"marketplace_count": 45,
"marketplace_extra_count": 40
}
]/statusStatus van het ophalen
Informatie over de automatische ophaalplanning. Een GET start nooit een nieuwe ophaalronde. De publieke API kan alleen opgeslagen gegevens lezen.
| Veld / parameter | Betekenis |
|---|---|
intervalMinutes | 360: geplande tussenpoos per wedstrijd op de hosting. |
nextRunAt | Volgende uurbeurt voor de planning; niet noodzakelijk de volgende meting van jouw gekozen wedstrijd. |
running / cooldownUntil | Of er een ronde actief is en of er een API-pauze geldt. Een poging kan mislukken of later afronden. |
lastRun | Laatste ronde met status, startedAt, finishedAt en result, of null. Extra diagnosevelden kunnen aanwezig zijn. |
manualSyncAllowed | Op de openbare website altijd false. POST /sync is niet beschikbaar voor afnemers en geeft 403. |
curl --fail --max-time 20 "https://plekindeveste.net/local-api/status"Voorbeeldantwoord
{
"running": false,
"nextRunAt": "2026-09-16T11:00:00.000Z",
"intervalMinutes": 360,
"snapshotCount": 120,
"cooldownUntil": null,
"manualSyncAllowed": false,
"progress": null,
"lastRun": null
}Tellingen en tijdstippen
Gegevens begrijpen
Eén stoel telt één keer
vrije verkoop + extra kaartenmarkt = totaal beschikbaar. Het volledige kaartenmarktaantal kan stoelen bevatten die ook vrije verkoop worden aangeboden. Tel daarom alleen het extra kaartenmarktaantal op bij vrije verkoop. De tellingen omvatten standaardplaatsen, geen X/Y-markeringen of andere plaatssoorten.
Een gesloten kaartenmarkt is geen gemeten nul
ShowMarketplaceForEvent in de wedstrijdlijst geeft de huidige openingsstatus aan. Voor historische metingen gebruik je marketplace_status; in het seizoenoverzicht heet dit availability.marketplaceStatus. closed betekent dat de kaartenmarkt expliciet niet beschikbaar was en niet is opgehaald. loaded betekent dat de kaartenmarkt geladen is; nul is dan een geldige waarneming. unavailable is een ophaalfout. unknown betekent dat de openingsstatus niet werd vastgelegd.
De numerieke kaartenmarkttellingen blijven 0 bij een gesloten markt, zodat de totaaltelling blijft kloppen. Zonder eerder aangetoonde opening toon je ‘Nog niet geopend’ in plaats van 0 en teken je geen kaartenmarktmeetpunt. Voor een nul na een eerdere opening geldt de afgeleide markering hieronder. Leid uit oudere nulmetingen met unknown geen openingsdatum af. Gebruik de huidige wedstrijdvlag niet om oude metingen achteraf als gesloten te bestempelen.
Volledigheid en actualiteit
Controleer altijd complete en het tijdstip van de stand. Een ontbrekende meting (null of een lege lijst) is iets anders dan nul beschikbare plaatsen. Het dashboard en seizoenoverzicht geven bij voorkeur de laatste volledige stand. Een nieuwere onvolledige poging kan daardoor een later tijdstip hebben dan de getoonde stand.
Iedere wedstrijd is ongeveer eens per zes uur aan de beurt. Wedstrijden worden over de uren verdeeld. Bij zes wedstrijden wordt elk uur één wedstrijd opgehaald. Fouten, pauzes of wijzigingen in het wedstrijdprogramma kunnen de tussenpoos verlengen of verschuiven.
Tijdzones
Metingen gebruiken ISO 8601 met Z (UTC). EventStartDateTime kan geen tijdzone bevatten: behandel die waarde als UTC. Toon tijden met Europe/Amsterdam om zomer- en wintertijd mee te nemen. Zo is 2026-09-20T12:30:00 in Nederland 14:30.
Een nul na een eerdere opening
Een volledige meting met marketplace_status === 'closed' en nul kaartenmarktaanbod na een eerdere waargenomen opening wordt op de website als afgeleide nul weergegeven. Het seizoenendpoint geeft hiervoor availability.marketplaceInferredZero: true terug. Dit is geen gemeten nul: gebruik deze waarde niet als bewijs van verkochte kaarten of een gemeten daling.
De history-endpoints geven de opgeslagen bronstatus terug en bevatten geen marketplace_inferred_zero-veld. De website berekent die markering zelf uit de chronologische historie, vóór filtering op periode. Een eerdere opening is aangetoond door loaded of positief kaartenmarktaanbod. Een mislukte of onvolledige meting levert nooit een afgeleide nul op.
Samen zitten uit stoelgegevens
Er is geen apart endpoint voor combinaties. Gebruik de dashboardstoelen voor groepen van 2, 3 of 4 beschikbare standaardplaatsen in dezelfde rij, met opeenvolgende Column-waarden. Stoelnummers bewijzen geen fysieke aansluiting. Alle stoelen van een combinatie moeten via dezelfde bron beschikbaar zijn: allemaal RegularAvailable of, bij een geladen kaartenmarkt, allemaal MarketplaceAvailable. Een combinatie met aanbod uit verschillende bronnen is niet gezamenlijk boekbaar. Sla vakken met onbekende capaciteit over en controleer eventuele MarketplaceBundled-voorwaarden in de ticketshop.
Wedstrijdmetadata en opgeslagen details
HomeImageUrl, AwayImageUrl en EventTypeLogoUrl zijn optionele bronvelden; oudere wedstrijden kunnen deze missen. De website kan ontbrekende logo's voor de weergave aanvullen. De API wijzigt daarvoor de opgeslagen metadata niet. data.eventMeta in het dashboard bevat de metadata bij die meting; /events bevat de laatst opgeslagen wedstrijdlijst.
Compatibiliteitsvelden zoals data.events, salesChannels, salesPeriods, ticketTypes en categoryPrices zijn in nieuwe opgeslagen dashboards lege lijsten; filters is een leeg object. Gebruik de getelde beschikbaarheid en stoelvelden. De gewijzigde interne databaseopslag verandert de publieke JSON-structuur niet.
Historie is geen verkoopteller
Een afname kan verkoop, een reservering of ingetrokken aanbod zijn. Vergelijk alleen volledige metingen met dezelfde getelde capaciteit en zonder te grote meetonderbreking. Voor veranderingen in kaartenmarkt en totaal moeten beide eindpunten bruikbare kaartenmarktwaarnemingen bevatten: loaded, of positief aanbod bij een oudere onbekende status. Ontbrekende brongegevens en afgeleide nullen mogen geen gemeten stijging of daling opleveren. Verandering in de vrije verkoop kan bij vergelijkbare volledige metingen wel afzonderlijk worden berekend. Uit een verschil over zes uur kun je niet afleiden in welk afzonderlijk uur kaarten zijn verkocht.
Praktische afspraken
Fouten en zorgvuldig gebruik
| Veld / parameter | Betekenis |
|---|---|
200 | Verzoek geslaagd. Het antwoord kan een lege lijst bevatten. |
400 | Ongeldige vakselectie, bijvoorbeeld sectionId en sectionIds samen. |
403 | Publieke bezoekers kunnen geen ophaalronde starten via POST /sync. |
404 | Onbekende route, niet-ondersteunde methode of geen opgeslagen dashboardmeting. |
500 / 503 | Gegevens of hosting tijdelijk niet beschikbaar. |
502 / 504 | De hosting kan een gatewayfout geven, eventueel als HTML in plaats van JSON. |
{
"error": "Opgeslagen gegevens zijn tijdelijk niet beschikbaar."
}- Bewaar antwoorden lokaal en stem verversen af op de zesuursplanning. Gebruik het lichte seizoenendpoint als je alleen totalen nodig hebt.
- Voer verzoeken achter elkaar uit. Haal geen volledige stoeloverzichten op voor een lijst met alleen aantallen.
- Controleer eerst de HTTP-status voordat je JSON verwerkt. Gebruik een timeout en hooguit enkele herpogingen met oplopende wachttijd bij tijdelijke fouten. Respecteer een eventuele
Retry-After. - Er is geen vaste publieke verzoeklimiet of beschikbaarheidsgarantie vastgelegd. De hosting kan verzoeken begrenzen.
- Toon bij hergebruik de datum van de stand. Een link naar Plek in de Veste als bron wordt gewaardeerd.
Deze website is een onafhankelijke tool. De API biedt geen reserverings- of aankoopfunctie en garandeert niet dat een getoonde stoel nog te koop is.