Ir al contenido
Recursos
¿Quiénes somos?Quién edita TestAutoescuela y cómo se verifica cada lección
Gratis

Temario completo · 100 % gratis

El temario del teórico

  • 14 lecciones
  • 5 capítulos
  • 2 h 13 min en total
  • tests corregidos
Empezar la lección 1

Las partes de la vía: calzada, carril, arcén, acera y más · 9 min

¿Cuándo es tu examen teórico?

TestAutoescuela · Datos

La API pública de TestAutoescuela

Documentación de la API pública de TestAutoescuela: búsqueda, fichas, fuentes, fechas de verificación, paginación, límites y ejemplos listos para copiar.

Versión Markdown · OpenAPI 3.1

Las direcciones

SolicitudRespuesta
GET https://testautoescuela.es/api/v1/El catálogo: descripción, número de fichas por naturaleza, enlaces.
GET https://testautoescuela.es/api/v1/factsLa búsqueda: {results, total, limit, offset}.
GET https://testautoescuela.es/api/v1/facts/{id}Una ficha, con su procedencia.
GET https://testautoescuela.es/api/v1/openapi.jsonLa descripción OpenAPI 3.1.

Los parámetros de la búsqueda

La primera solicitud se redirige (307) a la misma dirección con po_live=1, para una lectura siempre actualizada: seguir la redirección (curl: --location). Códigos: 200, 307, 400 (parámetro no válido), 404 (ficha desconocida), 405 (método rechazado), 429 (límite alcanzado, ver Retry-After), 503 (servicio no disponible).

Desde un navegador

CORS público para GET, sin cookie ni clave: usar credentials: 'omit'. La cabecera Retry-After se puede leer desde otro sitio. Para leer todo el catálogo, recorrer la API página a página y eliminar los duplicados por identificador.

Ejemplos listos para copiar

Una búsqueda con curl

Esta solicitud pública devuelve hasta tres fichas, su texto y sus referencias. No hace falta ninguna clave.

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

Mostrar fichas y sus fuentes en una página

Coloca este JavaScript después del contenido de tu página, en un script de tipo módulo. Muestra los textos, una atribución visible y las referencias con enlaces seguros, sin cookies ni clave.

await (async () => {
  const section = document.createElement('section');
  section.setAttribute('aria-label', 'Información de ' + "TestAutoescuela");
  const status = document.createElement('p');
  status.setAttribute('role', 'status');
  status.textContent = 'Cargando la información…';
  section.append(status);
  document.body.append(section);

  const link = (label, address) => {
    const text = String(label || address || 'Referencia');
    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://testautoescuela.es/api/v1/facts');
    url.search = new URLSearchParams({ q: '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
          ? `Límite alcanzado. Vuelve a intentarlo dentro de ${Math.ceil(retry)} segundos.`
          : 'Límite alcanzado. Vuelve a intentarlo dentro de un minuto.');
      }
      throw new Error(`La información no está disponible (HTTP ${response.status}).`);
    }
    const data = await response.json();
    if (!Array.isArray(data.results)) throw new Error('La respuesta recibida no es válida.');
    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('Fuente: ', link("TestAutoescuela" + ', consultar esta ficha', record.url));
      article.append(title, text, attribution);
      if (record.verified_at) {
        const date = document.createElement('p');
        date.textContent = `Fecha de verificación publicada: ${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('Para leer junto con esta ficha: ', link(related.title, related.url), ` ${related.text || ''}`);
        article.append(context);
      }
      section.append(article);
    }
    status.textContent = data.results.length ? `${data.results.length} ficha(s) mostrada(s).` : 'No se ha encontrado ninguna ficha.';
  } catch (error) {
    status.textContent = error.name === 'TimeoutError'
      ? 'La carga tarda demasiado. Vuelve a intentarlo en un instante.'
      : error.message || 'La carga ha fallado.';
  }
})();

Recorrer los resultados en Python 3

No hay que instalar ninguna biblioteca. Cada línea de salida contiene una ficha completa con su URL y sus fuentes. La paginación se detiene en el último resultado. Tras una respuesta 429, el script respeta Retry-After, con tres reintentos como máximo y una parada si la espera solicitada supera un minuto.

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://testautoescuela.es/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"Solicitud interrumpida: 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("Espera demasiado larga. Reanuda la recopilación más tarde.") from error
            time.sleep(max(1, delay))

def iter_records(query="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("Respuesta de la API no válida.")
        if not rows:
            if offset < total:
                raise RuntimeError("Página vacía antes del final de los resultados.")
            return
        yield from rows
        offset += len(rows)
        if offset >= total:
            return
    raise RuntimeError("Límite de paginación alcanzado. Precisa la búsqueda.")

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

Encontrar la versión actual de una información

La API y el servidor MCP dan acceso a las publicaciones públicas de TestAutoescuela. Las fichas siguen las actualizaciones del sitio, con un enlace a la página de origen y las referencias asociadas.

Antes de responder o de actualizar tu herramienta, vuelve a leer las fichas que te sirvan: encontrarás su versión en línea, sus fuentes y sus fechas. Una norma oficial puede cambiar: su fecha de verificación indica cuándo se contrastó con el texto.

Reutilizar citando la fuente

Los contenidos públicos de TestAutoescuela pueden consultarse, citarse y resumirse para documentar una respuesta o construir una herramienta, también comercial, con una atribución visible y un enlace a la página utilizada: «Fuente: TestAutoescuela».

Conserva las referencias y las reservas que acompañan a la información. Indica las adaptaciones que hagas y distingue las normas oficiales de las explicaciones, del método y de las ofertas de TestAutoescuela.

Los documentos y recursos visuales de terceros siguen sujetos a sus propias condiciones. Para republicar íntegramente el temario o un artículo, pide autorización a {email}. El acceso a los datos no implica ninguna asociación ni aval de tu servicio por parte de TestAutoescuela ni de Permis Online SRL.