Naar de inhoud
Hulpmiddelen
Gratis

Complete cursus · 100% gratis

De theoriecursus

  • 9 lessen
  • 4 hoofdstukken
  • 1 uur 21 in totaal
  • quizzen met uitleg
Begin met les 1

Rechts houden: waar op de weg mag jij rijden? · 10 min

Wanneer is je theorie-examen?

Theorie Rijbewijs · Open data

De openbare API van Theorie Rijbewijs

Documentatie van de openbare API van Theorie Rijbewijs: zoeken, documenten, bronnen, controledata, paginering, limieten en voorbeelden om te kopiëren.

Markdown-versie · OpenAPI 3.1

De adressen

VerzoekAntwoord
GET https://theorie-rijbewijs.nl/api/v1/De catalogus: beschrijving, aantal documenten per aard, links.
GET https://theorie-rijbewijs.nl/api/v1/factsHet zoeken: {results, total, limit, offset}.
GET https://theorie-rijbewijs.nl/api/v1/facts/{id}Eén document, met zijn herkomst.
GET https://theorie-rijbewijs.nl/api/v1/openapi.jsonDe OpenAPI 3.1-beschrijving.

De zoekparameters

Het eerste verzoek wordt doorgestuurd (307) naar hetzelfde adres met po_live=1, voor een altijd actuele weergave: volg de redirect (curl: --location). Codes: 200, 307, 400 (ongeldige parameter), 404 (onbekend document), 405 (methode geweigerd), 429 (limiet bereikt, zie Retry-After), 503 (dienst niet beschikbaar).

Vanuit een browser

Openbare CORS voor GET, zonder cookie of sleutel: gebruik credentials: 'omit'. De header Retry-After is leesbaar vanaf een andere site. Om de hele catalogus te lezen, doorloop je de API pagina voor pagina en ontdubbel je op id.

Voorbeelden om te kopiëren

Zoeken met curl

Dit openbare verzoek geeft maximaal drie documenten terug, met hun tekst en verwijzingen. Een sleutel is niet nodig.

curl --location --fail --silent --show-error --get \
  'https://theorie-rijbewijs.nl/api/v1/facts' \
  --header 'Accept: application/json' \
  --data-urlencode 'q=theorie-examen' \
  --data 'kind=fact' \
  --data 'limit=3'

Documenten en hun bronnen op een pagina tonen

Zet dit JavaScript na de inhoud van je pagina, in een script van het type module. Het toont de teksten, een zichtbare bronvermelding en de verwijzingen met veilige links, zonder cookie of sleutel.

await (async () => {
  const section = document.createElement('section');
  section.setAttribute('aria-label', 'Informatie van ' + "Theorie Rijbewijs");
  const status = document.createElement('p');
  status.setAttribute('role', 'status');
  status.textContent = 'Informatie wordt geladen…';
  section.append(status);
  document.body.append(section);

  const link = (label, address) => {
    const text = String(label || address || 'Referentie');
    try {
      const url = new URL(address);
      if (!['https:', 'http:'].includes(url.protocol)) throw new Error();
      const anchor = document.createElement('a');
      anchor.textContent = text;
      anchor.href = url.href;
      return anchor;
    } catch {
      const span = document.createElement('span');
      span.textContent = text;
      return span;
    }
  };

  try {
    const url = new URL('https://theorie-rijbewijs.nl/api/v1/facts');
    url.search = new URLSearchParams({ q: 'theorie-examen', kind: 'fact', limit: '3' });
    const response = await fetch(url, {
      credentials: 'omit',
      headers: { Accept: 'application/json' },
      signal: AbortSignal.timeout(15000)
    });
    if (!response.ok) {
      if (response.status === 429) {
        const retry = Number(response.headers.get('Retry-After'));
        throw new Error(Number.isFinite(retry) && retry > 0
          ? `Limiet bereikt. Probeer het over ${Math.ceil(retry)} seconden opnieuw.`
          : 'Limiet bereikt. Probeer het over een minuut opnieuw.');
      }
      throw new Error(`De informatie is niet beschikbaar (HTTP ${response.status}).`);
    }
    const data = await response.json();
    if (!Array.isArray(data.results)) throw new Error('Het ontvangen antwoord is ongeldig.');
    for (const record of data.results) {
      const article = document.createElement('article');
      const title = document.createElement('h2');
      title.textContent = record.title;
      const text = document.createElement('p');
      text.textContent = record.text;
      text.style.whiteSpace = 'pre-line';
      const attribution = document.createElement('p');
      attribution.append('Bron: ', link("Theorie Rijbewijs" + ', bekijk dit document', record.url));
      article.append(title, text, attribution);
      if (record.verified_at) {
        const date = document.createElement('p');
        date.textContent = `Gepubliceerde controledatum: ${record.verified_at}`;
        if (record.verification_scope) date.textContent += ` · ${record.verification_scope}`;
        article.append(date);
      }
      const references = document.createElement('ul');
      for (const source of record.sources || []) {
        const item = document.createElement('li');
        item.append(link(source.label || source.title || source.url, source.url));
        references.append(item);
      }
      for (const reference of record.bibliography || []) {
        const item = document.createElement('li');
        item.textContent = reference;
        references.append(item);
      }
      if (references.childElementCount) article.append(references);
      for (const related of record.related || []) {
        const context = document.createElement('p');
        context.append('Lees hierbij ook: ', link(related.title, related.url), ` ${related.text || ''}`);
        article.append(context);
      }
      section.append(article);
    }
    status.textContent = data.results.length ? `${data.results.length} document(en) getoond.` : 'Geen document gevonden.';
  } catch (error) {
    status.textContent = error.name === 'TimeoutError'
      ? 'Het laden duurt te lang. Probeer het zo meteen opnieuw.'
      : error.message || 'Het laden is mislukt.';
  }
})();

Resultaten doorlopen in Python 3

Je hoeft geen bibliotheek te installeren. Elke regel uitvoer bevat een volledig document met zijn URL en bronnen. De paginering stopt bij het laatste resultaat. Na een 429-antwoord houdt het script zich aan Retry-After. Het probeert het hoogstens drie keer opnieuw en stopt als de gevraagde wachttijd langer is dan een minuut.

import json
import time
from email.utils import parsedate_to_datetime
from urllib.error import HTTPError
from urllib.parse import urlencode
from urllib.request import Request, urlopen

API = "https://theorie-rijbewijs.nl/api/v1/facts"

def request_json(url):
    for attempt in range(4):
        try:
            request = Request(url, headers={"Accept": "application/json"})
            with urlopen(request, timeout=15) as response:
                return json.load(response)
        except HTTPError as error:
            retry_after = error.headers.get("Retry-After", "")
            status = error.code
            error.close()
            if status != 429 or attempt == 3:
                raise RuntimeError(f"Verzoek onderbroken: HTTP {status}") from error
            try:
                delay = float(retry_after)
            except ValueError:
                try:
                    delay = parsedate_to_datetime(retry_after).timestamp() - time.time()
                except (ValueError, TypeError, OverflowError):
                    delay = 2 ** attempt
            if not 0 <= delay <= 60:
                raise RuntimeError("Wachttijd te lang. Hervat het ophalen later.") from error
            time.sleep(max(1, delay))

def iter_records(query="theorie-examen"):
    offset = 0
    while offset <= 10000:
        params = {"q": query, "kind": "fact", "limit": 50, "offset": offset}
        page = request_json(API + "?" + urlencode(params))
        rows, total = page["results"], page["total"]
        if not isinstance(rows, list) or not isinstance(total, int):
            raise RuntimeError("Ongeldig API-antwoord.")
        if not rows:
            if offset < total:
                raise RuntimeError("Lege pagina voordat de resultaten op zijn.")
            return
        yield from rows
        offset += len(rows)
        if offset >= total:
            return
    raise RuntimeError("Paginalimiet bereikt. Maak je zoekopdracht specifieker.")

if __name__ == "__main__":
    for record in iter_records():
        print(json.dumps(record, ensure_ascii=False))

De actuele versie van een gegeven terugvinden

De API en de MCP-server geven toegang tot de openbare publicaties van Theorie Rijbewijs. De documenten volgen de updates van de site, met een link naar de oorspronkelijke pagina en de bijbehorende bronnen.

Lees voordat je antwoordt of je tool bijwerkt de relevante documenten opnieuw: je vindt hun online versie, hun bronnen en hun data. Een officiële regel kan veranderen: de controledatum zegt wanneer de regel voor het laatst in de wettekst is nagelezen.

Hergebruiken met bronvermelding

De openbare inhoud van Theorie Rijbewijs mag worden bekeken, geciteerd en samengevat om een antwoord te onderbouwen of een tool te bouwen, ook voor commercieel gebruik, met zichtbare bronvermelding en een link naar de gebruikte pagina: ‘Bron: Theorie Rijbewijs’.

Bewaar de bronnen en de voorbehouden die bij de informatie horen. Vermeld welke aanpassingen je hebt gedaan en maak onderscheid tussen de officiële regels en de uitleg, de methode en het aanbod van Theorie Rijbewijs.

Documenten en beeldmateriaal van derden vallen onder hun eigen voorwaarden. Wil je een cursus of artikel volledig opnieuw publiceren, vraag dan toestemming via contact@theorie-rijbewijs.nl. Toegang tot de gegevens betekent niet dat Theorie Rijbewijs of Permis Online SRL met jou samenwerkt of jouw dienst goedkeurt.